memory.js
  1  /*!
  2   * express-session
  3   * Copyright(c) 2010 Sencha Inc.
  4   * Copyright(c) 2011 TJ Holowaychuk
  5   * Copyright(c) 2015 Douglas Christopher Wilson
  6   * MIT Licensed
  7   */
  8  
  9  'use strict';
 10  
 11  /**
 12   * Module dependencies.
 13   * @private
 14   */
 15  
 16  var Store = require('./store')
 17  var util = require('util')
 18  
 19  /**
 20   * Shim setImmediate for node.js < 0.10
 21   * @private
 22   */
 23  
 24  /* istanbul ignore next */
 25  var defer = typeof setImmediate === 'function'
 26    ? setImmediate
 27    : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
 28  
 29  /**
 30   * Module exports.
 31   */
 32  
 33  module.exports = MemoryStore
 34  
 35  /**
 36   * A session store in memory.
 37   * @public
 38   */
 39  
 40  function MemoryStore() {
 41    Store.call(this)
 42    this.sessions = Object.create(null)
 43  }
 44  
 45  /**
 46   * Inherit from Store.
 47   */
 48  
 49  util.inherits(MemoryStore, Store)
 50  
 51  /**
 52   * Get all active sessions.
 53   *
 54   * @param {function} callback
 55   * @public
 56   */
 57  
 58  MemoryStore.prototype.all = function all(callback) {
 59    var sessionIds = Object.keys(this.sessions)
 60    var sessions = Object.create(null)
 61  
 62    for (var i = 0; i < sessionIds.length; i++) {
 63      var sessionId = sessionIds[i]
 64      var session = getSession.call(this, sessionId)
 65  
 66      if (session) {
 67        sessions[sessionId] = session;
 68      }
 69    }
 70  
 71    callback && defer(callback, null, sessions)
 72  }
 73  
 74  /**
 75   * Clear all sessions.
 76   *
 77   * @param {function} callback
 78   * @public
 79   */
 80  
 81  MemoryStore.prototype.clear = function clear(callback) {
 82    this.sessions = Object.create(null)
 83    callback && defer(callback)
 84  }
 85  
 86  /**
 87   * Destroy the session associated with the given session ID.
 88   *
 89   * @param {string} sessionId
 90   * @public
 91   */
 92  
 93  MemoryStore.prototype.destroy = function destroy(sessionId, callback) {
 94    delete this.sessions[sessionId]
 95    callback && defer(callback)
 96  }
 97  
 98  /**
 99   * Fetch session by the given session ID.
100   *
101   * @param {string} sessionId
102   * @param {function} callback
103   * @public
104   */
105  
106  MemoryStore.prototype.get = function get(sessionId, callback) {
107    defer(callback, null, getSession.call(this, sessionId))
108  }
109  
110  /**
111   * Commit the given session associated with the given sessionId to the store.
112   *
113   * @param {string} sessionId
114   * @param {object} session
115   * @param {function} callback
116   * @public
117   */
118  
119  MemoryStore.prototype.set = function set(sessionId, session, callback) {
120    this.sessions[sessionId] = JSON.stringify(session)
121    callback && defer(callback)
122  }
123  
124  /**
125   * Get number of active sessions.
126   *
127   * @param {function} callback
128   * @public
129   */
130  
131  MemoryStore.prototype.length = function length(callback) {
132    this.all(function (err, sessions) {
133      if (err) return callback(err)
134      callback(null, Object.keys(sessions).length)
135    })
136  }
137  
138  /**
139   * Touch the given session object associated with the given session ID.
140   *
141   * @param {string} sessionId
142   * @param {object} session
143   * @param {function} callback
144   * @public
145   */
146  
147  MemoryStore.prototype.touch = function touch(sessionId, session, callback) {
148    var currentSession = getSession.call(this, sessionId)
149  
150    if (currentSession) {
151      // update expiration
152      currentSession.cookie = session.cookie
153      this.sessions[sessionId] = JSON.stringify(currentSession)
154    }
155  
156    callback && defer(callback)
157  }
158  
159  /**
160   * Get session from the store.
161   * @private
162   */
163  
164  function getSession(sessionId) {
165    var sess = this.sessions[sessionId]
166  
167    if (!sess) {
168      return
169    }
170  
171    // parse
172    sess = JSON.parse(sess)
173  
174    if (sess.cookie) {
175      var expires = typeof sess.cookie.expires === 'string'
176        ? new Date(sess.cookie.expires)
177        : sess.cookie.expires
178  
179      // destroy expired session
180      if (expires && expires <= Date.now()) {
181        delete this.sessions[sessionId]
182        return
183      }
184    }
185  
186    return sess
187  }