Skip to content

Instantly share code, notes, and snippets.

@vincentmac
Created August 29, 2012 18:36
Show Gist options
  • Save vincentmac/3516816 to your computer and use it in GitHub Desktop.
Save vincentmac/3516816 to your computer and use it in GitHub Desktop.
Riak-js: User Model
/*!
* user.js
* User Model using Riak as a datastore
*/
/**
* Model dependencies
*/
var db = require('riak-js').getClient({debug: true, port:8091, api: 'http'});
var bcrypt = require('bcrypt');
var util = require('util');
var events = require('events');
// Voxer Riak Client congig
// var RiakClient = require('riak');
// var servers = ['127.0.0.1:8091'];
// var client_id = 'backoffice.io-client';
// var pool_name = 'backoffice.io-pool';
// // var client_id = '';
// // var pool_name = '';
// var client = new RiakClient(servers, client_id, pool_name);
// client.debug_mode = true;
/**
* `User` constructor. Initialize with `data`.
*
* @param {Object} data
* @api public
*/
var User = function(data) {
events.EventEmitter.call(this);
var that = this;
this.data = data || {};
};
util.inherits(User, events.EventEmitter);
// Enable automatic document indexing in riak
// db.enableIndex('users'); // This command not available in the js branch on riak-js
/**
* Generate bcrypted `password` from plain text `password`
*
* @param {String} password
* @return {String}
* @api private
*/
function bcryptPassword(password) {
console.log('bcrypting/salting password');
var salt = bcrypt.genSaltSync(15);
return bcrypt.hashSync(password, salt);
}
/**
* Get user from riak db given `userId`
*
* @param {String} userId
* @return {User}
* @api public
*/
User.prototype.get = function(userId, callback) {
if (typeof callback !== 'function') {
callback = function(err, data, meta) {
console.log('found user: ', data);
return data;
};
}
db.get('users', userId, callback);
};
/**
* Search for userId given `username`
*
* @param {String} username
* @return {String} userId
* @api public
*/
User.prototype.search = function(username, callback) {
if (typeof callback !== 'function') {
callback = function(err, data) {
if (data.docs.length < 1) { return null; }
// console.log('[User search] found userId: ', data.docs[0].id);
return data.docs[0].id;
};
}
// console.log('[User search] GET/SEARCH for user');
db.search('users', 'username:' + username, callback);
};
/**
* Save a new user to riak with metadata `meta`
*
* @param {Object} meta
* @api public
*/
User.prototype.create = function(meta, callback) {
// bcryptPassword before saving
console.log('password: ',this.data.password);
this.data.password = bcryptPassword(this.data.password);
console.log('bcrypted password: ',this.data.password);
console.log('[User Model] create: this.data: ', this.data);
// db.save('users', this.data.username, this.data, callback);
db.save('users', 0, this.data, meta, callback);
};
/**
* Save updated user data `data` and metadata `meta` to riak db given `key`.
* Verify that password before submitting changes.
*
* @param {String} userId
* @api public
*/
User.prototype.save = function(userId, data, meta, callback) {
// if new password being set bcryptPassword before saving
console.log('[SAVE USER] ', userId);
console.log('[SAVE USER DATA] ', data);
db.save('users', userId, data, meta, callback);
};
/**
* Check if a user by the given `email` exists in the riak db.
*
* @param {String} email
* @api public
*/
User.prototype.emailExists = function(email, callback) {
db.search('users', 'email:' + email, callback);
};
/**
* Check if a user by the given `username` exists in the riak db.
*
* @param {String} username
* @api public
*/
User.prototype.usernameExists = function(username, callback) {
db.search('users', 'username:' + username, callback);
};
/**
* Check if a user by the given `email` and `username` exists.
*
* @param {String} email
* @param {String} username
* @return {User}
* @api public
*/
User.prototype.exists = function(email, username, callback) {
if (typeof callback !== 'function') {
callback = function(err, data) {
if (data.docs.length < 1) { return null; }
return data.docs[0].id;
};
}
var user = new User();
user.emailExists(email, function(err, data) {
if (err) { console.log('[User emailExists: Error] ', err); }
user.emit('UserModel:emailExists', data);
});
user.on('UserModel:emailExists', function(data) {
if (data.numFound > 0) {
return callback(null, data, {message:'email address exists'});
}
user.usernameExists(username, function(err, data) {
if (err) {
console.log('[User usernameExists: Error] ', err);
}
user.emit('UserModel:usernameExists', data);
});
});
user.on('UserModel:usernameExists', function(data) {
if (data.numFound > 0) {
return callback(null, data, {message:'username exists'});
}
// console.log('new username');
return callback(null, data, {message:'new user'});
});
};
/**
* Verify user-provided `password` matches bcrypted password in db
*
* @param {String} password
* @return {User}
* @api public
*/
User.prototype.verifyPassword = function(password, callback) {
console.log('verifying password');
bcrypt.compare(password, this.data.password, callback);
};
User.prototype.autoLogin = function(username, password, callback) {
//get user this.get(user stuff)
};
/**
* Authenticate user credentials from user-provided `username` and `password`
*
* @param {String} username
* @param {String} password
* @param {Function} callback
* @return {Function} callback(err, user [, message])
* @api public
*/
User.prototype.authenticate = function(username, password, callback) {
console.log('[UserModel] trying authenticate');
this.search(username, function(err, data) {
if (err) { return callback(err); }
console.log('[UserModel search]: ', data.docs.length);
if (data.docs.length < 1) {
return callback(null, false, {message: 'Unknown user'});
}
// console.log('[UserModel Authenticate] User Id: ', data.docs[0].id);
// console.log('[UserModel Authenticate] User data: ', data);
var user = new User();
user.get(data.docs[0].id, function(err, data, meta) {
// console.log('[UserModel Auth: get user by id] ', data);
// console.log('[UserModel Auth: get user by id] ', meta);
// return data;
user.emit('UserModel:authenticated', data, meta);
});
user.on('UserModel:authenticated', function(data, meta) {
user.data = data;
user.meta = meta;
console.log('[UserModel On: authenticated] key: ', user.meta.key);
console.log('[UserModel On: authenticated] data: ', user.data);
console.log('[UserModel On: authenticated] meta: ', user.meta);
// console.log('[UserModel] password: ', user.data.password);
user.verifyPassword(password, function(err, passwordCorrect) {
if (err) { return callback(err); }
if (!passwordCorrect) { return callback(null, false, { message: 'Invalid password' }); }
return callback(null, user);
});
});
});
};
/**
* Delete user from riak by `userId`
*
* @param {String} userId
* @api public
*/
User.prototype.remove = function(userId, callback) {
console.log('[USER REMOVE] ', userId);
// console.log('[DEL CALLBACK fn]', callback);
db.remove('users', userId, {}, callback);
// client.del('users', userId, callback); // Voxer's Riak Client
};
/**
* Expose `User`.
*/
exports = module.exports = User;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment