UNPKG

jsforce2

Version:

Salesforce API Library for JavaScript

242 lines (219 loc) 6.12 kB
/** * @file Browser client connection management class * @author Shinichi Tomita <shinichi.tomita@gmail.com> */ 'use strict'; var events = require('events'), inherits = require('inherits'), qs = require('querystring'), _ = require('lodash/core'), Connection = require('../connection'), OAuth2 = require('../oauth2'); /** * @private */ function popupWin(url, w, h) { var left = (screen.width/2)-(w/2); var top = (screen.height/2)-(h/2); return window.open(url, null, 'location=yes,toolbar=no,status=no,menubar=no,width='+w+',height='+h+',top='+top+',left='+left); } function handleCallbackResponse() { var res = checkCallbackResponse(); var state = localStorage.getItem('jsforce_state'); if (res && state && res.body.state === state) { localStorage.removeItem('jsforce_state'); var states = state.split('.'); var prefix = states[0], promptType = states[1]; var cli = new Client(prefix); if (res.success) { cli._storeTokens(res.body); location.hash = ''; } else { cli._storeError(res.body); } if (promptType === 'popup') { window.close(); } return true; } } /** * @private */ function checkCallbackResponse() { var params; if (window.location.hash) { params = qs.parse(window.location.hash.substring(1)); if (params.access_token) { return { success: true, body: params }; } } else if (window.location.search) { params = qs.parse(window.location.search.substring(1)); if (params.error) { return { success: false, body: params }; } } } /** @private **/ var clientIdx = 0; /** * @class * @todo add document */ var Client = function(prefix) { this._prefix = prefix || 'jsforce' + clientIdx++; this.connection = null; }; inherits(Client, events.EventEmitter); /** * */ Client.prototype.init = function(config) { if (handleCallbackResponse()) { return; } this.config = config; this.connection = new Connection(config); var tokens = this._getTokens(); if (tokens) { this.connection.initialize(tokens); var self = this; setTimeout(function() { self.emit('connect', self.connection); }, 10); } }; /** * */ Client.prototype.login = function(options, callback) { if (_.isFunction(options)) { callback = options; options = {}; } options = options || {}; callback = callback || function(){ }; _.extend(options, this.config); var self = this; this._prompt(options, callback); }; Client.prototype._prompt = function(options, callback) { var self = this; var oauth2 = new OAuth2(options); var rand = Math.random().toString(36).substring(2); var state = [ this._prefix, "popup", rand ].join('.'); localStorage.setItem("jsforce_state", state); var authzUrl = oauth2.getAuthorizationUrl({ response_type: 'token', scope : options.scope, state: state }); var size = options.size || {}; var pw = popupWin(authzUrl, size.width || 912, size.height || 513); if (!pw) { state = [ this._prefix, "redirect", rand ].join('.'); localStorage.setItem("jsforce_state", state); authzUrl = oauth2.getAuthorizationUrl({ response_type: 'token', scope : options.scope, state: state }); location.href = authzUrl; return; } self._removeTokens(); var pid = setInterval(function() { try { if (!pw || pw.closed) { clearInterval(pid); var tokens = self._getTokens(); if (tokens) { self.connection.initialize(tokens); self.emit('connect', self.connection); callback(null, { status: 'connect' }); } else { var err = self._getError(); if (err) { callback(new Error(err.error + ": " + err.error_description)); } else { callback(null, { status: 'cancel' }); } } } } catch(e) {} }, 1000); }; /** * */ Client.prototype.isLoggedIn = function() { return !!(this.connection && this.connection.accessToken); }; /** * */ Client.prototype.logout = function() { this.connection.logout(); this._removeTokens(); this.emit('disconnect'); }; /** * @private */ Client.prototype._getTokens = function() { var regexp = new RegExp("(^|;\\s*)"+this._prefix+"_loggedin=true(;|$)"); if (document.cookie.match(regexp)) { var issuedAt = Number(localStorage.getItem(this._prefix+'_issued_at')); if (Date.now() < issuedAt + 2 * 60 * 60 * 1000) { // 2 hours var userInfo; var idUrl = localStorage.getItem(this._prefix + '_id'); if (idUrl) { var ids = idUrl.split('/'); userInfo = { id: ids.pop(), organizationId: ids.pop(), url: idUrl }; } return { accessToken: localStorage.getItem(this._prefix + '_access_token'), instanceUrl: localStorage.getItem(this._prefix + '_instance_url'), userInfo: userInfo }; } } return null; }; /** * @private */ Client.prototype._storeTokens = function(params) { localStorage.setItem(this._prefix + '_access_token', params.access_token); localStorage.setItem(this._prefix + '_instance_url', params.instance_url); localStorage.setItem(this._prefix + '_issued_at', params.issued_at); localStorage.setItem(this._prefix + '_id', params.id); document.cookie = this._prefix + '_loggedin=true;'; }; /** * @private */ Client.prototype._removeTokens = function() { localStorage.removeItem(this._prefix + '_access_token'); localStorage.removeItem(this._prefix + '_instance_url'); localStorage.removeItem(this._prefix + '_issued_at'); localStorage.removeItem(this._prefix + '_id'); document.cookie = this._prefix + '_loggedin='; }; /** * @private */ Client.prototype._getError = function() { try { var err = JSON.parse(localStorage.getItem(this._prefix + '_error')); localStorage.removeItem(this._prefix + '_error'); return err; } catch(e) {} }; /** * @private */ Client.prototype._storeError = function(err) { localStorage.setItem(this._prefix + '_error', JSON.stringify(err)); }; /** * */ module.exports = new Client(); module.exports.Client = Client;