/* jshint node: true */ var User = require('../schemas/User'), Project = require('../schemas/Project'), Media = require('../schemas/Media'), Collaborator = require('../schemas/Collaborator'), config = require('../../../config'), middleware = require('../middleware'), util = require('../util'), _ = require('lodash'), moment = require('moment'); var staff = module.exports = { fields: { user: "_id username displayName photo created_at updated_at last_seen created_ip last_ip", project: "_id name slug user_id privacy created_at updated_at", }, defaults: { user: { _id: "", username: "", displayName: "", created_at: "", updated_at: "", created_ip: "", last_ip: "", }, }, middleware: { ensureUsers: function(req, res, next){ var paginationInfo = res.locals.pagination = {} var criteria = req.criteria || {} var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) var offset = paginationInfo.offset = Number(req.query.offset) || 0 var sort paginationInfo.sort = req.query.sort paginationInfo.sortOptions = ["date", "last_seen", "username"] switch (req.query.sort) { case 'date': sort = {'created_at': -1} break case 'last_seen': sort = {'last_seen': -1} break case 'username': default: sort = {'username': 1} paginationInfo.sort = "username" break } User.find(criteria) .select(staff.fields.user) .sort(sort) .skip(offset) .limit(limit) .exec(function (err, users) { res.locals.users = users.map(staff.helpers.user) next() }) }, ensureRecentUsers: function(req, res, next){ var dreq = { query: { sort: 'last_seen', limit: 20, offset: 0 } } staff.middleware.ensureUsers(dreq, res, next) }, ensureProjects: function(req, res, next){ var paginationInfo = res.locals.pagination = {} var criteria = req.criteria || {} var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) var offset = paginationInfo.offset = Number(req.query.offset) || 0 var sort paginationInfo.sort = req.query.sort paginationInfo.sortOptions = ["date", "name"] switch (req.query.sort) { default: case 'date': sort = {'updated_at': -1} break case 'name': paginationInfo.sort = "name" sort = {'slug': 1} break } Project.find(criteria) .select(staff.fields.project) .sort(sort) .skip(offset) .limit(limit) .exec(function (err, projects) { res.locals.projects = projects.map(staff.helpers.project) next() }) }, ensureMedia: function(req, res, next){ var paginationInfo = res.locals.pagination = {} var criteria = req.criteria || {} var limit = paginationInfo.limit = Math.min( Number(req.query.limit) || 50, 200 ) var offset = paginationInfo.offset = Number(req.query.offset) || 0 var sort paginationInfo.sort = req.query.sort paginationInfo.sortOptions = ["date"] switch (req.query.sort) { default: case 'date': paginationInfo.sort = "date" sort = {'created_at': -1} break } Media.find(criteria) // .select(staff.fields.media) .sort(sort) .skip(offset) .limit(limit) .exec(function (err, media) { res.locals.media = media.map(staff.helpers.media) next() }) }, ensureRecentProjects: function(req, res, next){ var dreq = { params: { sort: 'created_at', limit: 20, offset: 0 } } staff.middleware.ensureProjects(dreq, res, next) }, ensureProjectsUsers: function(req, res, next){ if (! res.locals.projects || ! res.locals.projects.length) { return next() } staff.middleware.ensureObjectsUsers(res.locals.projects, next) }, ensureMediaUsers: function(req, res, next){ if (! res.locals.media || ! res.locals.media.length) { return next() } staff.middleware.ensureObjectsUsers(res.locals.media, next) }, ensureMediaUser: function(req, res, next){ if (! res.locals.media) { return next() } staff.middleware.ensureObjectsUsers([ res.locals.media ], function(){ res.locals.mediaUser = res.locals.media.User next() }) }, ensureObjectsUsers: function(objects, next){ if (! objects) { return next () } var dedupe = {}, user_ids objects.forEach(function(obj){ dedupe[ obj.user_id ] = dedupe[ obj.user_id ] || [] dedupe[ obj.user_id ].push(obj) }) user_ids = _.keys(dedupe) User.find({ _id: { $in: user_ids } }) .select(staff.fields.user) .exec(function (err, users) { if (! users) { return next () } users.forEach(function(user){ dedupe[user._id].forEach(function(obj){ obj.user = user }) }) next() }) }, ensureProfile: function(req, res, next){ var username = req.params.username if (username) { User.findOne({ username: username }, function (err, user) { if (user) { res.locals.profile = req.method == "GET" ? staff.helpers.user(user) : user } else { res.locals.profile = null } next() }) } else { res.locals.profile = null next() } }, ensureSingleMedia: function(req, res, next){ var id = req.params.id if (id) { Media.findOne({ _id: id }, function (err, media) { if (media) { res.locals.media = req.method == "GET" ? staff.helpers.media(media) : media } else { res.locals.media = null } next() }) } else { res.locals.media = null next() } }, ensureUsersCount: function(req, res, next){ User.count({}, function(err, count){ res.locals.userCount = count || 0 next() }) }, ensureProjectsCount: function(req, res, next){ Project.count({}, function(err, count){ res.locals.projectCount = count || 0 next() }) }, ensureMediaCount: function(req, res, next){ Media.count({}, function(err, count){ res.locals.mediaCount = count || 0 next() }) }, ensureProfileProjectCount: function(req, res, next){ if (! res.locals.profile) { return next() } Project.count({ user_id: res.locals.profile._id}, function(err, count){ res.locals.profile.projectCount = count || 0 next() }) }, ensureProfileMediaCount: function(req, res, next){ if (! res.locals.profile) { return next() } Media.count({ user_id: res.locals.profile._id}, function(err, count){ res.locals.profile.mediaCount = count || 0 next() }) }, ensureProfileProjects: function(req, res, next){ if (! res.locals.profile) { return next() } Project.find({ user_id: res.locals.profile._id }, staff.fields.project, function(err, projects){ res.locals.projects = projects.map(staff.helpers.project) next() }) }, ensureProfileMedia: function(req, res, next){ if (! res.locals.profile) { return next() } req.criteria = { user_id: res.locals.profile._id } staff.middleware.ensureMedia(req, res, next) }, ensureProject: function(req, res, next){ res.locals.project = req.project next() }, ensureProjectUser: function(req, res, next){ if (! res.locals.project) { return next() } User.findOne({ _id: res.locals.project.user_id }, staff.fields.user, function(err, user){ res.locals.projectUser = staff.helpers.user(user) || staff.defaults.user next() }) }, ensureProjectCollaborators: function(req, res, next){ if (! res.locals.project) { res.locals.collaborators = [] return next() } Collaborator.find({ project_id: res.locals.project._id}, function(err, collaborators){ res.locals.collaborators = collaborators || [] next() }) }, }, helpers: { user: function(user){ user = user.toObject() user.last_seen = moment( user.last_seen || user.updated_at || user.created_at ).fromNow() user.created_ip = util.num2ip( user.created_ip ) user.last_ip = util.num2ip( user.last_ip ) return user }, project: function(project){ project = project.toObject() project.date = moment( project.updated_at || project.created_at ).format("M/DD/YYYY hh:mm a") project.user = {} return project }, media: function(media){ media = media.toObject() media.date = moment( media.updated_at || media.created_at ).format("M/DD/YYYY hh:mm a") media.user = {} media.shortUrl = media.url.replace(/^http.:\/\//,"") return media } }, route: function(app){ app.get('/staff', middleware.ensureAuthenticated, middleware.ensureIsStaff, staff.middleware.ensureRecentUsers, staff.middleware.ensureUsersCount, staff.middleware.ensureProjectsCount, staff.middleware.ensureMediaCount, staff.index ); // // users app.get('/staff/users', middleware.ensureAuthenticated, middleware.ensureIsStaff, staff.middleware.ensureUsersCount, staff.middleware.ensureUsers, staff.users.index ); app.get('/staff/users/:username', middleware.ensureAuthenticated, middleware.ensureIsStaff, staff.middleware.ensureProfile, staff.middleware.ensureProfileProjectCount, staff.middleware.ensureProfileMediaCount, staff.middleware.ensureProfileProjects, staff.users.show ); app.get('/staff/users/:username/media', middleware.ensureAuthenticated, middleware.ensureIsStaff, staff.middleware.ensureProfile, staff.middleware.ensureProfileMedia, staff.middleware.ensureProfileMediaCount, staff.users.media ); app.put('/staff/users/:username/bless', middleware.ensureAuthenticated, middleware.ensureIsStaff, staff.middleware.ensureProfile, staff.users.bless ); if (app.get('env') === 'development') { app.get('/staff/authorize', middleware.ensureAuthenticated, staff.users.blessSelf ); } // // projects app.get('/staff/projects', middleware.ensureAuthenticated, middleware.ensureIsStaff, staff.middleware.ensureProjectsCount, staff.middleware.ensureProjects, staff.middleware.ensureProjectsUsers, staff.projects.index ); app.get('/staff/projects/:slug', middleware.ensureAuthenticated, middleware.ensureIsStaff, middleware.ensureProject, staff.middleware.ensureProject, staff.middleware.ensureProjectUser, staff.middleware.ensureProjectCollaborators, staff.projects.show ); app.put('/staff/projects/:slug/feature', middleware.ensureAuthenticated, middleware.ensureIsStaff, middleware.ensureProject, staff.middleware.ensureProject, staff.projects.feature ); // // media app.get('/staff/media', middleware.ensureAuthenticated, middleware.ensureIsStaff, staff.middleware.ensureMediaCount, staff.middleware.ensureMedia, staff.middleware.ensureMediaUsers, staff.media.index ); app.get('/staff/media/:id', middleware.ensureAuthenticated, middleware.ensureIsStaff, staff.middleware.ensureSingleMedia, staff.middleware.ensureMediaUser, staff.media.show ); }, paginate: function(req, res){ var info = res.locals.pagination info.query = "sort=" + info.sort + "&limit=" + info.limit info.first_page = 0 info.last_page = Math.max(0, info.max - info.limit) info.sortOptions = info.sortOptions if (info.offset > 0) { info.prev_page = Math.max(0, info.offset - info.limit) } else { info.prev_page = -1 } if (info.count == info.limit && info.offset + info.limit < info.max) { info.next_page = info.offset + info.limit } else { info.next_page = -1 } }, index: function(req, res){ res.render('staff/index') }, // /staff/users/ // /staff/users/:username users: { index: function(req, res){ res.locals.pagination.count = res.locals.users.length res.locals.pagination.max = res.locals.userCount staff.paginate(req, res) res.render('staff/users/index') }, show: function(req, res){ if (res.locals.profile) { res.render('staff/users/show', { profileJSON: util.escape( JSON.stringify( res.locals.profile ) ) }) } else { res.render('staff/users/show_404') } }, media: function(req, res){ if (res.locals.profile) { res.locals.pagination.count = res.locals.media.length res.locals.pagination.max = res.locals.profile.mediaCount staff.paginate(req, res) res.render('staff/users/media') } else { res.render('staff/users/show_404') } }, blessSelf: function(req, res){ req.user.isStaff = true req.user.save(function(err, user){ res.json({ state: user.isStaff }) }) }, bless: function(req, res){ res.locals.profile.isStaff = req.body.state == "true" res.locals.profile.save(function(err, user){ res.json({ state: user.isStaff }) }) }, }, // /staff/projects/ // /staff/projects/:name projects: { index: function(req, res){ res.locals.pagination.count = res.locals.projects.length res.locals.pagination.max = res.locals.projectCount staff.paginate(req, res) res.render('staff/projects/index') }, show: function(req, res){ if (res.locals.project) { res.render('staff/projects/show', { projectJSON: util.escape( JSON.stringify( res.locals.project ) ), projectUserJSON: util.escape( JSON.stringify( res.locals.projectUser ) ), collaboratorsJSON: util.escape( JSON.stringify( res.locals.collaborators ) ), }) } else { res.render('staff/projects/show_404') } }, feature: function(req, res){ res.locals.project.featured = req.body.state == "true" res.locals.project.save(function(err, project){ res.json({ state: project.featured }) }) }, }, media: { index: function(req, res){ res.locals.pagination.count = res.locals.media.length res.locals.pagination.max = res.locals.mediaCount staff.paginate(req, res) res.render('staff/media/index') }, show: function(req, res){ if (res.locals.media) { res.render('staff/media/show', { mediaJSON: util.escape( JSON.stringify( res.locals.media ) ), mediaUserJSON: util.escape( JSON.stringify( res.locals.mediaUser ) ), }) } else { res.render('staff/media/show_404') } }, } }