diff options
| author | Jules Laplace <jules@okfoc.us> | 2014-08-25 13:12:27 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2014-08-25 13:40:12 -0400 |
| commit | 099dfd16940c62e931bf01e7f62b7a45f2b8c654 (patch) | |
| tree | b10d4dc452d01783619966a43ea10decc75e4344 /server/lib | |
| parent | 4ef340497ef24bb2ecacb2c9c4106c24515c874f (diff) | |
collaborators api
Diffstat (limited to 'server/lib')
| -rw-r--r-- | server/lib/api/collaborator.js | 85 | ||||
| -rw-r--r-- | server/lib/api/index.js | 1 | ||||
| -rw-r--r-- | server/lib/auth/mail.js | 24 | ||||
| -rw-r--r-- | server/lib/middleware.js | 29 | ||||
| -rw-r--r-- | server/lib/schemas/Collaborator.js | 29 | ||||
| -rw-r--r-- | server/lib/views.js | 32 |
6 files changed, 179 insertions, 21 deletions
diff --git a/server/lib/api/collaborator.js b/server/lib/api/collaborator.js new file mode 100644 index 0000000..4b55f09 --- /dev/null +++ b/server/lib/api/collaborator.js @@ -0,0 +1,85 @@ +/* jshint node: true */ + +var _ = require('lodash'), + util = require('../util'), + upload = require('../upload'), + config = require('../../../config.json'), + Collaborator = require('../schemas/Collaborator'), + Project = require('../schemas/Project'); + +var collaborator = { + + join: function(req, res){ + var nonce = req.query.nonce + if (! nonce || ! nonce.length) { return res.json({ error: "invalid invite code" }) } + Collaborator.findOne({ nonce: nonce }, function(err, collaborator){ + if (err || ! collaborator) { return res.json({ error: "can't find collaborator" }) } + collaborator.user_id = req.user.user_id + collaborator.nonce = "" + collaborator.save(function(err, collaborator){ + Project.findOne({ _id: collaborator.project_id }, function(err, project){ + if (err || ! project) { return res.json({ error: err }) } + res.redirect("/project/" + project.slug + "/edit") + }) + }) + }) + }, + + // + + index: function(req, res){ + if (! req.project) { + return res.json({ error: "can't find project" }) + } + if (req.project.user_id !== req.user._id) { return res.json({ error: "insufficient permission" }) } + Collaborator.find({ project_id: req.project._id }, function(err, collaborators){ + var user_ids = _.pluck(collaborators, "user_id").filter(function(id){ return !! id }) + User.find({ _id: user_ids }, "username displayName photo", function(err, users){ + if (! user_ids) { + return res.json(collaborators) + } + var userIndex = _.indexBy(users, '_id') + collaborators = collaborators.map(function(collaborator){ + var obj = collaborator.toObject() + obj.user = userIndex[ obj.user_id ] + return obj + }) + res.json(collaborators) + }) + }) + }, + + create: function(req, res){ + if (! req.project) { + return res.json({ error: "can't find project" }) + } + var data = util.cleanQuery(req.body) + delete data.user_id + + data.project_id = req.project._id + + Collaborator.makeNonce(function(nonce){ + data.nonce = nonce + new Collaborator(data).save(function(err, collaborator){ + if (err || ! collaborator) { return res.json({ error: err }) } + auth.mail.forgotPassword(req.project, req.user, collaborator, function(){ + res.json(collaborator) + }) + }) + }) + }, + + destroy: function(req, res){ + if (! req.project) { + return res.json({ error: "can't find project" }) + } + if (req.project.user_id !== req.user._id) { + return res.json({ error: "insufficient permission" }) + } + Collaborator.remove({ _id: _id }, function(err){ + res.json({ status: "OK" }) + }) + } +} + +module.exports = collaborator diff --git a/server/lib/api/index.js b/server/lib/api/index.js index bfe3632..ad86daa 100644 --- a/server/lib/api/index.js +++ b/server/lib/api/index.js @@ -6,6 +6,7 @@ var api = { media: require('./media'), profile: require('./profile'), projects: require('./projects'), + collaborator: require('./collaborator'), } module.exports = api diff --git a/server/lib/auth/mail.js b/server/lib/auth/mail.js index a4abccd..0211325 100644 --- a/server/lib/auth/mail.js +++ b/server/lib/auth/mail.js @@ -10,7 +10,7 @@ var mail = { templates: {}, init: function(){ - var names = ["welcome","password"].forEach(function(name){ + var names = ["welcome","password","collaborator"].forEach(function(name){ mail.templates[name] = {}; var types = ["text","html"].forEach(function(type){ fs.readFile("views/mail/" + name + "." + type + ".ejs", function(err, data){ @@ -62,6 +62,28 @@ var mail = { mail.send(message, cb) console.log("sent password email to", user.email) }, + + collaborator: function(project, user, collaborator, cb){ + var data = { + projectSlug: project.slug, + projectName: project.name, + nonce: collaborator.nonce, + username: user.username, + } + + var message = { + text: mail.templates.collaborator.text(data), + from: mail.from, + to: collaborator.email, + subject: "Join " + data.username + " on " + data.projectName, + attachment: [ + { data: mail.templates.collaborator.html(data), alternative: true }, + ] + } + mail.send(message, cb) + console.log("sent collaborator email to", user.email) + }, + } module.exports = mail diff --git a/server/lib/middleware.js b/server/lib/middleware.js index 27b9c04..9d6236a 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -5,6 +5,7 @@ var passport = require('passport'), _ = require('lodash'), config = require('../../config.json'), User = require('./schemas/User'), + Collaborator = require('./schemas/Collaborator'), Project = require('./schemas/Project'); @@ -36,7 +37,7 @@ var middleware = { ensureLocals: function (req, res, next) { res.locals.token = req.csrfToken(); res.locals.logged_in = req.isAuthenticated() - res.locals.user = req.user || { id: undefined } + res.locals.user = req.user || { _id: undefined } res.locals.config = config res.locals.profile = null res.locals.opt = {} @@ -63,8 +64,32 @@ var middleware = { req.project = null next() } - } + }, + + ensureIsCollaborator: function(req, res, next) { + req.isCollaborator = false + req.isOwner = false + if (! req.user || ! req.project) { + next() + } + else if (String(req.user._id) === String(req.project.user_id)) { + req.isOwner = true + next() + } + else { + Collaborator.findOne({ user_id: req.user._id, project_id: req.project._id }, function(err, collab) { + if (err || ! collab) { + next() + } + else { + req.isCollaborator = true + next() + } + }) + } + }, + } module.exports = middleware diff --git a/server/lib/schemas/Collaborator.js b/server/lib/schemas/Collaborator.js new file mode 100644 index 0000000..79e3287 --- /dev/null +++ b/server/lib/schemas/Collaborator.js @@ -0,0 +1,29 @@ +/* jshint node: true */ + +var mongoose = require('mongoose'), + _ = require('lodash'), + config = require('../../../config.json'), + util = require('../util'); + +var CollaboratorSchema = new mongoose.Schema({ + email: { type: String, required: true}, + project_id: { type: mongoose.Schema.ObjectId, index: true }, + user_id: { type: mongoose.Schema.ObjectId, index: true }, + nonce: { + type: String, + default: "", + }, + created_at: { type: Date }, + updated_at: { type: Date }, +}) + +CollaboratorSchema.statics.makeNonce = function(cb){ + crypto.pseudoRandomBytes(256, function (err, buf){ + var shasum = crypto.createHash('sha1') + shasum.update(buf) + cb( shasum.digest('hex') ) + }) +} + +module.exports = exports = mongoose.model('collaborator', CollaboratorSchema); +exports.schema = CollaboratorSchema; diff --git a/server/lib/views.js b/server/lib/views.js index b776582..4faf80f 100644 --- a/server/lib/views.js +++ b/server/lib/views.js @@ -3,6 +3,7 @@ var User = require('./schemas/User'), Project = require('./schemas/Project'), Documentation = require('./schemas/Documentation'), + Collaborator = require('./schemas/Collaborator'), config = require('../../config'), marked = require('marked'), util = require('./util'), @@ -19,29 +20,24 @@ marked.setOptions({ var views = {} +views.editor_new = function (req, res) { + if (! req.user) { + res.redirect('/') + } + else { + res.render('editor') + } +} + views.editor = function (req, res) { - if (! req.user && ! req.project) { + if (! req.project) { res.redirect('/') } - else if (! req.user || (req.project && String(req.user._id) !== String(req.project.user_id))) { - User.findOne({ _id: req.project.user_id }, function(err, user) { - if (err || ! user) { - console.error(err) - res.redirect('/') - return - } - res.render('reader', { - name: util.sanitize(req.project.name), - description: util.sanitize(req.project.description), - date: moment(req.project.updated_at).format("M/DD/YYYY"), - author: user.displayName, - authorlink: "/profile/" + user.username, - noui: !! (req.query.noui === '1'), - }) - }) + else if (req.isCollaborator || req.isOwner) { + res.render('editor') } else { - res.render('editor') + views.reader(req, res) } } |
