Skip to content

Instantly share code, notes, and snippets.

@wgallios
Created September 13, 2014 04:45
Show Gist options
  • Select an option

  • Save wgallios/9ab24b3a1162841e73fe to your computer and use it in GitHub Desktop.

Select an option

Save wgallios/9ab24b3a1162841e73fe to your computer and use it in GitHub Desktop.
Node.js/total.js authorization module example
// MIT License
// Copyright Peter Širka <[email protected]>
// Version 1.02
var events = require('events');
var SUGAR = 'AtH101s84';
var USERAGENT = 20;
// expireCookie in days
// expireSession in minutes
function Users() {
this.options = { cookie: '__user', secret: 'a4e13bCbb9', expireSession: 10, expireCookie: 10, autoLogin: true };
this.online = 0;
this.users = {};
}
Users.prototype = new events.EventEmitter;
/*
Authorize user
@id {Number}
@callback {Function} :: callback must have as parameter an object or null value
*/
Users.prototype.onAuthorization = function (id, callback) {
if (id === undefined || id.length <= 0) return callback(null);
var self = this;
/*
var model = framework.model('user');
model.getUserByID(id).then(function(user){
if (!user)
callback(null);
else
callback(user);
});
*/
};
Users.prototype.usage = function() {
return { online: this.online };
};
Users.prototype._onAuthorization = function(req, res, flags, callback) {
var self = this;
var options = self.options;
var cookie = req.cookie(options.cookie) || '';
if (cookie === '' || cookie.length < 10) {
callback(false);
return;
}
var value = framework.decrypt(cookie, options.secret, false);
if (value === null || value.length === 0) {
callback(false);
return;
}
var arr = value.split('|');
if (arr[1] !== SUGAR || arr[3] !== req.ip || arr[2] !== req.headers['user-agent'].substring(0, USERAGENT).replace(/\s/g, '')) {
callback(false);
return;
}
var id = arr[0];
var user = self.users[id];
if (user) {
user.expire = new Date().add('m', self.options.expireSession);
req.user = user.user;
callback(true);
return;
}
self.onAuthorization(id, function(user) {
if (!user || !options.autoLogin) {
// remove cookie
res.cookie(options.cookie, '', new Date().add('d', -1));
callback(false);
return;
}
req.user = user;
self.users[id] = { user: user, expire: new Date().add('m', self.options.expireSession) };
self.emit('login', id, user);
self.refresh();
callback(true);
}, flags);
};
/*
Login an user
@controller {Controller}
@id {Number}
@user {Object}
@expire {Number} :: expire in minutes
return {Users}
*/
Users.prototype.login = function(controller, id, user, expire) {
id = id.toString();
var self = this;
if (typeof(expire) !== 'number')
expire = null;
self.users[id] = { user: user, expire: utils.isDate(expire) ? expire : new Date().add('m', expire || self.options.expireSession).getTime() };
self.refresh();
self.emit('login', id, user);
self._writeOK(id, controller.req, controller.res);
return self;
};
/*
Logoff an user
@controller {Controller}
@id {Number}
return {Users}
*/
Users.prototype.logoff = function(controller, id) {
id = id.toString();
var self = this;
var user = self.users[id];
delete self.users[id];
self._writeNO(controller.res);
self.refresh();
self.emit('logoff', id, user || null);
return self;
};
/*
Change an user
@id {Number}
@newUser {Object}
return {Users}
*/
Users.prototype.change = function(id, newUser, expire) {
id = id.toString();
var self = this;
var old = self.users[id] || null;
if (old === null)
return self;
self.users[id].user = newUser;
self.emit('change', id, newUser, old);
return self;
};
/*
Update an user
@id {Number}
@fn {function}
return {Users}
*/
Users.prototype.update = function(id, fn) {
id = id.toString();
var self = this;
var old = self.users[id] || null;
if (old === null)
return null;
var tmp = fn(old);
if (tmp)
self.users[id] = tmp;
self.emit('update', id, old);
return self;
};
/*
Set Expires
@id {Number}
@expire {Date}
return {Users}
*/
Users.prototype.setExpires = function(id, expire) {
id = id.toString();
var self = this;
var old = self.users[id] || null;
if (old === null)
return self;
self.users[id].expire = utils.isDate(expire) ? expire : new Date().add('m', expire || self.options.expireSession).getTime();
return self;
};
/*
Internal
*/
Users.prototype.refresh = function() {
var self = this;
var keys = Object.keys(self.users);
self.online = keys.length;
self.emit('online', self.online);
return self;
};
/*
Internal
*/
Users.prototype.recycle = function() {
var self = this;
var keys = Object.keys(self.users);
var length = keys.length;
if (length === 0)
return self;
var expire = new Date();
var users = self.users;
for (var i = 0; i < length; i++) {
var key = keys[i];
var user = users[key];
if (user.expire < expire) {
self.emit('expire', key, user.user);
delete users[key];
}
}
self.refresh();
return self;
};
/*
Internal
*/
Users.prototype._writeOK = function(id, req, res) {
var self = this;
var value = id + '|' + SUGAR + '|' + req.headers['user-agent'].substring(0, USERAGENT).replace(/\s/g, '') + '|' + req.ip + '|';
res.cookie(self.options.cookie, framework.encrypt(value, self.options.secret), new Date().add('d', self.options.expireCookie));
return this;
};
/*
Internal
*/
Users.prototype._writeNO = function(res) {
var self = this;
res.cookie(self.options.cookie, '', new Date().add('y', -1));
return self;
};
var users = new Users();
module.exports = users;
module.exports.name = 'auth';
module.exports.version = '1.01';
function service(counter) {
// Each 3 minutes
if (counter % 3 === 0)
users.recycle();
}
function authorization(req, res, flags, callback) {
if (users.onAuthorization !== null) {
users._onAuthorization(req, res, flags, callback);
return;
}
callback(false);
}
module.exports.install = function(framework, options) {
SUGAR = (framework.config.name + framework.config.version + SUGAR).replace(/\s/g, '');
framework.onAuthorization = authorization;
framework.on('service', service);
if (options)
users.options = Utils.copy(options);
};
module.exports.uninstall = function(framework, options) {
if (framework.onAuthorization === authorization)
framework.onAuthorization = null;
framework.removeListener('service', service);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment