summaryrefslogtreecommitdiff
path: root/server/lib
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2014-08-25 13:12:27 -0400
committerJules Laplace <jules@okfoc.us>2014-08-25 13:40:12 -0400
commit099dfd16940c62e931bf01e7f62b7a45f2b8c654 (patch)
treeb10d4dc452d01783619966a43ea10decc75e4344 /server/lib
parent4ef340497ef24bb2ecacb2c9c4106c24515c874f (diff)
collaborators api
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/api/collaborator.js85
-rw-r--r--server/lib/api/index.js1
-rw-r--r--server/lib/auth/mail.js24
-rw-r--r--server/lib/middleware.js29
-rw-r--r--server/lib/schemas/Collaborator.js29
-rw-r--r--server/lib/views.js32
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)
}
}