UNPKG

deep-security

Version:
389 lines (306 loc) 9.97 kB
/** * Created by mgoria on 11/6/15. */ /* eslint-disable no-unused-vars */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.TokenManager = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _awsSdk = require('aws-sdk'); var _awsSdk2 = _interopRequireDefault(_awsSdk); var _deepCore = require('deep-core'); var _deepCore2 = _interopRequireDefault(_deepCore); var _amazonCognitoJs = require('amazon-cognito-js'); var _amazonCognitoJs2 = _interopRequireDefault(_amazonCognitoJs); var _CreateCognitoDatasetException = require('./Exception/CreateCognitoDatasetException'); var _PutCognitoRecordException = require('./Exception/PutCognitoRecordException'); var _SynchronizeCognitoDatasetException = require('./Exception/SynchronizeCognitoDatasetException'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } let TokenManager = exports.TokenManager = function () { _createClass(TokenManager, null, [{ key: 'DATASET_NAME', /** * @returns {String} */ get: function get() { return 'deep_session'; } /** * @returns {String} */ }, { key: 'RECORD_NAME', get: function get() { return 'session_creds'; } /** * @param {String} identityPoolId * @param {Object|null} cognitoSyncClient */ }]); function TokenManager(identityPoolId) { let cognitoSyncClient = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; _classCallCheck(this, TokenManager); this._identityPoolId = identityPoolId; this._cognitoSyncClient = cognitoSyncClient; this._lastSyncedEntry = null; this._syncInProgress = false; } /** * @returns {Object} */ _createClass(TokenManager, [{ key: 'saveToken', /** * @param {Token} token * @returns {Promise} */ value: function saveToken(token) { return new Promise((resolve, reject) => { this._createOrGetDataset((error, dataset) => { if (error) { return reject(error); } let encodedToken = this._encodeToken(token); if (this._lastSyncedEntry === encodedToken || this._syncInProgress) { return resolve(); } this._syncInProgress = true; this._lastSyncedEntry = encodedToken; dataset.put(TokenManager.RECORD_NAME, this._encodeToken(token), (error /*, record*/) => { if (error) { return reject(new _PutCognitoRecordException.PutCognitoRecordException(TokenManager.DATASET_NAME, TokenManager.RECORD_NAME, error)); } this._synchronizeDataset(dataset, (error, savedRecords) => { this._syncInProgress = false; if (error) { return reject(new _SynchronizeCognitoDatasetException.SynchronizeCognitoDatasetException(dataset, error)); } resolve(savedRecords); }); }); }); }); } /** * @param {String} identityId * @returns {Promise} */ }, { key: 'loadBackendToken', value: function loadBackendToken(identityId) { let cognitosync = new _awsSdk2.default.CognitoSync({ credentials: _deepCore2.default.AWS.ENV_CREDENTIALS }); let params = { DatasetName: TokenManager.DATASET_NAME, IdentityId: identityId, IdentityPoolId: this._identityPoolId }; return cognitosync.listRecords(params).promise().then(data => { let token = null; data.Records.forEach(record => { if (record.Key === TokenManager.RECORD_NAME) { token = this._decodeToken(record.Value); return token; } }); return token; }); } /** * @returns {Promise} */ }, { key: 'loadFrontendToken', value: function loadFrontendToken() { return new Promise((resolve, reject) => { this._createOrGetDataset((error, dataset) => { if (error) { return reject(error); } dataset.get(TokenManager.RECORD_NAME, (error, rawToken) => { if (error) { return reject(error); } resolve(this._decodeToken(rawToken)); }); }); }); } /** * @returns {String} */ }, { key: 'deleteToken', /** * Deletes cached Token from local storage * * @returns {TokenManager} */ value: function deleteToken() { this.cognitoSyncClient.wipeData(); return this; } /** * @param {Function} callback * @private */ }, { key: '_createOrGetDataset', value: function _createOrGetDataset(callback) { this.cognitoSyncClient.openOrCreateDataset(TokenManager.DATASET_NAME, (error, dataset) => { if (error) { callback(new _CreateCognitoDatasetException.CreateCognitoDatasetException(TokenManager.DATASET_NAME, error), null); return; } callback(null, dataset); }); } /** * @param {Object} dataset * @param {Function} callback * @private */ }, { key: '_synchronizeDataset', value: function _synchronizeDataset(dataset, callback) { dataset.synchronize({ onSuccess: (dataset, newRecords) => { callback(null, newRecords); }, onFailure: error => { callback(error, null); }, onConflict: (dataset, conflicts, cb) => { let resolved = []; for (let i = 0; i < conflicts.length; i++) { // take local version. @todo: implement custom merge logic to take latest changes resolved.push(conflicts[i].resolveWithLocalRecord()); } dataset.resolve(resolved, () => { return cb(true); }); }, onDatasetDeleted: (dataset, datasetName, cb) => { return cb(true); }, onDatasetMerged: (dataset, datasetNames, cb) => { return cb(true); } }); } /** * @todo: implement an encoding method * * @param {Token} token * @returns {String} */ }, { key: '_encodeToken', value: function _encodeToken(token) { return JSON.stringify(token.toJSON()); } /** * @todo: implement a decoding method * * @param {String} rawToken * @returns {Object} */ }, { key: '_decodeToken', value: function _decodeToken(rawToken) { if (rawToken && typeof rawToken === 'string') { try { let tokenObj = JSON.parse(rawToken); tokenObj.credentials = this._decodeCredentials(tokenObj.credentials); tokenObj.credentials.params = { IdentityId: tokenObj.identityId, IdentityPoolId: this._identityPoolId }; for (let key in tokenObj.rolesCredentials) { if (tokenObj.rolesCredentials.hasOwnProperty(key)) { tokenObj.rolesCredentials[key] = this._decodeCredentials(tokenObj.rolesCredentials[key]); } } return tokenObj; } catch (e) { return null; } } return null; } /** * @todo: implement a decoding method * * @param {Object} credentials * @returns {Object} */ }, { key: '_decodeCredentials', value: function _decodeCredentials(credentials) { let expireTime = credentials.expireTime; credentials = new _awsSdk2.default.Credentials(credentials); // restore expireTime because AWS.Credentials resets it to null credentials.expireTime = expireTime; // set secretAccessKey property enumerable:true to allow storing it into Cognito datastore credentials = this._makeKeyEnumerable(credentials, 'secretAccessKey'); return credentials; } /** * @param {Object} obj * @param {String} key * @returns {Object} * @private */ }, { key: '_makeKeyEnumerable', value: function _makeKeyEnumerable(obj, key) { obj = Object.defineProperty(obj, key, { enumerable: true, writable: true, configurable: true }); return obj; } /** * @returns {Boolean} * @private */ }, { key: '_isLocalStorageAvailable', value: function _isLocalStorageAvailable() { try { if (window && window.localStorage) { window.localStorage.setItem('key', 'value'); window.localStorage.removeItem('key'); return true; } return false; } catch (e) { return false; } } }, { key: 'cognitoSyncClient', get: function get() { if (!this._cognitoSyncClient) { let options = {}; if (!this._isLocalStorageAvailable()) { options.DataStore = _awsSdk2.default.CognitoSyncManager.StoreInMemory; } this._cognitoSyncClient = new _awsSdk2.default.CognitoSyncManager(options); } return this._cognitoSyncClient; } }, { key: 'identityId', get: function get() { return this.cognitoSyncClient.getIdentityId(); } }]); return TokenManager; }();