remove passport dependencies, user and document cruft
This commit is contained in:
parent
9a7dc3c138
commit
de45c9b411
@ -19,11 +19,6 @@
|
||||
"method-override": "~1.0.0",
|
||||
"mongoose": "~3.8.8",
|
||||
"morgan": "~1.0.0",
|
||||
"passport": "~0.2.0",
|
||||
"passport-facebook": "latest",
|
||||
"passport-google-oauth": "latest",
|
||||
"passport-local": "~0.1.6",
|
||||
"passport-twitter": "latest",
|
||||
"serve-favicon": "~2.0.1",
|
||||
"temp": "^0.8.1"
|
||||
},
|
||||
|
@ -1,274 +0,0 @@
|
||||
/**
|
||||
* Using Rails-like standard naming convention for endpoints.
|
||||
* GET /documents -> index
|
||||
* POST /documents -> create
|
||||
* GET /documents/:id -> show
|
||||
* PUT /documents/:id -> update
|
||||
* DELETE /documents/:id -> destroy
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var Document = require('./document.model');
|
||||
var Revision = require('./revision.model');
|
||||
var wdiff = require('../../components/wdiff');
|
||||
var mongoose = require('mongoose');
|
||||
|
||||
|
||||
// Get a list of all documents
|
||||
exports.index = function(req, res) {
|
||||
Document
|
||||
.find()
|
||||
.populate('owner', '_id name')
|
||||
.populate('currentRevision', '_id state created')
|
||||
.populate('revisions', '_id state created description')
|
||||
.exec(function (err, documents) {
|
||||
if(err) { return handleError(res, err); }
|
||||
return res.json(200, documents);
|
||||
});
|
||||
};
|
||||
|
||||
// Get a list of all documents
|
||||
exports.indexForUser = function(req, res) {
|
||||
Document
|
||||
.find({owner: req.params.userid})
|
||||
.populate('owner', '_id name')
|
||||
.populate('revisions', '_id state created description')
|
||||
.populate('currentRevision', '_id state created')
|
||||
.exec(function (err, documents) {
|
||||
if(err) { return handleError(res, err); }
|
||||
return res.json(200, documents);
|
||||
});
|
||||
};
|
||||
|
||||
// Get a single document
|
||||
exports.show = function(req, res) {
|
||||
Document
|
||||
.findById(req.params.id)
|
||||
.populate('owner', '_id name')
|
||||
.populate('currentRevision', '_id state created description content')
|
||||
.populate('revisions', '_id state created description')
|
||||
.exec(function (err, document) {
|
||||
if(err) { return handleError(res, err); }
|
||||
if(!document) { return res.send(404); }
|
||||
return res.json(document);
|
||||
});
|
||||
};
|
||||
|
||||
// Creates a new document with the current user as owner
|
||||
exports.create = function(req, res) {
|
||||
//we do not allow the api client to change the owner willy-nilly!
|
||||
//can this be set in the schema somehow?
|
||||
if (req.body.owner) { delete req.body.owner; }
|
||||
|
||||
//nor document id
|
||||
if (req.body._id) { delete req.body._id; }
|
||||
|
||||
//the client cant add revisions either
|
||||
if (req.body.revisions) { delete req.body.revisions; }
|
||||
if (req.body.currentRevision) { delete req.body.currentRevision; }
|
||||
|
||||
//add the current user to the document object
|
||||
var document = _.merge(req.body, {owner: req.user._id});
|
||||
|
||||
|
||||
//and add to the db
|
||||
Document.create(document, function(err, document) {
|
||||
if(err) { return handleError(res, err); }
|
||||
|
||||
//create an initial, empty revision
|
||||
var revision = {document: document, status: 'empty', content:''};
|
||||
Revision.create(revision, function(err, revision) {
|
||||
if(err) { return handleError(res, err); }
|
||||
|
||||
//then add that revision back to the document
|
||||
document.currentRevision = revision;
|
||||
document.revisions = [revision];
|
||||
|
||||
//save the document and return
|
||||
document.save(function (err, document) {
|
||||
if(err) { return handleError(res, err); }
|
||||
return res.json(201, document);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
// Updates an existing document in the DB.
|
||||
exports.update = function(req, res) {
|
||||
//we don't allow the id to be updated
|
||||
//!!! do we even need to worry about this? Prolly not!
|
||||
if(req.body._id) { delete req.body._id; }
|
||||
|
||||
//??? should we allow the revisions to be updated here? Prolly not
|
||||
if (req.body.revisions) { delete req.body.revisions; }
|
||||
|
||||
Document.findById(req.params.id, function (err, document) {
|
||||
if (err) { return handleError(res, err); }
|
||||
if(!document) { return res.send(404); }
|
||||
|
||||
// require user authentication
|
||||
if (! mongoose.Types.ObjectId(document.owner).equals(req.user._id))
|
||||
{return res.send(401);}
|
||||
|
||||
//do it
|
||||
var updated = _.merge(document, req.body);
|
||||
updated.save(function (err) {
|
||||
if (err) { return handleError(res, err); }
|
||||
return res.json(200, document);
|
||||
});
|
||||
});
|
||||
};
|
||||
*/
|
||||
|
||||
// Deletes a document from the DB.
|
||||
exports.destroy = function(req, res) {
|
||||
Document.findById(req.params.id, function (err, document) {
|
||||
if(err) { return handleError(res, err); }
|
||||
if(!document) { return res.send(404); }
|
||||
|
||||
// require user authentication
|
||||
if (! mongoose.Types.ObjectId(document.owner).equals(req.user._id))
|
||||
{return res.send(401);}
|
||||
|
||||
//do it
|
||||
document.remove(function(err) {
|
||||
if(err) { return handleError(res, err); }
|
||||
return res.send(204);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Get a list of all revisions for a document
|
||||
exports.indexRevisionsForDocument = function(req, res) {
|
||||
Revision
|
||||
.find({document: req.params.id})
|
||||
.populate('owner', '_id name')
|
||||
.populate('document', '_id title currentRevision revisions')
|
||||
.populate('document.revisions', '_id')
|
||||
.exec(function (err, revisions) {
|
||||
if(err) { return handleError(res, err); }
|
||||
if(!revisions) { return res.send(404); }
|
||||
|
||||
return res.json(200, revisions);
|
||||
});
|
||||
};
|
||||
|
||||
// Show a revision by id
|
||||
exports.showRevision = function(req, res) {
|
||||
Revision
|
||||
.findById(req.params.revisionid)
|
||||
.populate('owner', '_id name')
|
||||
.populate('document', '_id title currentRevision revisions')
|
||||
.populate('document.revisions', '_id')
|
||||
.exec(function (err, revision) {
|
||||
if(err) { return handleError(res, err); }
|
||||
if(!revision) { return res.send(404); }
|
||||
|
||||
//ensure this revision actually belongs to the specified document
|
||||
if (! mongoose.Types.ObjectId(revision.document._id).equals(req.params.id))
|
||||
{return res.status(403).send("Mismatch between revision id and document id.");}
|
||||
|
||||
|
||||
// ??? require user authentication
|
||||
//if (! mongoose.Types.ObjectId(document.owner).equals(req.user._id))
|
||||
// {return res.send(401);}
|
||||
|
||||
return res.json(revision);
|
||||
});
|
||||
};
|
||||
|
||||
// Create a new revision and add it to a document (with the current user as owner)
|
||||
// This can only be performed by the user who owns the document
|
||||
exports.createRevision = function(req, res) {
|
||||
//we do not allow the api client to change the owner willy-nilly!
|
||||
//can this be set in the schema somehow?
|
||||
if (req.body.owner) { delete req.body.owner; }
|
||||
|
||||
//similarly the document
|
||||
if (req.body.document) { delete req.body.document; }
|
||||
|
||||
//and the date
|
||||
if (req.body.created) { delete req.body.created; }
|
||||
|
||||
//and the id!
|
||||
if (req.body._id) { delete req.body._id; }
|
||||
|
||||
console.log(req.body);
|
||||
|
||||
//get the record for the parent document
|
||||
Document.findById(req.params.id).exec(function(err, document){
|
||||
if (err) { return handleError(res, err); }
|
||||
if(!document) { return res.send(404); }
|
||||
|
||||
// require user authentication
|
||||
if (! mongoose.Types.ObjectId(document.owner).equals(req.user._id))
|
||||
{return res.send(401);}
|
||||
|
||||
console.log('---');
|
||||
console.log(document);
|
||||
|
||||
//set the owner and document fields for the revision
|
||||
var revision = _.merge(req.body, {owner: req.user, document: document});
|
||||
|
||||
console.log('---');
|
||||
console.log(revision);
|
||||
|
||||
//create the record
|
||||
Revision.create(revision, function (err, revision) {
|
||||
if(err) { return handleError(res, err); }
|
||||
if (!revision) {return handleError(res, "Unknown error creating revision");}
|
||||
|
||||
console.log('---');
|
||||
console.log(revision);
|
||||
|
||||
//and update the document
|
||||
document.revisions.push(revision);
|
||||
document.currentRevision = revision;
|
||||
document.save(function (err) {
|
||||
if (err) { return handleError(res, err); }
|
||||
return res.json(200, revision);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//compares two revisions with wdiff
|
||||
exports.wdiff = function(req, res) {
|
||||
Revision
|
||||
.findById(req.params.revisionida)
|
||||
.populate('document', 'title')
|
||||
.exec(function (err, revisiona) {
|
||||
if(err) { return handleError(res, err); }
|
||||
if(!revisiona) { return res.send(404); }
|
||||
|
||||
|
||||
Revision
|
||||
.findById(req.params.revisionidb)
|
||||
.populate('document', 'title')
|
||||
.exec(function (err, revisionb) {
|
||||
if(err) { return handleError(res, err); }
|
||||
if(!revisionb) { return res.send(404); }
|
||||
|
||||
//??? do we care if both revisions have the same document?
|
||||
//??? if they both have the same user?
|
||||
//??? if the current user is the owner?
|
||||
|
||||
wdiff(revisiona.content, revisionb.content, true, function(err, result){
|
||||
if(err) { return handleError(res, err); }
|
||||
|
||||
result.a = revisiona;
|
||||
result.b = revisionb;
|
||||
|
||||
res.json(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function handleError(res, err) {
|
||||
return res.send(500, err);
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var mongoose = require('mongoose'),
|
||||
Schema = mongoose.Schema;
|
||||
|
||||
var DocumentSchema = new Schema({
|
||||
title: String,
|
||||
owner: {type: Schema.Types.ObjectId, ref: 'User'},
|
||||
|
||||
//is it necessary to have the revisions list?
|
||||
//yes - it maintains the order
|
||||
revisions : [{ type: Schema.Types.ObjectId, ref: 'Revision' }],
|
||||
|
||||
//do we need this? - current revision is just revisions[n-1]
|
||||
currentRevision : {type: Schema.Types.ObjectId, ref: 'Revision'}
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Document', DocumentSchema);
|
@ -1,30 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var controller = require('./document.controller');
|
||||
var auth = require('../../auth/auth.service');
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
router.get('/', controller.index);
|
||||
router.get('/owner/:userid', controller.indexForUser);
|
||||
|
||||
router.get('/:id', controller.show);
|
||||
router.post('/', auth.isAuthenticated(), controller.create);
|
||||
//router.put('/:id', auth.isAuthenticated(), controller.update);
|
||||
//router.patch('/:id', auth.isAuthenticated(), controller.update);
|
||||
router.delete('/:id', auth.isAuthenticated(), controller.destroy);
|
||||
|
||||
router.get('/:id/revisions', controller.indexRevisionsForDocument);
|
||||
router.get('/:id/revisions/:revisionid', controller.showRevision);
|
||||
|
||||
|
||||
router.post('/:id/revisions', auth.isAuthenticated(), controller.createRevision);
|
||||
/*
|
||||
router.put('/:id/revisions/:revisionid', auth.isAuthenticated(), controller.updateRevision);
|
||||
router.patch('/:id/revisions/:revisionid', auth.isAuthenticated(), ontroller.updateRevision);
|
||||
router.delete('/:id/revisions/:revisionid', auth.isAuthenticated(), controller.destroyRevision);
|
||||
*/
|
||||
router.get('/wdiff/:revisionida/:revisionidb', controller.wdiff);
|
||||
|
||||
module.exports = router;
|
@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var mongoose = require('mongoose'),
|
||||
Schema = mongoose.Schema;
|
||||
|
||||
var RevisionSchema = new Schema({
|
||||
state: String,
|
||||
//This property is denormalized for efficient querying
|
||||
owner: {type: Schema.Types.ObjectId, ref: 'User'},
|
||||
created: {type: Date, default: Date.now},
|
||||
description: String,
|
||||
content: String,
|
||||
|
||||
document : {type: Schema.Types.ObjectId, ref: 'Document'}
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Revision', RevisionSchema);
|
@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var controller = require('./user.controller');
|
||||
var config = require('../../config/environment');
|
||||
var auth = require('../../auth/auth.service');
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
router.get('/', auth.hasRole('admin'), controller.index);
|
||||
router.delete('/:id', auth.hasRole('admin'), controller.destroy);
|
||||
router.get('/me', auth.isAuthenticated(), controller.me);
|
||||
router.put('/:id/password', auth.isAuthenticated(), controller.changePassword);
|
||||
router.get('/:id', auth.isAuthenticated(), controller.show);
|
||||
router.post('/', controller.create);
|
||||
|
||||
module.exports = router;
|
@ -1,101 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var User = require('./user.model');
|
||||
var passport = require('passport');
|
||||
var config = require('../../config/environment');
|
||||
var jwt = require('jsonwebtoken');
|
||||
|
||||
var validationError = function(res, err) {
|
||||
return res.json(422, err);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get list of users
|
||||
* restriction: 'admin'
|
||||
*/
|
||||
exports.index = function(req, res) {
|
||||
User.find({}, '-salt -hashedPassword', function (err, users) {
|
||||
if(err) return res.send(500, err);
|
||||
res.json(200, users);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new user
|
||||
*/
|
||||
exports.create = function (req, res, next) {
|
||||
var newUser = new User(req.body);
|
||||
newUser.provider = 'local';
|
||||
newUser.role = 'user';
|
||||
newUser.save(function(err, user) {
|
||||
if (err) return validationError(res, err);
|
||||
var token = jwt.sign({_id: user._id }, config.secrets.session, { expiresInMinutes: 60*5 });
|
||||
res.json({ token: token });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a single user
|
||||
*/
|
||||
exports.show = function (req, res, next) {
|
||||
var userId = req.params.id;
|
||||
|
||||
User.findById(userId, function (err, user) {
|
||||
if (err) return next(err);
|
||||
if (!user) return res.send(401);
|
||||
res.json(user.profile);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a user
|
||||
* restriction: 'admin'
|
||||
*/
|
||||
exports.destroy = function(req, res) {
|
||||
User.findByIdAndRemove(req.params.id, function(err, user) {
|
||||
if(err) return res.send(500, err);
|
||||
return res.send(204);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Change a users password
|
||||
*/
|
||||
exports.changePassword = function(req, res, next) {
|
||||
var userId = req.user._id;
|
||||
var oldPass = String(req.body.oldPassword);
|
||||
var newPass = String(req.body.newPassword);
|
||||
|
||||
User.findById(userId, function (err, user) {
|
||||
if(user.authenticate(oldPass)) {
|
||||
user.password = newPass;
|
||||
user.save(function(err) {
|
||||
if (err) return validationError(res, err);
|
||||
res.send(200);
|
||||
});
|
||||
} else {
|
||||
res.send(403);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get my info
|
||||
*/
|
||||
exports.me = function(req, res, next) {
|
||||
var userId = req.user._id;
|
||||
User.findOne({
|
||||
_id: userId
|
||||
}, '-salt -hashedPassword', function(err, user) { // don't ever give out the password or salt
|
||||
if (err) return next(err);
|
||||
if (!user) return res.json(401);
|
||||
res.json(user);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Authentication callback
|
||||
*/
|
||||
exports.authCallback = function(req, res, next) {
|
||||
res.redirect('/');
|
||||
};
|
@ -1,149 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var mongoose = require('mongoose');
|
||||
var Schema = mongoose.Schema;
|
||||
var crypto = require('crypto');
|
||||
var authTypes = ['github', 'twitter', 'facebook', 'google'];
|
||||
|
||||
var UserSchema = new Schema({
|
||||
name: String,
|
||||
email: { type: String, lowercase: true },
|
||||
role: {
|
||||
type: String,
|
||||
default: 'user'
|
||||
},
|
||||
hashedPassword: String,
|
||||
provider: String,
|
||||
salt: String,
|
||||
facebook: {},
|
||||
twitter: {},
|
||||
google: {},
|
||||
github: {}
|
||||
});
|
||||
|
||||
/**
|
||||
* Virtuals
|
||||
*/
|
||||
UserSchema
|
||||
.virtual('password')
|
||||
.set(function(password) {
|
||||
this._password = password;
|
||||
this.salt = this.makeSalt();
|
||||
this.hashedPassword = this.encryptPassword(password);
|
||||
})
|
||||
.get(function() {
|
||||
return this._password;
|
||||
});
|
||||
|
||||
// Public profile information
|
||||
UserSchema
|
||||
.virtual('profile')
|
||||
.get(function() {
|
||||
return {
|
||||
'name': this.name,
|
||||
'role': this.role
|
||||
};
|
||||
});
|
||||
|
||||
// Non-sensitive info we'll be putting in the token
|
||||
UserSchema
|
||||
.virtual('token')
|
||||
.get(function() {
|
||||
return {
|
||||
'_id': this._id,
|
||||
'role': this.role
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Validations
|
||||
*/
|
||||
|
||||
// Validate empty email
|
||||
UserSchema
|
||||
.path('email')
|
||||
.validate(function(email) {
|
||||
if (authTypes.indexOf(this.provider) !== -1) return true;
|
||||
return email.length;
|
||||
}, 'Email cannot be blank');
|
||||
|
||||
// Validate empty password
|
||||
UserSchema
|
||||
.path('hashedPassword')
|
||||
.validate(function(hashedPassword) {
|
||||
if (authTypes.indexOf(this.provider) !== -1) return true;
|
||||
return hashedPassword.length;
|
||||
}, 'Password cannot be blank');
|
||||
|
||||
// Validate email is not taken
|
||||
UserSchema
|
||||
.path('email')
|
||||
.validate(function(value, respond) {
|
||||
var self = this;
|
||||
this.constructor.findOne({email: value}, function(err, user) {
|
||||
if(err) throw err;
|
||||
if(user) {
|
||||
if(self.id === user.id) return respond(true);
|
||||
return respond(false);
|
||||
}
|
||||
respond(true);
|
||||
});
|
||||
}, 'The specified email address is already in use.');
|
||||
|
||||
var validatePresenceOf = function(value) {
|
||||
return value && value.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pre-save hook
|
||||
*/
|
||||
UserSchema
|
||||
.pre('save', function(next) {
|
||||
if (!this.isNew) return next();
|
||||
|
||||
if (!validatePresenceOf(this.hashedPassword) && authTypes.indexOf(this.provider) === -1)
|
||||
next(new Error('Invalid password'));
|
||||
else
|
||||
next();
|
||||
});
|
||||
|
||||
/**
|
||||
* Methods
|
||||
*/
|
||||
UserSchema.methods = {
|
||||
/**
|
||||
* Authenticate - check if the passwords are the same
|
||||
*
|
||||
* @param {String} plainText
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
authenticate: function(plainText) {
|
||||
return this.encryptPassword(plainText) === this.hashedPassword;
|
||||
},
|
||||
|
||||
/**
|
||||
* Make salt
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
makeSalt: function() {
|
||||
return crypto.randomBytes(16).toString('base64');
|
||||
},
|
||||
|
||||
/**
|
||||
* Encrypt password
|
||||
*
|
||||
* @param {String} password
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
encryptPassword: function(password) {
|
||||
if (!password || !this.salt) return '';
|
||||
var salt = new Buffer(this.salt, 'base64');
|
||||
return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = mongoose.model('User', UserSchema);
|
@ -1,60 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var should = require('should');
|
||||
var app = require('../../app');
|
||||
var User = require('./user.model');
|
||||
|
||||
var user = new User({
|
||||
provider: 'local',
|
||||
name: 'Fake User',
|
||||
email: 'test@test.com',
|
||||
password: 'password'
|
||||
});
|
||||
|
||||
describe('User Model', function() {
|
||||
before(function(done) {
|
||||
// Clear users before testing
|
||||
User.remove().exec().then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
User.remove().exec().then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should begin with no users', function(done) {
|
||||
User.find({}, function(err, users) {
|
||||
users.should.have.length(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail when saving a duplicate user', function(done) {
|
||||
user.save(function() {
|
||||
var userDup = new User(user);
|
||||
userDup.save(function(err) {
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail when saving without an email', function(done) {
|
||||
user.email = '';
|
||||
user.save(function(err) {
|
||||
should.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should authenticate user if password is valid", function() {
|
||||
return user.authenticate('password').should.be.true;
|
||||
});
|
||||
|
||||
it("should not authenticate user if password is invalid", function() {
|
||||
return user.authenticate('blah').should.not.be.true;
|
||||
});
|
||||
});
|
@ -1,12 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var controller = require('./wdiff.controller');
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
router.post('/', controller.compare);
|
||||
router.post('/markdown', controller.compareMarkdown);
|
||||
|
||||
|
||||
module.exports = router;
|
@ -1,47 +0,0 @@
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash'),
|
||||
temp = require('temp'),
|
||||
fs = require('fs'),
|
||||
exec = require('child_process').exec,
|
||||
wdiff = require('../../components/wdiff');
|
||||
|
||||
// Automatically track and cleanup files at exit
|
||||
temp.track();
|
||||
|
||||
exports.compare = function(req, res) {
|
||||
doCompare(req, res, false);
|
||||
};
|
||||
|
||||
exports.compareMarkdown = function(req, res) {
|
||||
doCompare(req, res, true);
|
||||
};
|
||||
|
||||
// Perform a comparison
|
||||
// The request should be a json object with two string fields: 'a' and 'b'
|
||||
function doCompare(req, res, asMarkdown) {
|
||||
|
||||
//check for properly formatted request
|
||||
if (req.headers["content-type"].toLowerCase() != "application/json")
|
||||
return handleError(res, {error: "Content-type must be 'application/json'"});
|
||||
|
||||
if (!req.body.a || !req.body.b)
|
||||
return handleError(res, {error: "Request data should be of the form {a:'text a', b:'text b'}"});
|
||||
|
||||
var a = req.body.a;
|
||||
var b = req.body.b;
|
||||
|
||||
wdiff(a,b,asMarkdown, function(err, result){
|
||||
if (err)
|
||||
return handleError(res, err);
|
||||
|
||||
res.json(result);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function handleError(res, err) {
|
||||
return res.send(500, err);
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var mongoose = require('mongoose');
|
||||
var passport = require('passport');
|
||||
var config = require('../config/environment');
|
||||
var jwt = require('jsonwebtoken');
|
||||
var expressJwt = require('express-jwt');
|
||||
var compose = require('composable-middleware');
|
||||
var User = require('../api/user/user.model');
|
||||
var validateJwt = expressJwt({ secret: config.secrets.session });
|
||||
|
||||
/**
|
||||
* Attaches the user object to the request if authenticated
|
||||
* Otherwise returns 403
|
||||
*/
|
||||
function isAuthenticated() {
|
||||
return compose()
|
||||
// Validate jwt
|
||||
.use(function(req, res, next) {
|
||||
// allow access_token to be passed through query parameter as well
|
||||
if(req.query && req.query.hasOwnProperty('access_token')) {
|
||||
req.headers.authorization = 'Bearer ' + req.query.access_token;
|
||||
}
|
||||
validateJwt(req, res, next);
|
||||
})
|
||||
// Attach user to request
|
||||
.use(function(req, res, next) {
|
||||
User.findById(req.user._id, function (err, user) {
|
||||
if (err) return next(err);
|
||||
if (!user) return res.send(401);
|
||||
|
||||
req.user = user;
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user role meets the minimum requirements of the route
|
||||
*/
|
||||
function hasRole(roleRequired) {
|
||||
if (!roleRequired) throw new Error('Required role needs to be set');
|
||||
|
||||
return compose()
|
||||
.use(isAuthenticated())
|
||||
.use(function meetsRequirements(req, res, next) {
|
||||
if (config.userRoles.indexOf(req.user.role) >= config.userRoles.indexOf(roleRequired)) {
|
||||
next();
|
||||
}
|
||||
else {
|
||||
res.send(403);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a jwt token signed by the app secret
|
||||
*/
|
||||
function signToken(id) {
|
||||
return jwt.sign({ _id: id }, config.secrets.session, { expiresInMinutes: 60*5 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set token cookie directly for oAuth strategies
|
||||
*/
|
||||
function setTokenCookie(req, res) {
|
||||
if (!req.user) return res.json(404, { message: 'Something went wrong, please try again.'});
|
||||
var token = signToken(req.user._id, req.user.role);
|
||||
res.cookie('token', JSON.stringify(token));
|
||||
res.redirect('/');
|
||||
}
|
||||
|
||||
exports.isAuthenticated = isAuthenticated;
|
||||
exports.hasRole = hasRole;
|
||||
exports.signToken = signToken;
|
||||
exports.setTokenCookie = setTokenCookie;
|
@ -1,21 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var passport = require('passport');
|
||||
var auth = require('../auth.service');
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
router
|
||||
.get('/', passport.authenticate('facebook', {
|
||||
scope: ['email', 'user_about_me'],
|
||||
failureRedirect: '/signup',
|
||||
session: false
|
||||
}))
|
||||
|
||||
.get('/callback', passport.authenticate('facebook', {
|
||||
failureRedirect: '/signup',
|
||||
session: false
|
||||
}), auth.setTokenCookie);
|
||||
|
||||
module.exports = router;
|
@ -1,37 +0,0 @@
|
||||
var passport = require('passport');
|
||||
var FacebookStrategy = require('passport-facebook').Strategy;
|
||||
|
||||
exports.setup = function (User, config) {
|
||||
passport.use(new FacebookStrategy({
|
||||
clientID: config.facebook.clientID,
|
||||
clientSecret: config.facebook.clientSecret,
|
||||
callbackURL: config.facebook.callbackURL
|
||||
},
|
||||
function(accessToken, refreshToken, profile, done) {
|
||||
User.findOne({
|
||||
'facebook.id': profile.id
|
||||
},
|
||||
function(err, user) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
if (!user) {
|
||||
user = new User({
|
||||
name: profile.displayName,
|
||||
email: profile.emails[0].value,
|
||||
role: 'user',
|
||||
username: profile.username,
|
||||
provider: 'facebook',
|
||||
facebook: profile._json
|
||||
});
|
||||
user.save(function(err) {
|
||||
if (err) done(err);
|
||||
return done(err, user);
|
||||
});
|
||||
} else {
|
||||
return done(err, user);
|
||||
}
|
||||
})
|
||||
}
|
||||
));
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var passport = require('passport');
|
||||
var auth = require('../auth.service');
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
router
|
||||
.get('/', passport.authenticate('google', {
|
||||
failureRedirect: '/signup',
|
||||
scope: [
|
||||
'https://www.googleapis.com/auth/userinfo.profile',
|
||||
'https://www.googleapis.com/auth/userinfo.email'
|
||||
],
|
||||
session: false
|
||||
}))
|
||||
|
||||
.get('/callback', passport.authenticate('google', {
|
||||
failureRedirect: '/signup',
|
||||
session: false
|
||||
}), auth.setTokenCookie);
|
||||
|
||||
module.exports = router;
|
@ -1,33 +0,0 @@
|
||||
var passport = require('passport');
|
||||
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
|
||||
|
||||
exports.setup = function (User, config) {
|
||||
passport.use(new GoogleStrategy({
|
||||
clientID: config.google.clientID,
|
||||
clientSecret: config.google.clientSecret,
|
||||
callbackURL: config.google.callbackURL
|
||||
},
|
||||
function(accessToken, refreshToken, profile, done) {
|
||||
User.findOne({
|
||||
'google.id': profile.id
|
||||
}, function(err, user) {
|
||||
if (!user) {
|
||||
user = new User({
|
||||
name: profile.displayName,
|
||||
email: profile.emails[0].value,
|
||||
role: 'user',
|
||||
username: profile.username,
|
||||
provider: 'google',
|
||||
google: profile._json
|
||||
});
|
||||
user.save(function(err) {
|
||||
if (err) done(err);
|
||||
return done(err, user);
|
||||
});
|
||||
} else {
|
||||
return done(err, user);
|
||||
}
|
||||
});
|
||||
}
|
||||
));
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var passport = require('passport');
|
||||
var config = require('../config/environment');
|
||||
var User = require('../api/user/user.model');
|
||||
|
||||
// Passport Configuration
|
||||
require('./local/passport').setup(User, config);
|
||||
require('./facebook/passport').setup(User, config);
|
||||
require('./google/passport').setup(User, config);
|
||||
require('./twitter/passport').setup(User, config);
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
router.use('/local', require('./local'));
|
||||
router.use('/facebook', require('./facebook'));
|
||||
router.use('/twitter', require('./twitter'));
|
||||
router.use('/google', require('./google'));
|
||||
|
||||
module.exports = router;
|
@ -1,20 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var passport = require('passport');
|
||||
var auth = require('../auth.service');
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
router.post('/', function(req, res, next) {
|
||||
passport.authenticate('local', function (err, user, info) {
|
||||
var error = err || info;
|
||||
if (error) return res.json(401, error);
|
||||
if (!user) return res.json(404, {message: 'Something went wrong, please try again.'});
|
||||
|
||||
var token = auth.signToken(user._id, user.role);
|
||||
res.json({token: token});
|
||||
})(req, res, next)
|
||||
});
|
||||
|
||||
module.exports = router;
|
@ -1,25 +0,0 @@
|
||||
var passport = require('passport');
|
||||
var LocalStrategy = require('passport-local').Strategy;
|
||||
|
||||
exports.setup = function (User, config) {
|
||||
passport.use(new LocalStrategy({
|
||||
usernameField: 'email',
|
||||
passwordField: 'password' // this is the virtual field on the model
|
||||
},
|
||||
function(email, password, done) {
|
||||
User.findOne({
|
||||
email: email.toLowerCase()
|
||||
}, function(err, user) {
|
||||
if (err) return done(err);
|
||||
|
||||
if (!user) {
|
||||
return done(null, false, { message: 'This email is not registered.' });
|
||||
}
|
||||
if (!user.authenticate(password)) {
|
||||
return done(null, false, { message: 'This password is not correct.' });
|
||||
}
|
||||
return done(null, user);
|
||||
});
|
||||
}
|
||||
));
|
||||
};
|
@ -1,20 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var passport = require('passport');
|
||||
var auth = require('../auth.service');
|
||||
|
||||
var router = express.Router();
|
||||
|
||||
router
|
||||
.get('/', passport.authenticate('twitter', {
|
||||
failureRedirect: '/signup',
|
||||
session: false
|
||||
}))
|
||||
|
||||
.get('/callback', passport.authenticate('twitter', {
|
||||
failureRedirect: '/signup',
|
||||
session: false
|
||||
}), auth.setTokenCookie);
|
||||
|
||||
module.exports = router;
|
@ -1,35 +0,0 @@
|
||||
exports.setup = function (User, config) {
|
||||
var passport = require('passport');
|
||||
var TwitterStrategy = require('passport-twitter').Strategy;
|
||||
|
||||
passport.use(new TwitterStrategy({
|
||||
consumerKey: config.twitter.clientID,
|
||||
consumerSecret: config.twitter.clientSecret,
|
||||
callbackURL: config.twitter.callbackURL
|
||||
},
|
||||
function(token, tokenSecret, profile, done) {
|
||||
User.findOne({
|
||||
'twitter.id_str': profile.id
|
||||
}, function(err, user) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
if (!user) {
|
||||
user = new User({
|
||||
name: profile.displayName,
|
||||
username: profile.username,
|
||||
role: 'user',
|
||||
provider: 'twitter',
|
||||
twitter: profile._json
|
||||
});
|
||||
user.save(function(err) {
|
||||
if (err) return done(err);
|
||||
return done(err, user);
|
||||
});
|
||||
} else {
|
||||
return done(err, user);
|
||||
}
|
||||
});
|
||||
}
|
||||
));
|
||||
};
|
@ -41,27 +41,10 @@ var all = {
|
||||
}
|
||||
},
|
||||
|
||||
facebook: {
|
||||
clientID: process.env.FACEBOOK_ID || 'id',
|
||||
clientSecret: process.env.FACEBOOK_SECRET || 'secret',
|
||||
callbackURL: (process.env.DOMAIN || '') + '/auth/facebook/callback'
|
||||
},
|
||||
|
||||
twitter: {
|
||||
clientID: process.env.TWITTER_ID || 'id',
|
||||
clientSecret: process.env.TWITTER_SECRET || 'secret',
|
||||
callbackURL: (process.env.DOMAIN || '') + '/auth/twitter/callback'
|
||||
},
|
||||
|
||||
google: {
|
||||
clientID: process.env.GOOGLE_ID || 'id',
|
||||
clientSecret: process.env.GOOGLE_SECRET || 'secret',
|
||||
callbackURL: (process.env.DOMAIN || '') + '/auth/google/callback'
|
||||
}
|
||||
};
|
||||
|
||||
// Export the config object based on the NODE_ENV
|
||||
// ==============================================
|
||||
module.exports = _.merge(
|
||||
all,
|
||||
require('./' + process.env.NODE_ENV + '.js') || {});
|
||||
require('./' + process.env.NODE_ENV + '.js') || {});
|
||||
|
@ -14,7 +14,6 @@ var cookieParser = require('cookie-parser');
|
||||
var errorHandler = require('errorhandler');
|
||||
var path = require('path');
|
||||
var config = require('./environment');
|
||||
var passport = require('passport');
|
||||
var session = require('express-session');
|
||||
var mongoStore = require('connect-mongo')(session);
|
||||
var mongoose = require('mongoose');
|
||||
@ -39,7 +38,7 @@ module.exports = function(app) {
|
||||
saveUninitialized: true,
|
||||
store: new mongoStore({ mongoose_connection: mongoose.connection })
|
||||
}));
|
||||
|
||||
|
||||
if ('production' === env) {
|
||||
app.use(favicon(path.join(config.root, 'public', 'favicon.ico')));
|
||||
app.use(express.static(path.join(config.root, 'public')));
|
||||
@ -55,4 +54,4 @@ module.exports = function(app) {
|
||||
app.use(morgan('dev'));
|
||||
app.use(errorHandler()); // Error handler - has to be last
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -4,81 +4,3 @@
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var Document = require('../api/document/document.model');
|
||||
var Revision = require('../api/document/revision.model');
|
||||
var User = require('../api/user/user.model');
|
||||
|
||||
|
||||
var oldUser;
|
||||
var testUser;
|
||||
var testDocument;
|
||||
var testRevisionIds = [];
|
||||
|
||||
|
||||
Document.find({owner:null}).remove();
|
||||
Revision.find({owner:null}).remove();
|
||||
|
||||
|
||||
User.findOne({email:'test@test.com'}).exec()
|
||||
.then(function(user) {
|
||||
oldUser = user;
|
||||
|
||||
console.log('removing test revisions');
|
||||
Revision.find({owner: user}).remove().exec();
|
||||
|
||||
console.log('removing test documents');
|
||||
Document.find({owner: user}).remove().exec();
|
||||
|
||||
console.log('removing test user');
|
||||
User.find({email:'test@test.com'}).remove().exec();
|
||||
}, function (err) { console.log('err: '+err)})
|
||||
|
||||
.then(function() {
|
||||
console.log('creating test user');
|
||||
return User.create({
|
||||
provider: 'local',
|
||||
name: 'Test User',
|
||||
email: 'test@test.com',
|
||||
password: 'test'
|
||||
});
|
||||
}, function (err) { console.log('err: '+err)})
|
||||
|
||||
.then(function(user) {
|
||||
testUser = user;
|
||||
console.log('creating test document');
|
||||
return Document.create({
|
||||
owner: testUser,
|
||||
title: "test document",
|
||||
});
|
||||
}, function (err) { console.log('err: '+err)})
|
||||
|
||||
.then(function(document) {
|
||||
testDocument = document;
|
||||
console.log('creating test revisions');
|
||||
return Revision.create({
|
||||
owner: testUser,
|
||||
state: "rough draft",
|
||||
description: "test revision a",
|
||||
content: "blah, blah, blah",
|
||||
document: testDocument
|
||||
}, {
|
||||
owner: testUser,
|
||||
state: "final draft",
|
||||
description: "test revision b",
|
||||
content: "Blah, blah, blah!",
|
||||
document: testDocument
|
||||
}, function (err, revisionA, revisionB) {
|
||||
console.log('updating document with revisions');
|
||||
testRevisionIds = [revisionA, revisionB];
|
||||
testDocument.currentRevision = revisionB;
|
||||
testDocument.revisions.push(revisionA);
|
||||
testDocument.revisions.push(revisionB);
|
||||
return testDocument.save();
|
||||
});
|
||||
}, function (err) { console.log('err: '+err)})
|
||||
|
||||
.then(function() {
|
||||
console.log('finished seeding db');
|
||||
}, function (err) { console.log('err: '+err)})
|
||||
;
|
@ -11,14 +11,9 @@ module.exports = function(app) {
|
||||
// Insert routes below
|
||||
|
||||
app.use('/api/compare', require('./api/comparison'));
|
||||
app.use('/api/documents', require('./api/document'));
|
||||
app.use('/api/wdiff', require('./api/wdiff'));
|
||||
app.use('/api/users', require('./api/user'));
|
||||
|
||||
app.use('/auth', require('./auth'));
|
||||
|
||||
// All undefined asset or api routes should return a 404
|
||||
app.route('/:url(api|auth|components|app|bower_components|assets)/*')
|
||||
app.route('/:url(api|components|app|bower_components|assets)/*')
|
||||
.get(errors[404]);
|
||||
|
||||
// All other routes should redirect to the index.html
|
||||
|
Loading…
Reference in New Issue
Block a user