+
+
+
+ `;
+ return htmlTemplate;
+}
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'ui', 'index.html'));
});
-app.get('/ui/style.css', function (req, res) {
- res.sendFile(path.join(__dirname, 'ui', 'style.css'));
+
+function hash (input, salt) {
+ // How do we create a hash?
+ var hashed = crypto.pbkdf2Sync(input, salt, 10000, 512, 'sha512');
+ return ["pbkdf2", "10000", salt, hashed.toString('hex')].join('$');
+}
+
+
+app.get('/hash/:input', function(req, res) {
+ var hashedString = hash(req.params.input, 'this-is-some-random-string');
+ res.send(hashedString);
+});
+
+app.post('/create-user', function (req, res) {
+ // username, password
+ // {"username": "tanmai", "password": "password"}
+ // JSON
+ var username = req.body.username;
+ var password = req.body.password;
+ var salt = crypto.randomBytes(128).toString('hex');
+ var dbString = hash(password, salt);
+ pool.query('INSERT INTO "user" (username, password) VALUES ($1, $2)', [username, dbString], function (err, result) {
+ if (err) {
+ res.status(500).send(err.toString());
+ } else {
+ res.send('User successfully created: ' + username);
+ }
+ });
+});
+
+app.post('/login', function (req, res) {
+ var username = req.body.username;
+ var password = req.body.password;
+
+ pool.query('SELECT * FROM "user" WHERE username = $1', [username], function (err, result) {
+ if (err) {
+ res.status(500).send(err.toString());
+ } else {
+ if (result.rows.length === 0) {
+ res.status(403).send('username/password is invalid');
+ } else {
+ // Match the password
+ var dbString = result.rows[0].password;
+ var salt = dbString.split('$')[2];
+ var hashedPassword = hash(password, salt); // Creating a hash based on the password submitted and the original salt
+ if (hashedPassword === dbString) {
+
+ // Set the session
+ req.session.auth = {userId: result.rows[0].id};
+ // set cookie with a session id
+ // internally, on the server side, it maps the session id to an object
+ // { auth: {userId }}
+
+ res.send('credentials correct!');
+
+ } else {
+ res.status(403).send('username/password is invalid');
+ }
+ }
+ }
+ });
+});
+
+app.get('/check-login', function (req, res) {
+ if (req.session && req.session.auth && req.session.auth.userId) {
+ // Load the user object
+ pool.query('SELECT * FROM "user" WHERE id = $1', [req.session.auth.userId], function (err, result) {
+ if (err) {
+ res.status(500).send(err.toString());
+ } else {
+ res.send(result.rows[0].username);
+ }
+ });
+ } else {
+ res.status(400).send('You are not logged in');
+ }
+});
+
+app.get('/logout', function (req, res) {
+ delete req.session.auth;
+ res.send('Logged out!
Back to home');
+});
+
+var pool = new Pool(config);
+
+app.get('/get-articles', function (req, res) {
+ // make a select request
+ // return a response with the results
+ pool.query('SELECT * FROM article ORDER BY date DESC', function (err, result) {
+ if (err) {
+ res.status(500).send(err.toString());
+ } else {
+ res.send(JSON.stringify(result.rows));
+ }
+ });
+});
+
+app.get('/get-comments/:articleName', function (req, res) {
+ // make a select request
+ // return a response with the results
+ pool.query('SELECT comment.*, "user".username FROM article, comment, "user" WHERE article.title = $1 AND article.id = comment.article_id AND comment.user_id = "user".id ORDER BY comment.timestamp DESC', [req.params.articleName], function (err, result) {
+ if (err) {
+ res.status(500).send(err.toString());
+ } else {
+ res.send(JSON.stringify(result.rows));
+ }
+ });
+});
+
+app.post('/submit-comment/:articleName', function (req, res) {
+ // Check if the user is logged in
+ if (req.session && req.session.auth && req.session.auth.userId) {
+ // First check if the article exists and get the article-id
+ pool.query('SELECT * from article where title = $1', [req.params.articleName], function (err, result) {
+ if (err) {
+ res.status(500).send(err.toString());
+ } else {
+ if (result.rows.length === 0) {
+ res.status(400).send('Article not found');
+ } else {
+ var articleId = result.rows[0].id;
+ // Now insert the right comment for this article
+ pool.query(
+ "INSERT INTO comment (comment, article_id, user_id) VALUES ($1, $2, $3)",
+ [req.body.comment, articleId, req.session.auth.userId],
+ function (err, result) {
+ if (err) {
+ res.status(500).send(err.toString());
+ } else {
+ res.status(200).send('Comment inserted!')
+ }
+ });
+ }
+ }
+ });
+ } else {
+ res.status(403).send('Only logged in users can comment');
+ }
+});
+
+app.get('/articles/:articleName', function (req, res) {
+ // SELECT * FROM article WHERE title = '\'; DELETE WHERE a = \'asdf'
+ pool.query("SELECT * FROM article WHERE title = $1", [req.params.articleName], function (err, result) {
+ if (err) {
+ res.status(500).send(err.toString());
+ } else {
+ if (result.rows.length === 0) {
+ res.status(404).send('Article not found');
+ } else {
+ var articleData = result.rows[0];
+ res.send(createTemplate(articleData));
+ }
+ }
+ });
});
-app.get('/ui/madi.png', function (req, res) {
- res.sendFile(path.join(__dirname, 'ui', 'madi.png'));
+app.get('/ui/:fileName', function (req, res) {
+ res.sendFile(path.join(__dirname, 'ui', req.params.fileName));
});
diff --git a/ui/article.js b/ui/article.js
new file mode 100644
index 0000000000..d86ab239f9
--- /dev/null
+++ b/ui/article.js
@@ -0,0 +1,100 @@
+// Eg: coco98.imad.hasura-app.io/articles/article-one will result in article-one
+var currentArticleTitle = window.location.pathname.split('/')[2];
+
+function loadCommentForm () {
+ var commentFormHtml = `
+
Submit a comment
+
+
+
+
+ `;
+ document.getElementById('comment_form').innerHTML = commentFormHtml;
+
+ // Submit username/password to login
+ var submit = document.getElementById('submit');
+ submit.onclick = function () {
+ // Create a request object
+ var request = new XMLHttpRequest();
+
+ // Capture the response and store it in a variable
+ request.onreadystatechange = function () {
+ if (request.readyState === XMLHttpRequest.DONE) {
+ // Take some action
+ if (request.status === 200) {
+ // clear the form & reload all the comments
+ document.getElementById('comment_text').value = '';
+ loadComments();
+ } else {
+ alert('Error! Could not submit comment');
+ }
+ submit.value = 'Submit';
+ }
+ };
+
+ // Make the request
+ var comment = document.getElementById('comment_text').value;
+ request.open('POST', '/submit-comment/' + currentArticleTitle, true);
+ request.setRequestHeader('Content-Type', 'application/json');
+ request.send(JSON.stringify({comment: comment}));
+ submit.value = 'Submitting...';
+
+ };
+}
+
+function loadLogin () {
+ // Check if the user is already logged in
+ var request = new XMLHttpRequest();
+ request.onreadystatechange = function () {
+ if (request.readyState === XMLHttpRequest.DONE) {
+ if (request.status === 200) {
+ loadCommentForm(this.responseText);
+ }
+ }
+ };
+
+ request.open('GET', '/check-login', true);
+ request.send(null);
+}
+
+function escapeHTML (text)
+{
+ var $text = document.createTextNode(text);
+ var $div = document.createElement('div');
+ $div.appendChild($text);
+ return $div.innerHTML;
+}
+
+function loadComments () {
+ // Check if the user is already logged in
+ var request = new XMLHttpRequest();
+ request.onreadystatechange = function () {
+ if (request.readyState === XMLHttpRequest.DONE) {
+ var comments = document.getElementById('comments');
+ if (request.status === 200) {
+ var content = '';
+ var commentsData = JSON.parse(this.responseText);
+ for (var i=0; i< commentsData.length; i++) {
+ var time = new Date(commentsData[i].timestamp);
+ content += `
+
${escapeHTML(commentsData[i].comment)}
+
+ ${commentsData[i].username} - ${time.toLocaleTimeString()} on ${time.toLocaleDateString()}
+
+
`;
+ }
+ comments.innerHTML = content;
+ } else {
+ comments.innerHTML('Oops! Could not load comments!');
+ }
+ }
+ };
+
+ request.open('GET', '/get-comments/' + currentArticleTitle, true);
+ request.send(null);
+}
+
+
+// The first thing to do is to check if the user is logged in!
+loadLogin();
+loadComments();
\ No newline at end of file
diff --git a/ui/index.html b/ui/index.html
index 5a28644db4..66b071da62 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -4,12 +4,26 @@
-
-
-
-
-
- Hi! I am your webapp.
+
+
+
+
+
About Me
+
+ Hi. My name is Tanmai Gopal
+ I work at Hasura
+
${escapeHTML(commentsData[i].comment)}
+