From aa8d1bb85335ade39e7b199a9d1c3757f1308d80 Mon Sep 17 00:00:00 2001 From: Ritchie Martori Date: Mon, 15 Jul 2013 14:07:17 -0700 Subject: [PATCH] Added bcrypt for password hashing --- lib/models/acl.js | 16 +++++++++++++++- lib/models/model.js | 16 +++++++++++++--- lib/models/user.js | 17 +++++++++++++++-- test/user.test.js | 26 ++++++++++++++++++++++++-- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/lib/models/acl.js b/lib/models/acl.js index d10f2c3c..14a6cf8c 100644 --- a/lib/models/acl.js +++ b/lib/models/acl.js @@ -12,6 +12,20 @@ // Class level permissions +// blog posts +allow: ['owner', 'admin'] to: '*' // allow owner's of posts and admins to do anything +allow: '*' to: ['find', 'read'] // allow everyone to read and find +// comments +allow '*' to: ['find', 'read'] // read aka findById +allow 'user' to: ['create'] +allow ['owner', 'admin'] to: '*' + +// users only section +allow: '*' to: ['find', 'read', 'create'] +allow: 'owner' to: ['*.destroy', '*.save'] + // scopes -// URL level permissions \ No newline at end of file +// URL level permissions + + diff --git a/lib/models/model.js b/lib/models/model.js index e987404f..b77433ad 100644 --- a/lib/models/model.js +++ b/lib/models/model.js @@ -2,16 +2,21 @@ * Module Dependencies. */ -var ModelBuilder = require('jugglingdb').ModelBuilder +var ModelBuilder = require('jugglingdb').ModelBuilder; var modeler = new ModelBuilder(); /** - * Extends from the built in `asteroid.Model` type. + * Define the built in asteroid.Model. */ var Model = module.exports = modeler.define('model'); Model.shared = true; + +/*! + * For **remoting**. Construct objects when calling instance methods remotely. + */ + Model.sharedCtor = function (data, id, fn) { var ModelCtor = this; @@ -87,12 +92,17 @@ Model.afterRemote = function (name, fn) { } /*! - * Setup extended models. + * Called when a model is extended. */ Model.setup = function () { var ModelCtor = this; + // each model has its + // own access control + // list + Model.acl = []; + ModelCtor.sharedCtor.accepts = [ {arg: 'data', type: 'object', http: {source: 'body'}}, {arg: 'id', type: 'any', http: {source: 'url'}} diff --git a/lib/models/user.js b/lib/models/user.js index 9b1e8e9f..e57cc140 100644 --- a/lib/models/user.js +++ b/lib/models/user.js @@ -5,7 +5,9 @@ var Model = require('../asteroid').Model , asteroid = require('../asteroid') , path = require('path') + , SALT_WORK_FACTOR = 10 , crypto = require('crypto') + , bcrypt = require('bcrypt') , passport = require('passport') , LocalStrategy = require('passport-local').Strategy; @@ -128,8 +130,14 @@ User.logout = function (sid, fn) { */ User.prototype.hasPassword = function (plain, fn) { - // TODO - bcrypt - fn(null, this.password === plain); + if(this.password && plain) { + bcrypt.compare(plain, this.password, function(err, isMatch) { + if(err) return fn(err); + fn(null, isMatch); + }); + } else { + fn(null, false); + } } /** @@ -233,6 +241,11 @@ User.confirm = function (uid, token, redirect, fn) { }); } +User.setter.password = function (plain) { + var salt = bcrypt.genSaltSync(this.constructor.settings.saltWorkFactor || SALT_WORK_FACTOR); + this._password = bcrypt.hashSync(plain, salt); +} + /** * Setup an extended user model. */ diff --git a/test/user.test.js b/test/user.test.js index 91f02166..bed60fd5 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -162,11 +162,33 @@ describe('User', function(){ describe('user.hasPassword(plain, fn)', function(){ it('Determine if the password matches the stored password.', function(done) { var u = new User({username: 'foo', password: 'bar'}); - u.hasPassword('bar', function (err, isMatch) { assert(isMatch, 'password doesnt match'); done(); - }); + }); + }); + + it('should match a password after it is changed', function(done) { + User.create({email: 'foo@baz.net', username: 'bat', password: 'baz'}, function (err, user) { + User.findById(user.id, function (err, foundUser) { + assert(foundUser); + foundUser.hasPassword('baz', function (err, isMatch) { + assert(isMatch); + foundUser.password = 'baz2'; + foundUser.save(function (err, updatedUser) { + updatedUser.hasPassword('baz2', function (err, isMatch) { + assert(isMatch); + User.findById(user.id, function (err, uu) { + uu.hasPassword('baz2', function (err, isMatch) { + assert(isMatch); + done(); + }); + }); + }); + }); + }); + }); + }); }); });