/**
* @version 1.0.0
* @author Boris GBAHOUE
* @file Common Session middleware
* @module amiwo/rest
*/
// =======================================================================
// BASE SETUP
// =======================================================================
// call the packages we need
var debug = require('debug')('amiwo:session');
var u = require('../util');
// public static variables
var __sessionHash = {};
// =======================================================================
// CONSTRUCTOR
// =======================================================================
/**
* @class
*
* @param {String} app: application name
* @param {Object} options
*/
function Session(app, options) {
this._application = app || "amiwo";
__sessionHash[this._application] = this;
// Options processing
if (options == null) options = {};
}
// =======================================================================
// PUBLIC METHODS
// =======================================================================
/**
* Middleware to initialize our session logic
*
* @public
*/
Session.prototype.init = function(req, res, next) {
if (req[this._application]) return next(); // Initialize only once per request
req[this._application] = {};
if (req.session && req.session[this._application]) {
// load data from existing session
req[this._application].session = req.session[this._application];
} else {
if (req.session) {
// initialize new session
req.session[this._application] = {};
req[this._application].session = req.session[this._application];
} else {
// no session is available
req[this._application].session = {};
}
req[this._application].session.request = {};
req[this._application].session.response = {};
}
return next();
}
/**
* Saves 'value' into our session response object
*
* @param {Request} req
* @param {String} property property name, can use dot to build a structured JSON
* @param {any} value
*
* @public
*/
Session.prototype.setResponse = function(req, property, value) {
$set.call(this, "response", req, property, value);
}
/**
* Get a value from our session response object
*
* @param {Request} req
* @param {String} property property name, can use dot to build a structured JSON
* @param {Boolean} [deleteEntry=true] if set to true, delete response object
*
* @public
*/
Session.prototype.getResponse = function(req, property, deleteEntry) {
deleteEntry = !(deleteEntry == false);
var tmp = $get.call(this, "response", req, property);
if (deleteEntry) this.deleteResponse(req, property);
return tmp;
}
/**
* Delete a value from our session response object
*
* @param {Request} req
* @param {String} property property name, can use dot to build a structured JSON
*
* @returns {any} the deleted entry
*
* @public
*/
Session.prototype.deleteResponse = function(req, property) {
return $delete.call(this, "response", req, property);
}
/**
* Clear session response object
*
* @param {Request} req
*
* @public
*/
Session.prototype.clearResponse = function(req) {
req[this._application].session.response = {};
}
/**
* Saves 'value' into our session request object
*
* @param {Request} req
* @param {String} property property name, can use dot to build a structured JSON
* @param {any} value
*
* @public
*/
Session.prototype.setRequest = function(req, property, value) {
$set.call(this, "request", req, property, value);
}
/**
* Get a value from our session request object
*
* @param {Request} req
* @param {String} property property name, can use dot to build a structured JSON
* @param {Boolean} [deleteEntry=true] if set to true, delete response object
*
* @public
*/
Session.prototype.getRequest = function(req, property, deleteEntry) {
deleteEntry = !(deleteEntry == false);
var tmp = $get.call(this, "request", req, property);
if (deleteEntry) this.deleteRequest(req, property);
return tmp;
}
/**
* Delete a value from our session request object
*
* @param {Request} req
* @param {String} property property name, can use dot to build a structured JSON
*
* @returns {any} the deleted entry
*
* @public
*/
Session.prototype.deleteRequest = function(req, property) {
return $delete.call(this, "request", req, property);
}
/**
* Clear session request object
*
* @param {Request} req
*
* @public
*/
Session.prototype.clearRequest = function(req) {
req[this._application].session.request = {};
}
/**
* Create the objects to hold flash messages if needed.
*
* @public
*/
Session.prototype.initMessages = function(req) {
if (u.isEmpty(req[this._application].session.messages)) req[this._application].session.messages = {};
if (u.isEmpty(req[this._application].session.messages.success)) req[this._application].session.messages.success = [];
if (u.isEmpty(req[this._application].session.messages.info)) req[this._application].session.messages.info = [];
if (u.isEmpty(req[this._application].session.messages.warning)) req[this._application].session.messages.warning = [];
if (u.isEmpty(req[this._application].session.messages.error)) req[this._application].session.messages.error = [];
// for backward compatibility
req.session.messages = req[this._application].session.messages;
}
/**
* Clear messages (and init messages if they didn't exist)
*
* @public
*/
Session.prototype.clearMessages = function(req) {
this.initMessages(req);
req[this._application].session.messages.success = [];
req[this._application].session.messages.info = [];
req[this._application].session.messages.warning = [];
req[this._application].session.messages.error = [];
}
/**
* Get message objects
*/
Session.prototype.getMessages = function(req) {
this.initMessages(req);
var messages = u.clone(u.fuse(req[this._application].session.messages, req.session.messages));
this.clearMessages(req);
return messages;
}
/**
* Set a new message
*/
Session.prototype.setMessage = function(req, type, message) {
if ((req == null) || u.isEmpty(type) || u.isEmpty(message)) return;
if ((req[this._application] == null) || (req[this._application].session == null) || (req[this._application].session.messages == null)) this.initMessages(req);
if (req[this._application].session.messages[type].indexOf(message) == -1) {
req[this._application].session.messages[type].push(message);
} else {
// Already existing message => don't create a duplicate
}
}
/**
* Saves an info message
*/
Session.prototype.setInfoMessage = function(req, message) {
this.setMessage(req, "info", message);
}
/**
* Saves a warning message
*/
Session.prototype.setWarningMessage = function(req, message) {
this.setMessage(req, "warning", message);
}
/**
* Saves an error message
*/
Session.prototype.setErrorMessage = function(req, message) {
this.setMessage(req, "error", message);
}
/**
* Saves a success message
*/
Session.prototype.setSuccessMessage = function(req, message) {
this.setMessage(req, "success", message);
}
// =======================================================================
// PUBLIC STATIC METHODS
// =======================================================================
/**
* Get the Session object for an application
*/
Session.getSession = function(app) {
var session = __sessionHash[app];
if (session == null) {
session = new Session(app);
__sessionHash[app] = session;
}
return session;
}
// =======================================================================
// PRIVATE METHODS
// =======================================================================
/**
* Saves 'value' into our session object 'object'
*
* @param {String} object 'response' or 'request'
* @param {Request} req
* @param {String} property property name, can use dot to build a structured JSON
* @param {any} value
* @memberOf Session
* @private
*/
function $set(object, req, property, value) {
if (u.isEmpty(object)) throw new ReferenceError("object can't be null");
if ((property == null) || (req == null)) return;
if (req && req[this._application]) {
if (req[this._application].session == null) req[this._application].session = {};
if (req[this._application].session[object] == null) req[this._application].session[object] = {};
if (property.indexOf(".") > -1) {
var propSplit = property.split(".");
var lastProp = propSplit.pop();
var obj = req[this._application].session[object];
for (var i = 0; i < propSplit.length; i++) {
if (obj[propSplit[i]] == null) {
obj[propSplit[i]] = {};
}
obj = obj[propSplit[i]];
}
obj[lastProp] = value;
} else {
req[this._application].session[object][property] = value;
}
} else {
debug("::AMIWO::SESSION::SET%s::%s::ERROR Session object has not been created",object.toUpperCase(), this._application.toUpperCase());
}
}
/**
* Get a value of 'property' from our session object 'object'
*
* @param {String} object 'response' or 'request'
* @param {Request} req
* @param {String} property property name, can use dot to use structured JSON path
* @memberOf Session
* @private
*/
function $get(object, req, property) {
if (req && req[this._application] && req[this._application].session && req[this._application].session[object]) {
return u.getProperty(req[this._application].session[object], property);
}
// else
return null;
}
/**
* Delete 'property' from our session object 'object'
*
* @param {String} object 'response' or 'request'
* @param {Request} req
* @param {String} property property name, can use dot to build a structured JSON
*
* @returns {any} the deleted entry
* @memberOf Session
* @private
*/
function $delete(object, req, property) {
if (u.isEmpty(object)) throw new ReferenceError("object can't be null");
if ((property == null) || (req == null)) return;
var deletedEntry = null;
if (req && req[this._application]) {
if (req[this._application].session == null) req[this._application].session = {};
if (req[this._application].session[object] == null) req[this._application].session[object] = {};
if (property.indexOf(".") > -1) {
var propSplit = property.split(".");
var lastProp = propSplit.pop();
var obj = req[this._application].session[object];
for (var i = 0; i < propSplit.length; i++) {
if (obj[propSplit[i]] == null) {
obj[propSplit[i]] = {};
}
obj = obj[propSplit[i]];
}
deletedEntry = obj[lastProp];
delete obj[lastProp];
} else {
deletedEntry = req[this._application].session[object][property];
delete req[this._application].session[object][property];
}
} else {
debug("::AMIWO::SESSION::DELETE%s::%s::ERROR Session object has not been created",object.toUpperCase(), this._application.toUpperCase());
}
return deletedEntry;
}
module.exports = Session;