124 lines
2.6 KiB
JavaScript
124 lines
2.6 KiB
JavaScript
var _ = require('underscore');
|
|
var Backbone = require('backbone');
|
|
var crypto = require('crypto');
|
|
var hashy = require('hashy');
|
|
var Q = require('q');
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
var check = function () {
|
|
var errors = undefined;
|
|
|
|
var validator = new require('validator').Validator();
|
|
validator.error = function (err) {
|
|
(errors || (errors = [])).push(err);
|
|
return this;
|
|
};
|
|
|
|
var check = function (data) {
|
|
validator.check(data);
|
|
};
|
|
check.pop = function () {
|
|
var res = errors;
|
|
errors = undefined;
|
|
return res;
|
|
};
|
|
|
|
return check;
|
|
}();
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Models
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// @todo We could also give a permission level to tokens (<=
|
|
// user.permission).
|
|
var Token = Backbone.Model.extend({
|
|
// Validates model attributes.
|
|
'validate': function (attr) {
|
|
check(attr.id).len(10);
|
|
check(attr.user_id).isInt();
|
|
|
|
return check.pop();
|
|
},
|
|
}, {
|
|
'generate': function (user_id) {
|
|
return Q.ninvoke(crypto, 'randomBytes', 32).then(function (buf) {
|
|
return new Token({
|
|
'id': buf.toString('base64'),
|
|
'user_id': user_id,
|
|
});
|
|
});
|
|
},
|
|
});
|
|
|
|
var User = Backbone.Model.extend({
|
|
'default': {
|
|
'permission': 'none',
|
|
},
|
|
|
|
'initialize': function ()
|
|
{
|
|
this.on('change:password', function (model, password) {
|
|
this.unset('password', {'silent': true});
|
|
|
|
var user = this;
|
|
hashy.hash(password).then(function (hash) {
|
|
user.set('pw_hash', hash);
|
|
}).done();
|
|
});
|
|
},
|
|
|
|
// Validates model attributes.
|
|
'validate': function (attr) {
|
|
check(attr.id).isInt();
|
|
check(attr.email).isEmail();
|
|
check(attr.pw_hash).len(40);
|
|
check(attr.permission).isIn('none', 'read', 'write', 'admin');
|
|
|
|
return check.pop();
|
|
},
|
|
|
|
// Checks and updates the hash if necessary.
|
|
'checkPassword': function (password) {
|
|
var hash = this.get('pw_hash');
|
|
var user = this;
|
|
|
|
return hashy.verify(password, hash).then(function (success) {
|
|
if (!success)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (hashy.needsRehash(hash))
|
|
{
|
|
user.set('password', password);
|
|
}
|
|
});
|
|
},
|
|
});
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Collections
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
var Tokens = Backbone.Collection.extend({
|
|
'model': Token,
|
|
});
|
|
|
|
var Users = Backbone.Collection.extend({
|
|
'model': User,
|
|
});
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
function Xo()
|
|
{
|
|
this.tokens = new Tokens();
|
|
this.users = new Users();
|
|
}
|
|
|
|
module.exports = function () {
|
|
return new Xo;
|
|
};
|