API Docs for: 0.8.0
Show:

File: include/session/storage/mongo_session_store.js

/*
    Copyright (C) 2016  PencilBlue, LLC

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';

//dependencies
var util  = require('../../util.js');
var async = require('async');

module.exports = function MongoSessionStoreModule(pb) {

    /**
     * Session storage backed by MongoDB
     *
     * @module Session
     * @class MongoSessionStore
     * @constructor
     */
    function MongoSessionStore(){}

    /**
     * The mongo collection that stores the sessions
     * @private
     * @static
     * @readonly
     * @property SESSION_COLLECTION_NAME
     * @type {String}
     */
    var SESSION_COLLECTION_NAME = 'session';

    /**
     * The cache lock key used when the index is needed to be modified
     * @private
     * @static
     * @readonly
     * @property INDEX_MOD_LOCK_KEY
     * @type {String}
     */
    var INDEX_MOD_LOCK_KEY = 'MONGO_SESSION_STORE_INDEX_MOD_LOCK';

    /**
     * Responsible for retrieving the session for persistent storage.
     *
     * @method get
     * @param {String} sessionId The identifier of the session to retrieve.
     * @param {Function} cb Callback of form cb(err, [Object])
     */
    MongoSessionStore.prototype.get = function(sessionId, cb){
        var dao = new pb.DAO();
        dao.loadByValue('uid', sessionId, SESSION_COLLECTION_NAME, MongoSessionStore.getHandler(cb));
    };

    /**
     * Responsible for persisting the session object between user requests
     * @param session The session object to store.  The session object must contain
     * the following in addition to other data:
     * <pre>
     * {
     * 	uid: [primitive]
     * }
     * </pre>
     *
     * @method set
     * @param {Function} cb Callback of form cb(err, 'OK')
     */
    MongoSessionStore.prototype.set = function(session, cb){
        //ensure an object type is set
        session.object_type = SESSION_COLLECTION_NAME;
        session.timeout = new Date(session.timeout);

        //persist the session
        var dao = new pb.DAO();
        dao.save(session, cb);
    };

    /**
     * Deletes a session if it exists.
     *
     * @method clear
     * @param {String} sessionId
     * @param {Function} cb Callback of form cb(err, [int SESSIONS_CLEARED])
     */
    MongoSessionStore.prototype.clear = function(sessionId, cb){
        var dao = new pb.DAO();
        dao.delete(MongoSessionStore.getSessionQuery(sessionId), SESSION_COLLECTION_NAME, cb);
    };

    /**
     * Responsable for shutting down the session store and any resources used for
     * reaping expired sessions.
     * @method shutdown
     * @param {Function} cb
     */
    MongoSessionStore.prototype.shutdown = function(cb){
        pb.log.debug("MongoSessionStore: Shutting down...");
        cb(null, true);
    };

    /**
     * Responsable for ensuring that the mechanism that expires sessions becomes
     * active.
     * @method start
     */
    MongoSessionStore.prototype.start = function(cb){
        var self = this;

        //prepare index values
        var expiry    = Math.floor(pb.config.session.timeout / util.TIME.MILLIS_PER_SEC);
        var procedure = {
            collection: SESSION_COLLECTION_NAME,
            spec: { timeout: 1 },
            options: { expireAfterSeconds: expiry }
        };

        //ensure an index exists.  According to the MongoDB documentation ensure
        //index cannot modify a TTL value once it is created.  Therefore, we have
        //to ensure that the index exists and then verify that the expiry matches.
        //When it doesn't match we must create a system lock, drop the index, and
        //recreate it.  Due to the permissions levels of some mongo hosting
        //providers the collMod command cannot be used.
        var TTLIndexHelper = require('../../dao/mongo/ttl_index_helper.js')(pb);
        var helper = new TTLIndexHelper();
        helper.ensureIndex(procedure, cb);
    };

    /**
     * Constructs a query to find a session in Mongo
     * @method getSessionQuery
     * @param {String} sessionId The session identifier
     * @return {Object}
     */
    MongoSessionStore.getSessionQuery = function(sessionId){
        return {
            uid: sessionId
        };
    };

    /**
     * @static
     * @method getHandler
     * @param {Function} cb
     * @return {Function}
     */
    MongoSessionStore.getHandler = function(cb) {
        return function(err, session) {
            if (session && util.isDate(session.timeout)) {
                session.timeout = session.timeout.getTime();
            }
            cb(err, session);
        };
    };

    return MongoSessionStore;
};