userauthjs
Version:
Node module for management of user/group privileges and sessions
122 lines (115 loc) • 3.94 kB
JavaScript
var async = require('async')
var bcrypt = require('bcrypt')
var jwt = require('jwt-simple')
var secret = process.env.USERAUTH_KEY
var User = require('./models/user')
var Usergroup = require('./models/usergroup')
var Privilege = require('./models/privilege')
var Session = require('./models/session')
/**
* Allow only a few active sessions per user
* Decide if an session should have an timeout.
* Usually an smartphone native app should not have an timeout
*/
exports.start = function(username, password, next, permanent) {
permanent = typeof permanent !== 'undefined' ? permanent : false
User.findOne({username: username})
.select('password')
.select('username')
.select('active')
.select('usergroups')
.exec(function(err, user) {
if (err) { return next(err) }
if (!user) { return next(null, false) }
bcrypt.compare(password, user.password, function(err, valid) {
if (err) { return next(err) }
if (!valid) { return next(null, false) }
var started = new Date()
var token = jwt.encode({
username: user.username,
userid: user._id,
usergroups: user.usergroups,
started: started
}, process.env.USERAUTH_KEY)
session = new Session({
user: user._id,
token: token,
permanent: permanent,
started: started
})
session.save(function(err, session) {
if (err) { return next(err) }
if (!session) { return next(null, false) }
if (process.env.USERAUTH_LOG) { console.log('Userauth session started for: ' + username) }
next(null, token)
})
})
})
}
exports.verify = function(token, privilege, next) {
userinfo = decodeToken(token)
if (!userinfo) { return next(null, false) }
Session.findOne({ token: token }, function(err, session) {
if (err) { return next(err) }
if (!session) { return next(null, false) }
var now = new Date()
var validTime = session.started.getTime() + process.env.SESSION_TIMEOUT * 1000
if (!session.permanent && now.getTime() > validTime) { return next(null, false) }
Privilege.findOne({ title: privilege }, function(err, privilege) {
if (err) { return next(err) }
if (!privilege) { return next(null, false) }
User.findOne({ _id: userinfo.userid }, function(err, user) {
if (err) { return next(err) }
if (!user) { return next(null, false) }
var validUsergroup = false
for (var i = 0; i < user.usergroups.length; i++) {
if (privilege.usergroups.indexOf(user.usergroups[i]) > -1) {
validUsergroup = true
}
}
if (privilege.users.indexOf(user._id) > -1 || validUsergroup) {
next(null, userinfo)
} else {
next(null, false)
}
})
})
})
}
exports.stop = function(token, next) {
Session.findOneAndRemove({ token: token }, function(err, session) {
if (err) { return next(err) }
if (!session) { return next(null, false) }
var userinfo = decodeToken(token)
if (process.env.USERAUTH_LOG) { console.log('Userauth session stopped for: ' + userinfo.username) }
next(null, userinfo)
})
}
exports.stopAll = function(userid, next) {
var userinfo
Session.find({ user: userid })
.populate('user')
.exec(function(err, sessions) {
if (err) { return next(err) }
if (!sessions) { return next(null, false) }
if (sessions.length < 1) { return next(null, false) }
var iSession = 1
async.each(sessions, function(session, done) {
session.remove(function(err, session) {
if (err) { return done(err) }
userinfo = decodeToken(session.token)
if (process.env.USERAUTH_LOG) { console.log('Userauth session (' + iSession + '/' + sessions.length + ') stopped for: ' + userinfo.username) }
iSession++
done()
})
}, function(err) {
if (err) { return next(err) }
if (process.env.USERAUTH_LOG) { console.log('All userauth sessions stopped for: ' + userinfo.username) }
next(null, userinfo)
})
})
}
var decodeToken = function (token) {
return jwt.decode(token, process.env.USERAUTH_KEY)
}
exports.decodeToken = decodeToken