UNPKG

meshblu-core-manager-token

Version:
113 lines (95 loc) 4.38 kB
_ = require 'lodash' crypto = require 'crypto' class TokenManager constructor: ({@datastore,@pepper,@uuidAliasResolver}) -> throw new Error "Missing mandatory parameter: @pepper" if _.isEmpty @pepper generateAndStoreToken: ({ uuid, metadata, expiresOn, root }, callback) => @uuidAliasResolver.resolve uuid, (error, uuid) => token = @_generateToken() hashedToken = @hashToken {uuid, token} return callback new Error 'Unable to hash token' unless hashedToken? @_storeHashedToken { uuid, hashedToken, metadata, expiresOn, root }, (error) => return callback error if error? callback null, token hashToken: ({uuid, token}) => return unless uuid? and token? hasher = crypto.createHash 'sha256' hasher.update token hasher.update uuid hasher.update @pepper hasher.digest 'base64' search: ({uuid, query, projection}, callback) => return callback new Error 'Missing uuid' unless uuid? query ?= {} projection ?= {} secureQuery = _.clone query secureQuery.uuid = uuid options = limit: 1000 maxTimeMS: 2000 sort: {_id: -1} @datastore.find secureQuery, projection, options, (error, tokens) => return callback error if error? results = _.map tokens, (token) => _.omit token, ['hashedToken'] callback null, results storeToken: ({ uuid, token, expiresOn, root }, callback) => @uuidAliasResolver.resolve uuid, (error, uuid) => return callback error if error? hashedToken = @hashToken {uuid, token} return callback new Error 'Unable to hash token' unless hashedToken? @_storeHashedToken { uuid, hashedToken, expiresOn, root }, callback removeRootToken: ({uuid}, callback) => @uuidAliasResolver.resolve uuid, (error, uuid) => return callback error if error? @datastore.remove {uuid, root: true}, callback revokeToken: ({uuid, token}, callback) => @uuidAliasResolver.resolve uuid, (error, uuid) => return callback error if error? hashedToken = @hashToken {uuid, token} return callback new Error 'Unable to hash token' unless hashedToken? @datastore.remove { uuid, hashedToken }, (error) => return callback error if error? callback null, true revokeTokenByQuery: ({uuid, query}, callback) => @uuidAliasResolver.resolve uuid, (error, uuid) => return callback error if error? removeQuery = { uuid } _.each query, (value, key) => removeQuery["metadata.#{key}"] = value @datastore.remove removeQuery, (error) => return callback error if error? callback null, true verifyToken: ({ uuid, token }, callback) => return callback null, false unless uuid? and token? @uuidAliasResolver.resolve uuid, (error, uuid) => return callback error if error? @_verifyHashedToken { uuid, token }, callback _generateToken: => return crypto.createHash('sha1').update((new Date()).valueOf().toString() + Math.random().toString()).digest('hex') # Becuase I didn't want to make a breaking change _hashToken: ({ uuid, token }) => return @hashToken({ uuid, token }) _storeHashedToken: ({ uuid, hashedToken, metadata, expiresOn, root }, callback) => record = { uuid, hashedToken } return callback new Error('expires on must be a date') if expiresOn? && !_.isDate(expiresOn) record.expiresOn = expiresOn if expiresOn? record.root = root if root record.metadata = metadata if _.isPlainObject metadata record.metadata ?= {} @datastore.findOne { uuid, hashedToken }, { uuid: true }, (error, found) => return callback error if error? return @datastore.insert record, callback unless found? @datastore.update { uuid, hashedToken }, { $set: record }, callback _verifyHashedToken: ({ uuid, token }, callback) => hashedToken = @hashToken { uuid, token } return callback new Error 'Unable to hash token' unless hashedToken? query = { uuid, hashedToken } @datastore.findOne query, { uuid: true }, (error, record) => return callback error if error? return callback null, false unless record? return callback null, true unless record.expiresOn? @datastore.remove query, (error) => return callback error if error? return callback null, true module.exports = TokenManager