UNPKG

copious-transitions

Version:
267 lines (233 loc) 9.84 kB
// const AppLifeCycle = require("./general_lifecyle") /// TokenTables /** * Top level abstraction defining the relationship between token users, and token storage which may refer to some DB. * * Provides access to token storage, making the semantics of token processing available to * the authorization classes. * * This abstraction just fixes a handle to some DB interface and provides methods that wrap the token storage, * which must be provided to the constructor. * * @memberof base */ class TokenTables extends AppLifeCycle { constructor(db_obj,tokenStorage) { super() // this.db = db_obj // These are loosly written here. But, it may be good to keep // a small number relative to session size id the backend is efficient try { this.tk_store = new tokenStorage(db_obj) } catch (e) { console.log(e) } } /** * * @param {string} prefix * @returns {string} - a token for a transition object */ generate_transition_token(prefix) { return (this.tk_store.create_token(prefix)) } /** * * @param {string} token * @returns {any|Promise} */ token_to_key(token) { let key = this.tk_store.from_token(token) return key } /** * * @param {string} token * @returns {boolean} */ async tokenCurrent(token) { if ( token === undefined ) return(false) let current = await this.tk_store.transition_token_is_active(token) return ( current !== false ) } } /// SessionTokenManager /** * * The Session Token Manager deals JSON objects arriving from some session oriented client. * The JSON object is interned and stored as in the language's data object format. * Certain fields may be expected in the data object. Methods for some default case are provided, but * it is expected the application will override these methods and provide access for fields germain to the application. * * Provides basic methods for generating session tokens, stashing and unstashing. * * Manages a reference to a hashing method, called by `do_hash`. * * @extends TokenTables */ class SessionTokenManager extends TokenTables { // /** * * The configuration may bind the field `forhash` to a hashing function that will be used throughout the runtime. * * The db_obj is a reference to a class instance that knows how to talk to a database. * * The tokenStorage parameter is a required class reference that can generate a instance that manages tables of tokens. * * Initializes a table `release_session_data` for keeping data between client repsonses, where data comes from user objects, * most likely obtained from the DB. In particular, the data will have a named field provided by `sess_data_accessor`. The data * lasts until the user session is initialized by an authorization process, one that uses the general authorization (as opposed to * light authorizatoin). * * @param {object} conf * @param {object} db_obj * @param {Class} tokenStorage */ constructor(conf,db_obj,tokenStorage) { // super(db_obj,tokenStorage) // token tables // this._sess_tok_hasher = (conf && (typeof conf.session_token_hasher === 'function')) ? conf.session_token_hasher : this.#produce_hasher() // if ( conf ) { this.hashables = clonify(conf.forhash) // clone the field map from the configuration. } else { this.hashables = { "field1" : "ucwid", "field2" : "timestamp" } // if these were not configured use something failry arbitrary } // this.release_session_data = {} // if a session provides information for release on finalization, temporarily keep it here } /** * Return the field name of the user object that references data that should be accessed as part of the session */ sess_data_accessor() { // likely to be overridden e.g. "_tracking" return "app_user_data" } /** * Access to a default hash function set globally for the application */ #produce_hasher() { try { if ( global_hasher === undefined ) { throw new Error("no hasher to return to the session manager in #produce_hasher") } else { return global_hasher } } catch (e) { console.log(e) } } /** * Synonimic method to expose the hash function field, a configurable parameter * * @param {string} str * @returns {string} - the hash of the string */ do_hash(str) { // default behavior -- return(this._sess_tok_hasher(str)) } /** * Makes a session token and returns it as a string * * >Uses access to a default hash function set globally for the application * * This method concatentates two informational parts and one nonce to make a parameter to a hash function * in order to get a key that may be used as the session identifier. * * @param {object} post_body -- this is the JSON post body from the web application */ generate_session_token(post_body) { let nonce = this.generate_transition_token(); // let hash_part_1 = post_body[this.hashables.field1] // the field might no be supplied by the application hash_part_1 = hash_part_1 ? hash_part_1 : "nothing1" let hash_part_2 = post_body[this.hashables.field3] // the field might no be supplied by the application hash_part_2 = hash_part_2 ? hash_part_2 : "nothing2" // let sess_tok = this.do_hash(hash_part_1 + hash_part_2 + nonce) // this is the session identifier just getting started. return sess_tok } // // stash_session_token /** * Stashes a session in the 'elements' map of the server-side transition object * * @param {object} user -- The user object is most likely extracted from the DB * @param {object} transition_object -- a nascent transition object that has both server side and client side aspects, but must contain the newly generated session token */ stash_session_token(user,transition_object) { // sess_tok a made up token (app rule) let sess_tok = transition_object.session_token let app_sess_data_access_fld = this.sess_data_accessor() // get the application identified field name that should occur in a user object if ( app_sess_data_access_fld ) { this.release_session_data[sess_tok] = user[app_sess_data_access_fld] // app overrides so that it knows this field (ucwid) // The elements field will provide access to the session token (in turn to the user data) for the life the authorization transition transition_object.elements[app_sess_data_access_fld] = sess_tok // for secondary } } // the stored transition object identified (mapped) by its token, // will have the session token within the elements map object. // see stash_session_token(user,transition_object,sess_tok) in general_auth which extends this module // /** * given the server side transition object for an authorization transition retrieve the sesssion token * from the transition object's elements fields */ unstash_session_token(transObject) { let key = this.sess_data_accessor() if ( key ) { return(transObject.elements[key]) } return false } /** * Calls upon token storage to save the session and the relationship to its owner. * * @param {string} key -- a key, mostly likely a ucwid that identifies an owner of the session * @param {string} session_token -- a session token (should be made by generate_session_token) */ async addSession(key,session_token) { // e.g. ucwid and server side hash if ( (key !== undefined) && (session_token !== undefined) ) { return (await this.tk_store.add_session(session_token,key,false,true)) // ucwid, stashed token -> stashed token, ucwid } } /** * Calls upon token storage to termiate a session and the tokens that expire with its termination. * The parameter passed is the session's transition token, which had been created for authorization transitions. * The parameter is used to obtain the session token. * * @param {string} token -- the session's authorization transition token. */ destroySession(token) { this.tk_store.destroy_session(token) } /** * Checks to see if a session is current. * The source key may be supplied to check on the hash of owner related data. * * @param {string} session_token -- a session token (should be made by generate_session_token) * @param {string} [src_key] -- data returned from storing the transition token */ async sessionCurrent(session_token,src_key) { // src_key is not in use in the general case if ( src_key === undefined ) return(false) let key = await this.tk_store.active_session(session_token,src_key) // src key might be a ucwid return key } /** * insert_session * * For apps that only check the session but have been informed how to construct a link hash. * * @param {string} session_token * @param {string} link_hash */ insert_session(session_token,link_hash) { this.tk_store.quick_insert_active_session(session_token,link_hash) } remove_session(session_token) { this.tk_store.discard_quick_insert(session_token) } } module.exports = SessionTokenManager