File: /var/dev/farhangmoaser/web/helpers/__access.js
/**
 * Authentication Helper
 * Version: 0.1
 * Author: Babak Vandad
 *
 * Contains common functionalities for authentication.
 * It also delegates with session data stored in Redis.
 */
"use strict";
var path = require('path');
var md5 = require('md5');
var ip = require('ip');
var consts = require(path.join(BASEDIR, 'consts.js'));
var UserAccessModel = require(path.join(BASEDIR, 'models/userAccess.js'));
var fail = function(response, conn, error, status){
		return function(){
			if(conn && conn.release)
				conn.release();
			response.status(status ? status : error.status).json({error: error.code, message: error.message});
		};
	};
class AccessHelper {
	
	/**
	 * Express middleware to validate token and corresponding user.
	 * Authorizes api key based on hit count, ip range, ...
	 * Adds a Passport styled user object to the request.
	 * @param  {request}    req   Express request
	 * @param  {response}   res   Express response
	 * @param  {middleware} next  next middleware in the list
	 */
	static authenticate(req, res, next){
		// return next();
		if(req.isAuthenticated()) return next(); //TODO: this is true for app model. check this for users too.
		var token = req.headers['x-token'] || req.query.token;
		if(token)
			AuthHelper.deserialize(token, function(err, user){
				if(err)
					return fail(res, null, consts.e.ERR_SERIALIZATION_ERROR)();
				if(!AuthHelper.ipcheck(req.ip, user.data.ip_range))
					return fail(res, null, consts.e.ERR_AUTH_IP)();
				if(user.data.hit_limit) {
					var lastReset = new Date(user.data.last_reset);
					var diff = Math.floor((new Date() - lastReset)/3600000);
					if(!user.data.counter_period || diff<user.data.counter_period){
						if(user.data.hit_count<user.data.hit_limit)
							return user.touch().then(
								function(){
									user.token = token;
									req.user = user;
									next();
								}, fail(res, null, consts.e.ERR_DB_ERROR));
						else
							return fail(res, null, consts.e.ERR_AUTH_QUOTA)();
					} else
						return user.resetHitCounter().then(
							function(){
								user.token = token;
								req.user = user;
								next();
							}, fail(res, null, consts.e.ERR_DB_ERROR));
				}
				user.token = token;
				req.user = user;
				next();
			});
		else
			return fail(res, null, consts.e.ERR_AUTH_TOKEN)();
	}
}
module.exports = AccessHelper;