diff options
Diffstat (limited to 'week-7/Final4/blog/routes')
| -rw-r--r-- | week-7/Final4/blog/routes/content.js | 214 | ||||
| -rw-r--r-- | week-7/Final4/blog/routes/error.js | 9 | ||||
| -rw-r--r-- | week-7/Final4/blog/routes/index.js | 47 | ||||
| -rw-r--r-- | week-7/Final4/blog/routes/session.js | 170 |
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; |
