diff options
author | gumi <git@gumi.ca> | 2020-03-15 17:28:35 -0400 |
---|---|---|
committer | gumi <git@gumi.ca> | 2020-03-15 17:28:35 -0400 |
commit | a0a35766911f5354487663b0f148b824ca32ba44 (patch) | |
tree | 6a5a80a52eaacc8f8b35798cedd16ddea37e3992 /src/routers/vault/types/SessionStore.js | |
parent | 267b900a82d7870e4bcd56857887fd3f697e6e45 (diff) | |
download | api-a0a35766911f5354487663b0f148b824ca32ba44.tar.gz api-a0a35766911f5354487663b0f148b824ca32ba44.tar.bz2 api-a0a35766911f5354487663b0f148b824ca32ba44.tar.xz api-a0a35766911f5354487663b0f148b824ca32ba44.zip |
turn the session store into a proper class
Diffstat (limited to 'src/routers/vault/types/SessionStore.js')
-rw-r--r-- | src/routers/vault/types/SessionStore.js | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/routers/vault/types/SessionStore.js b/src/routers/vault/types/SessionStore.js new file mode 100644 index 0000000..daa71c3 --- /dev/null +++ b/src/routers/vault/types/SessionStore.js @@ -0,0 +1,129 @@ +"use strict"; +const Session = require("./Session.js"); + +/** + * we store the timeout directly in Session instances + * @type Symbol("session timeout") + */ +const timeout_symbol = Symbol("session timeout"); + +/** + * holds the Sessions and re-hydrates them when accessed + */ +class SessionStore { + /** + * a Map of all Session instances + * @type Map<string, Session> + */ + sessions = new Map(); + /** lifetime of an unauthenticated Session, in minutes */ + base_lifetime = 30; + /** lifetime of a properly authenticated Session, in minutes */ + authed_lifetime = 60 * 6; // 6 hours + + /** + * creates a new SessionStore + * @param {number} base - the base Session lifetime, in minutes + * @param {number} authed - the lifetime of an authenticated Session + */ + constructor (base = 0, authed = 0) { + this.base_lifetime = base || this.base_lifetime; + this.authed_lifetime = authed || this.authed_lifetime; + } + + /** + * re-hydrates a Session by resetting the expiration + * @param {string} key - the Session key + * @param {Session} sess - the Session to hydrate + * @returns {Session} the same Session + */ + hydrate (key, sess) { + /** the new expiration, in minutes */ + let minutes = this.base_lifetime; + + if (Reflect.has(sess, timeout_symbol)) { + /** clear any existing timeout */ + clearTimeout(sess[timeout_symbol]); + } + + if (sess.authenticated === true) { + /** Session is properly authenticated: set lifetime accordingly */ + minutes = this.authed_lifetime; + } + + /** the new expiry Date */ + const expires = new Date(); + expires.setUTCMinutes(expires.getUTCMinutes() + minutes); // update it + sess.expires = expires; // swap the old for the new expiry + sess[timeout_symbol] = setTimeout(() => this.delete(key), minutes * 60000); + return sess; + } + + /** + * checks whether a Session with the given key exists + * @param {string} key - the Session key + */ + has (key) { + return this.sessions.has(key); + } + + /** + * returns a Session with the matching key + * @param {string} key - the Session key + * @returns {Session} the found Session + */ + get (key) { + /** lookup the session by key */ + const sess = this.sessions.get(key); + + if (sess) { + /** the Session, re-hydrated */ + return this.hydrate(key, sess); + } + + /** session not found */ + return null; + } + + /** + * adds a Session to the store + * @param {string} key - the Session key + * @param {Session} sess - the Session + */ + set (key, sess) { + this.sessions.set(key, this.hydrate(key, sess)); + } + + /** + * removes a Session with the matching key from the store + * + * NOTE: this does not actually delete the Session instance + * @param {string} key - the Session key + */ + delete (key) { + /** lookup the session by key */ + const sess = this.sessions.get(key); + + if (sess) { + if (Reflect.has(sess, timeout_symbol)) { + /** clear any existing timeout */ + clearTimeout(sess[timeout_symbol]); + } + + return this.sessions.delete(key) + } + + /** session not found */ + return false; + } + + /** + * iterator for use in for-of + * @returns {Iterator<[string, Session]>} the Map iterator of the SessionStore instance + */ + [Symbol.iterator] () { + return this.sessions[Symbol.iterator](); + } +} + +module.exports = SessionStore; |