Added bcrypt for password hashing
This commit is contained in:
parent
3f7e4b693a
commit
aa8d1bb853
|
@ -12,6 +12,20 @@
|
||||||
|
|
||||||
// Class level permissions
|
// 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
|
// scopes
|
||||||
|
|
||||||
// URL level permissions
|
// URL level permissions
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,21 @@
|
||||||
* Module Dependencies.
|
* Module Dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var ModelBuilder = require('jugglingdb').ModelBuilder
|
var ModelBuilder = require('jugglingdb').ModelBuilder;
|
||||||
var modeler = new 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');
|
var Model = module.exports = modeler.define('model');
|
||||||
|
|
||||||
Model.shared = true;
|
Model.shared = true;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* For **remoting**. Construct objects when calling instance methods remotely.
|
||||||
|
*/
|
||||||
|
|
||||||
Model.sharedCtor = function (data, id, fn) {
|
Model.sharedCtor = function (data, id, fn) {
|
||||||
var ModelCtor = this;
|
var ModelCtor = this;
|
||||||
|
|
||||||
|
@ -87,12 +92,17 @@ Model.afterRemote = function (name, fn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Setup extended models.
|
* Called when a model is extended.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Model.setup = function () {
|
Model.setup = function () {
|
||||||
var ModelCtor = this;
|
var ModelCtor = this;
|
||||||
|
|
||||||
|
// each model has its
|
||||||
|
// own access control
|
||||||
|
// list
|
||||||
|
Model.acl = [];
|
||||||
|
|
||||||
ModelCtor.sharedCtor.accepts = [
|
ModelCtor.sharedCtor.accepts = [
|
||||||
{arg: 'data', type: 'object', http: {source: 'body'}},
|
{arg: 'data', type: 'object', http: {source: 'body'}},
|
||||||
{arg: 'id', type: 'any', http: {source: 'url'}}
|
{arg: 'id', type: 'any', http: {source: 'url'}}
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
var Model = require('../asteroid').Model
|
var Model = require('../asteroid').Model
|
||||||
, asteroid = require('../asteroid')
|
, asteroid = require('../asteroid')
|
||||||
, path = require('path')
|
, path = require('path')
|
||||||
|
, SALT_WORK_FACTOR = 10
|
||||||
, crypto = require('crypto')
|
, crypto = require('crypto')
|
||||||
|
, bcrypt = require('bcrypt')
|
||||||
, passport = require('passport')
|
, passport = require('passport')
|
||||||
, LocalStrategy = require('passport-local').Strategy;
|
, LocalStrategy = require('passport-local').Strategy;
|
||||||
|
|
||||||
|
@ -128,8 +130,14 @@ User.logout = function (sid, fn) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
User.prototype.hasPassword = function (plain, fn) {
|
User.prototype.hasPassword = function (plain, fn) {
|
||||||
// TODO - bcrypt
|
if(this.password && plain) {
|
||||||
fn(null, 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.
|
* Setup an extended user model.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -162,12 +162,34 @@ describe('User', function(){
|
||||||
describe('user.hasPassword(plain, fn)', function(){
|
describe('user.hasPassword(plain, fn)', function(){
|
||||||
it('Determine if the password matches the stored password.', function(done) {
|
it('Determine if the password matches the stored password.', function(done) {
|
||||||
var u = new User({username: 'foo', password: 'bar'});
|
var u = new User({username: 'foo', password: 'bar'});
|
||||||
|
|
||||||
u.hasPassword('bar', function (err, isMatch) {
|
u.hasPassword('bar', function (err, isMatch) {
|
||||||
assert(isMatch, 'password doesnt match');
|
assert(isMatch, 'password doesnt match');
|
||||||
done();
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Verification', function(){
|
describe('Verification', function(){
|
||||||
|
|
Loading…
Reference in New Issue