summaryrefslogtreecommitdiff
path: root/week-7/Final4/blog/routes
diff options
context:
space:
mode:
Diffstat (limited to 'week-7/Final4/blog/routes')
-rw-r--r--week-7/Final4/blog/routes/content.js214
-rw-r--r--week-7/Final4/blog/routes/error.js9
-rw-r--r--week-7/Final4/blog/routes/index.js47
-rw-r--r--week-7/Final4/blog/routes/session.js170
4 files changed, 440 insertions, 0 deletions
diff --git a/week-7/Final4/blog/routes/content.js b/week-7/Final4/blog/routes/content.js
new file mode 100644
index 0000000..6e7491c
--- /dev/null
+++ b/week-7/Final4/blog/routes/content.js
@@ -0,0 +1,214 @@
+var PostsDAO = require('../posts').PostsDAO
+ , sanitize = require('validator').sanitize; // Helper to sanitize form input
+
+/* The ContentHandler must be constructed with a connected db */
+function ContentHandler (db) {
+ "use strict";
+
+ var posts = new PostsDAO(db);
+
+ this.displayMainPage = function(req, res, next) {
+ "use strict";
+
+ posts.getPosts(10, function(err, results) {
+ "use strict";
+
+ if (err) return next(err);
+
+ return res.render('blog_template', {
+ title: 'blog homepage',
+ username: req.username,
+ myposts: results
+ });
+ });
+ }
+
+ this.displayMainPageByTag = function(req, res, next) {
+ "use strict";
+
+ var tag = req.params.tag;
+
+ posts.getPostsByTag(tag, 10, function(err, results) {
+ "use strict";
+
+ if (err) return next(err);
+
+ return res.render('blog_template', {
+ title: 'blog homepage',
+ username: req.username,
+ myposts: results
+ });
+ });
+ }
+
+ this.displayPostByPermalink = function(req, res, next) {
+ "use strict";
+
+ var permalink = req.params.permalink;
+
+ posts.getPostByPermalink(permalink, function(err, post) {
+ "use strict";
+
+ if (err) return next(err);
+
+ if (!post) return res.redirect("/post_not_found");
+
+ // init comment form fields for additional comment
+ var comment = {'name': req.username, 'body': "", 'email': ""}
+
+ return res.render('entry_template', {
+ title: 'blog post',
+ username: req.username,
+ post: post,
+ comment: comment,
+ errors: ""
+ });
+ });
+ }
+
+ this.handleNewComment = function(req, res, next) {
+ "use strict";
+ var name = req.body.commentName;
+ var email = req.body.commentEmail;
+ var body = req.body.commentBody;
+ var permalink = req.body.permalink;
+
+ // Override the comment with our actual user name if found
+ if (req.username) {
+ name = req.username;
+ }
+
+ if (!name || !body) {
+ // user did not fill in enough information
+
+ posts.getPostByPermalink(permalink, function(err, post) {
+ "use strict";
+
+ if (err) return next(err);
+
+ if (!post) return res.redirect("/post_not_found");
+
+ // init comment form fields for additional comment
+ var comment = {'name': name, 'body': "", 'email': ""}
+
+ var errors = "Post must contain your name and an actual comment."
+ return res.render('entry_template', {
+ title: 'blog post',
+ username: req.username,
+ post: post,
+ comment: comment,
+ errors: errors
+ });
+ });
+
+ return;
+ }
+
+ // even if there is no logged in user, we can still post a comment
+ posts.addComment(permalink, name, email, body, function(err, updated) {
+ "use strict";
+
+ if (err) return next(err);
+
+ if (updated == 0) return res.redirect("/post_not_found");
+
+ return res.redirect("/post/" + permalink);
+ });
+ }
+
+ this.displayPostNotFound = function(req, res, next) {
+ "use strict";
+ return res.send('Sorry, post not found', 404);
+ }
+
+ this.displayNewPostPage = function(req, res, next) {
+ "use strict";
+
+ if (!req.username) return res.redirect("/login");
+
+ return res.render('newpost_template', {
+ subject: "",
+ body: "",
+ errors: "",
+ tags: "",
+ username: req.username
+ });
+ }
+
+ function extract_tags(tags) {
+ "use strict";
+
+ var cleaned = [];
+
+ var tags_array = tags.split(',');
+
+ for (var i = 0; i < tags_array.length; i++) {
+ if ((cleaned.indexOf(tags_array[i]) == -1) && tags_array[i] != "") {
+ cleaned.push(tags_array[i].replace(/\s/g,''));
+ }
+ }
+
+ return cleaned
+ }
+
+ this.handleNewPost = function(req, res, next) {
+ "use strict";
+
+ var title = req.body.subject
+ var post = req.body.body
+ var tags = req.body.tags
+
+ if (!req.username) return res.redirect("/signup");
+
+ if (!title || !post) {
+ var errors = "Post must contain a title and blog entry";
+ return res.render("newpost_template", {subject:title, username:req.username, body:post, tags:tags, errors:errors});
+ }
+
+ var tags_array = extract_tags(tags)
+
+ // looks like a good entry, insert it escaped
+ var escaped_post = sanitize(post).escape();
+
+ // substitute some <br> for the paragraph breaks
+ var formatted_post = escaped_post.replace(/\r?\n/g,'<br>');
+
+ posts.insertEntry(title, formatted_post, tags_array, req.username, function(err, permalink) {
+ "use strict";
+
+ if (err) return next(err);
+
+ // now redirect to the blog permalink
+ return res.redirect("/post/" + permalink)
+ });
+ }
+
+ this.handleLike = function(req, res, next) {
+ "use strict";
+
+ var permalink = req.body.permalink;
+ permalink = sanitize(permalink).escape();
+
+ var comment_ordinal = req.body.comment_ordinal;
+
+ posts.getPostByPermalink(permalink, function(err, post) {
+ "use strict";
+
+ if (err) return next(err);
+
+ if (!post) return res.redirect("/post_not_found");
+
+ // it all looks good. increment the ordinal
+ posts.incrementLikes(permalink, comment_ordinal, function(err, post) {
+ "use strict";
+
+ if (err) return next(err);
+
+ // now redirect to the blog permalink
+ return res.redirect("/post/" + permalink)
+ });
+ });
+ }
+}
+
+module.exports = ContentHandler;
diff --git a/week-7/Final4/blog/routes/error.js b/week-7/Final4/blog/routes/error.js
new file mode 100644
index 0000000..f50f2b6
--- /dev/null
+++ b/week-7/Final4/blog/routes/error.js
@@ -0,0 +1,9 @@
+// Error handling middleware
+
+exports.errorHandler = function(err, req, res, next) {
+ "use strict";
+ console.error(err.message);
+ console.error(err.stack);
+ res.status(500);
+ res.render('error_template', { error: err });
+}
diff --git a/week-7/Final4/blog/routes/index.js b/week-7/Final4/blog/routes/index.js
new file mode 100644
index 0000000..4586e7b
--- /dev/null
+++ b/week-7/Final4/blog/routes/index.js
@@ -0,0 +1,47 @@
+var SessionHandler = require('./session')
+ , ContentHandler = require('./content')
+ , ErrorHandler = require('./error').errorHandler;
+
+module.exports = exports = function(app, db) {
+
+ var sessionHandler = new SessionHandler(db);
+ var contentHandler = new ContentHandler(db);
+
+ // Middleware to see if a user is logged in
+ app.use(sessionHandler.isLoggedInMiddleware);
+
+ // The main page of the blog
+ app.get('/', contentHandler.displayMainPage);
+
+ // The main page of the blog, filtered by tag
+ app.get('/tag/:tag', contentHandler.displayMainPageByTag);
+
+ // A single post, which can be commented on
+ app.get("/post/:permalink", contentHandler.displayPostByPermalink);
+ app.post('/newcomment', contentHandler.handleNewComment);
+ app.get("/post_not_found", contentHandler.displayPostNotFound);
+
+ // Displays the form allowing a user to add a new post. Only works for logged in users
+ app.get('/newpost', contentHandler.displayNewPostPage);
+ app.post('/newpost', contentHandler.handleNewPost);
+
+ // Used to process a like on a blog post
+ app.post('/like', contentHandler.handleLike);
+
+ // Login form
+ app.get('/login', sessionHandler.displayLoginPage);
+ app.post('/login', sessionHandler.handleLoginRequest);
+
+ // Logout page
+ app.get('/logout', sessionHandler.displayLogoutPage);
+
+ // Welcome page
+ app.get("/welcome", sessionHandler.displayWelcomePage);
+
+ // Signup form
+ app.get('/signup', sessionHandler.displaySignupPage);
+ app.post('/signup', sessionHandler.handleSignup);
+
+ // Error handling middleware
+ app.use(ErrorHandler);
+}
diff --git a/week-7/Final4/blog/routes/session.js b/week-7/Final4/blog/routes/session.js
new file mode 100644
index 0000000..73fe6d9
--- /dev/null
+++ b/week-7/Final4/blog/routes/session.js
@@ -0,0 +1,170 @@
+var UsersDAO = require('../users').UsersDAO
+ , SessionsDAO = require('../sessions').SessionsDAO;
+
+/* The SessionHandler must be constructed with a connected db */
+function SessionHandler (db) {
+ "use strict";
+
+ var users = new UsersDAO(db);
+ var sessions = new SessionsDAO(db);
+
+ this.isLoggedInMiddleware = function(req, res, next) {
+ var session_id = req.cookies.session;
+ sessions.getUsername(session_id, function(err, username) {
+ "use strict";
+
+ if (!err && username) {
+ req.username = username;
+ }
+ return next();
+ });
+ }
+
+ this.displayLoginPage = function(req, res, next) {
+ "use strict";
+ return res.render("login", {username:"", password:"", login_error:""})
+ }
+
+ this.handleLoginRequest = function(req, res, next) {
+ "use strict";
+
+ var username = req.body.username;
+ var password = req.body.password;
+
+ console.log("user submitted username: " + username + " pass: " + password);
+
+ users.validateLogin(username, password, function(err, user) {
+ "use strict";
+
+ if (err) {
+ if (err.no_such_user) {
+ return res.render("login", {username:username, password:"", login_error:"No such user"});
+ }
+ else if (err.invalid_password) {
+ return res.render("login", {username:username, password:"", login_error:"Invalid password"});
+ }
+ else {
+ // Some other kind of error
+ return next(err);
+ }
+ }
+
+ sessions.startSession(user['_id'], function(err, session_id) {
+ "use strict";
+
+ if (err) return next(err);
+
+ res.cookie('session', session_id);
+ return res.redirect('/welcome');
+ });
+ });
+ }
+
+ this.displayLogoutPage = function(req, res, next) {
+ "use strict";
+
+ var session_id = req.cookies.session;
+ sessions.endSession(session_id, function (err) {
+ "use strict";
+
+ // Even if the user wasn't logged in, redirect to home
+ res.cookie('session', '');
+ return res.redirect('/');
+ });
+ }
+
+ this.displaySignupPage = function(req, res, next) {
+ "use strict";
+ res.render("signup", {username:"", password:"",
+ password_error:"",
+ email:"", username_error:"", email_error:"",
+ verify_error :""});
+ }
+
+ function validateSignup(username, password, verify, email, errors) {
+ "use strict";
+ var USER_RE = /^[a-zA-Z0-9_-]{3,20}$/;
+ var PASS_RE = /^.{3,20}$/;
+ var EMAIL_RE = /^[\S]+@[\S]+\.[\S]+$/;
+
+ errors['username_error'] = "";
+ errors['password_error'] = "";
+ errors['verify_error'] = "";
+ errors['email_error'] = "";
+
+ if (!USER_RE.test(username)) {
+ errors['username_error'] = "invalid username. try just letters and numbers";
+ return false;
+ }
+ if (!PASS_RE.test(password)) {
+ errors['password_error'] = "invalid password.";
+ return false;
+ }
+ if (password != verify) {
+ errors['verify_error'] = "password must match";
+ return false;
+ }
+ if (email != "") {
+ if (!EMAIL_RE.test(email)) {
+ errors['email_error'] = "invalid email address";
+ return false;
+ }
+ }
+ return true;
+ }
+
+ this.handleSignup = function(req, res, next) {
+ "use strict";
+
+ var email = req.body.email
+ var username = req.body.username
+ var password = req.body.password
+ var verify = req.body.verify
+
+ // set these up in case we have an error case
+ var errors = {'username': username, 'email': email}
+ if (validateSignup(username, password, verify, email, errors)) {
+ users.addUser(username, password, email, function(err, user) {
+ "use strict";
+
+ if (err) {
+ // this was a duplicate
+ if (err.code == '11000') {
+ errors['username_error'] = "Username already in use. Please choose another";
+ return res.render("signup", errors);
+ }
+ // this was a different error
+ else {
+ return next(err);
+ }
+ }
+
+ sessions.startSession(user['_id'], function(err, session_id) {
+ "use strict";
+
+ if (err) return next(err);
+
+ res.cookie('session', session_id);
+ return res.redirect('/welcome');
+ });
+ });
+ }
+ else {
+ console.log("user did not validate");
+ return res.render("signup", errors);
+ }
+ }
+
+ this.displayWelcomePage = function(req, res, next) {
+ "use strict";
+
+ if (!req.username) {
+ console.log("welcome: can't identify user...redirecting to signup");
+ return res.redirect("/signup");
+ }
+
+ return res.render("welcome", {'username':req.username})
+ }
+}
+
+module.exports = SessionHandler;