UNPKG

mongoscope-client

Version:
116 lines (95 loc) 3.17 kB
var request = require('superagent'), util = require('util'), EventEmitter = require('events').EventEmitter, debug = require('debug')('mongoscope:client:token'); module.exports = Token; function Token(config){ if(!(this instanceof Token)) return new Token(config); this.config = config; this.expirationRedLine = 15 * 1000; this.session = {}; this.readable = false; process.nextTick(function(){ this.bake(function(err, res){ if(err) return this.emit('error', err); this.session = res; this.schedule(); this.readable = true; debug('emit readable!'); this.emit('readable'); }.bind(this)); }.bind(this)); } util.inherits(Token, EventEmitter); Token.prototype.toString = function(){ return this.session.token; }; Object.defineProperty(Token.prototype, 'token', {get: function(){ return this.session.token; }}); var defaultFn = function(err){ if(err) return console.error(err); }; Token.prototype.close = function(fn){ fn = fn || defaultFn; clearTimeout(this.refreshTimeout); debug('closing token'); request.del(this.config.scope + '/api/v1/token') .set('Accept', 'application/json') .set('Authorization', 'Bearer ' + this.session.token) .end(function(err, res){ debug('response from token close'); fn(err, res); }); }; Token.prototype.bake = function(done){ var payload = { seed: this.config.seed }; if(this.config.timeout) payload.timeout = this.config.timeout; if(this.config.auth){ Object.keys(this.config.auth).map(function(name){ var service = this.config.auth[name]; Object.keys(service).map(function(key){ payload[name + '_' + key] = service[key]; }); }.bind(this)); } debug('getting token for', this.config.seed, payload); request.post(this.config.scope + '/api/v1/token') .send(payload) .set('Accept', 'application/json') .end(function(err, res){ if(err) return done(err); if(!err && res.status >= 400){ err = new Error(res.body ? res.body.message : res.text); err.code = res.status; Error.captureStackTrace(err, Token.prototype.bake); return done(err); } if(!res.body.expires_at || !res.body.created_at){ return done(new Error('Malformed response. Missing expires_at or created_at')); } if(new Date(res.body.expires_at) - Date.now() < (1 * 60 * 1000)){ return done(new Error('Got an expires that is less than a minute from now.')); } done(null, res.body); }.bind(this)); }; Token.prototype.refresh = function(){ this.bake(function(err, res){ if(err) return this.emit('error', err); if(!res) return this.emit('error', new Error('Empty response with no error')); this.session = res; debug('token refreshed successfully'); return this.schedule(); }.bind(this)); }; Token.prototype.schedule = function(){ if(!this.session){ console.warn('Session nuked but timeout not cleared'); return this; } var ms = (new Date(this.session.expires_at) - Date.now()) - this.expirationRedLine; this.refreshTimeout = setTimeout(this.refresh.bind(this), ms); };