diff --git a/.gitignore b/.gitignore index 8d87b1d2..6adcd013 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules/* +npm-debug.log diff --git a/app/controllers/comments.js b/app/controllers/comments.js index bf652d96..ea52f901 100644 --- a/app/controllers/comments.js +++ b/app/controllers/comments.js @@ -1,4 +1,18 @@ var mongoose = require('mongoose'); +var utils = require('../../lib/utils'); + +/** + * Load comment + */ + +exports.load = function (req, res, next, id) { + var tweet = req.tweet + utils.findByParam(tweet.comments, { id: id }, function (err, comment) { + if (err) return next(err); + req.comment = comment; + next(); + }); +}; // ### Create Comment exports.create = function (req, res) { diff --git a/app/controllers/tweets.js b/app/controllers/tweets.js index 85af1374..817556a8 100644 --- a/app/controllers/tweets.js +++ b/app/controllers/tweets.js @@ -85,21 +85,23 @@ exports.destroy = function (req, res) { }; + exports.index = function (req, res) { - var page = req.param('page') > 0 ? req.param('page'):0; - var perPage = 15; + var page = (req.param('page') > 0 ? req.param('page'):1) - 1; + var perPage = 15; var options = { perPage: perPage, page: page }; - Tweet.list(options, function (err, tweets) { + + Tweet.list(options, function(err, tweets) { if (err) return res.render('500'); Tweet.count().exec(function (err, count) { res.render('tweets/index', { - title: 'List of tweets', + title: 'List of Tweets', tweets: tweets, - page: page, - pages: count/perPage + page: page + 1, + pages: Math.ceil(count / perPage) }); }); }); diff --git a/app/models/tweets.js b/app/models/tweets.js index 8fac1697..816db8e9 100644 --- a/app/models/tweets.js +++ b/app/models/tweets.js @@ -1,7 +1,9 @@ var mongoose = require('mongoose'), env = process.env.NODE_ENV || 'development', config = require('../../config/config')[env], - Schema = mongoose.Schema; + Schema = mongoose.Schema, + utils = require('../../lib/utils') + // Getters and Setters var getTags = function (tags) { @@ -77,6 +79,16 @@ TweetSchema.methods = { user: user._id }); this.save(cb); + }, + + removeComment: function (commentId, cb) { + var index = utils.indexof(this.comments, { id: commentId }); + if (~index) { + this.comments.splice(index, 1); + } else { + return cb('not found'); + } + this.save(cb); } }; @@ -86,7 +98,7 @@ TweetSchema.statics = { // Load tweets load: function (id, cb) { this.findOne({ _id: id }) - .populate('user', 'name email') + .populate('user', 'name email username') .populate('comments.user') .exec(cb); }, @@ -96,7 +108,7 @@ TweetSchema.statics = { var criteria = options.criteria || {}; this.find(criteria) - .populate('user', 'name') + .populate('user', 'name username') .sort({'createdAt': -1}) .limit(options.perPage) .skip(options.perPage * options.page) diff --git a/app/views/comments/comment.jade b/app/views/comments/comment.jade index 58ce4d60..04f394b6 100644 --- a/app/views/comments/comment.jade +++ b/app/views/comments/comment.jade @@ -1,7 +1,7 @@ if (comment && comment.user) .comment - a(href="/users/"+ comment.user) #{comment.user} + a(href="/users/"+ comment.user)= comment.user | :  != comment.body .date= formatDate(tweet.createdAt, "%b %d, %Y at %I:%M %p") diff --git a/app/views/tweets/index.jade b/app/views/tweets/index.jade index 2a4593c9..f6651994 100644 --- a/app/views/tweets/index.jade +++ b/app/views/tweets/index.jade @@ -43,7 +43,11 @@ block content .row .col-lg-6.pull-left h5 - a(href="/users/"+tweet.user._id)=tweet.user.name + - var name = tweet.user.name ? tweet.user.name : tweet.user.username + + //- if (tweet.user.name) + //- a(href="/users/"+tweet.user._id)=tweet.user.name + a(href="/users/"+tweet.user._id)= name .col-lg-5.date .pull-right = formatDate(tweet.createdAt, "%b %d, %Y at %I:%M %p") @@ -60,3 +64,7 @@ block content include ../comments/comment hr include ../comments/form + + - if (pages > 1) + ul.pagination + != createPagination(pages, page) diff --git a/config/middlewares/authorization.js b/config/middlewares/authorization.js index 908056d8..cc809d16 100644 --- a/config/middlewares/authorization.js +++ b/config/middlewares/authorization.js @@ -34,4 +34,21 @@ exports.tweet = { }; +/** + * Comment authorization routing middleware + */ + +exports.comment = { + hasAuthorization: function (req, res, next) { + // if the current user is comment owner or article owner + // give them authority to delete + if (req.user.id === req.comment.user.id || req.user.id === req.article.user.id) { + next(); + } else { + req.flash('info', 'You are not authorized'); + res.redirect('/articles/' + req.article.id); + } + } +}; + diff --git a/config/routes.js b/config/routes.js index 683ae40c..6ea8fac8 100644 --- a/config/routes.js +++ b/config/routes.js @@ -1,5 +1,8 @@ var async = require('async'); + + + module.exports = function (app, passport, auth) { var users = require('../app/controllers/users'); app.get('/login', users.login); @@ -34,6 +37,7 @@ module.exports = function (app, passport, auth) { //comment routes var comments = require('../app/controllers/comments'); app.post('/tweets/:id/comments', auth.requiresLogin, comments.create); + app.get('/tweets/:id/comments', auth.requiresLogin, comments.create); app.del('/tweets/:id/comments', auth.requiresLogin, comments.destroy); /** diff --git a/lib/utils.js b/lib/utils.js new file mode 100644 index 00000000..52e6f66d --- /dev/null +++ b/lib/utils.js @@ -0,0 +1,78 @@ +/** + * Formats mongoose errors into proper array + * + * @param {Array} errors + * @return {Array} + * @api public + */ + +exports.errors = function (errors) { + var keys = Object.keys(errors) + var errs = [] + + // if there is no validation error, just display a generic error + if (!keys) { + return ['Oops! There was an error'] + } + + keys.forEach(function (key) { + errs.push(errors[key].message) + }) + + return errs +} + +/** + * Index of object within an array + * + * @param {Array} arr + * @param {Object} obj + * @return {Number} + * @api public + */ + +exports.indexof = function (arr, obj) { + var index = -1; // not found initially + var keys = Object.keys(obj); + // filter the collection with the given criterias + var result = arr.filter(function (doc, idx) { + // keep a counter of matched key/value pairs + var matched = 0; + + // loop over criteria + for (var i = keys.length - 1; i >= 0; i--) { + if (doc[keys[i]] === obj[keys[i]]) { + matched++; + + // check if all the criterias are matched + if (matched === keys.length) { + index = idx; + return idx; + } + } + }; + }); + return index; +} + +/** + * Find object in an array of objects that matches a condition + * + * @param {Array} arr + * @param {Object} obj + * @param {Function} cb - optional + * @return {Object} + * @api public + */ + +exports.findByParam = function (arr, obj, cb) { + var index = exports.indexof(arr, obj) + if (~index && typeof cb === 'function') { + return cb(undefined, arr[index]) + } else if (~index && !cb) { + return arr[index] + } else if (!~index && typeof cb === 'function') { + return cb('not found') + } + // else undefined is returned +} diff --git a/package.json b/package.json index 1258b339..0950a9a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nwitter", "description": "A twitter demo app in nodejs", - "version": "0.0.1-49", + "version": "0.0.1-54", "repository": "https://github.com/vinitcool76/node-twitter", "private": false, "author": "Vinit Kumar (http://vinitkumar.me)",