diff --git a/.babelrc b/.babelrc index b7c78e4..1acc235 100644 --- a/.babelrc +++ b/.babelrc @@ -1,7 +1,7 @@ { "presets": [ [ - "es2015", + "@babel/preset-env", { "modules": false } diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..302e8e6 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "useTabs": false, + "printWidth": 80, + "arrowParens": "avoid" +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..24da136 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# Code of Conduct + +Don't be an asshole. diff --git a/bower.json b/bower.json index 29acd4d..1972fa3 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "vue-authenticate", - "version": "1.3.5-beta.1", + "version": "1.5.0", "main": "dist/vue-authenticate.js", "homepage": "https://github.com/dgrubelic/vue-authenticate", "ignore": [] diff --git a/build/build.js b/build/build.js deleted file mode 100644 index 5e80d6d..0000000 --- a/build/build.js +++ /dev/null @@ -1,64 +0,0 @@ -var fs = require('fs'); -var rollup = require('rollup'); -var uglify = require('uglify-js'); -var buble = require('rollup-plugin-buble'); -var package = require('../package.json'); -var banner = - "/*!\n" + - " * vue-authenticate v" + package.version + "\n" + - " * https://github.com/dgrubelic/vue-authenticate\n" + - " * Released under the MIT License.\n" + - " */\n"; - -rollup.rollup({ - entry: 'src/index.js', - plugins: [buble()] -}) -.then(function (bundle) { - return write('dist/vue-authenticate.js', bundle.generate({ - format: 'umd', - banner: banner, - moduleName: 'VueAuthenticate' - }).code, bundle); -}) -.then(function (bundle) { - return write('dist/vue-authenticate.min.js', - banner + '\n' + uglify.minify('dist/vue-authenticate.js').code, - bundle); -}) -.then(function (bundle) { - return write('dist/vue-authenticate.es2015.js', bundle.generate({ - format: 'es', - banner: banner, - footer: 'export { VueAuthenticate };' - }).code, bundle); -}) -.then(function (bundle) { - return write('dist/vue-authenticate.common.js', bundle.generate({ - format: 'cjs', - banner: banner - }).code, bundle); -}) -.catch(logError); - -function write(dest, code, bundle) { - return new Promise(function (resolve, reject) { - fs.writeFile(dest, code, function (err) { - if (err) return reject(err); - console.log(blue(dest) + ' ' + getSize(code)); - resolve(bundle); - }); - }); -} - -function getSize(code) { - return (code.length / 1024).toFixed(2) + 'kb'; -} - -function logError(e) { - console.log(e); -} - -function blue(str) { - return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'; -} \ No newline at end of file diff --git a/build/build.rollup.js b/build/build.rollup.js new file mode 100644 index 0000000..fadee9d --- /dev/null +++ b/build/build.rollup.js @@ -0,0 +1,83 @@ +var fs = require('fs'); +var rollup = require('rollup'); +var uglify = require('uglify-js'); +var buble = require('@rollup/plugin-buble'); +var uglify = require('rollup-plugin-uglify').uglify; +var rollupBanner = require('rollup-plugin-banner').default; +var package = require('../package.json'); + +var banner = + 'vue-authenticate v' + + package.version + + '\n' + + 'https://github.com/dgrubelic/vue-authenticate/n' + + 'Released under the MIT License.\n'; + +function buildSource(inputOptions, outputOptions) { + rollup + .rollup(inputOptions) + .then(function (bundle) { + return bundle.generate(outputOptions).then(function (output) { + bundle.write(outputOptions); + }); + }) + .catch(logError); +} + +buildSource( + { + input: 'src/index.js', + plugins: [buble(), rollupBanner(banner)], + }, + { + file: 'dist/vue-authenticate.js', + format: 'umd', + name: 'VueAuthenticate', + } +); + +buildSource( + { + input: 'src/index.js', + plugins: [buble(), uglify(), rollupBanner(banner)], + }, + { + file: 'dist/vue-authenticate.min.js', + format: 'umd', + name: 'VueAuthenticate', + } +); + +buildSource( + { + input: 'src/index.js', + plugins: [rollupBanner(banner)], + }, + { + file: 'dist/vue-authenticate.esm.js', + format: 'es', + } +); + +buildSource( + { + input: 'src/index.js', + plugins: [rollupBanner(banner)], + }, + { + file: 'dist/vue-authenticate.common.js', + format: 'cjs', + } +); + +function logError(e) { + console.error(e); +} + +function getSize(code) { + return (((code && code.length) || 0) / 1024).toFixed(2) + 'kb'; +} + +function blue(str) { + return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'; +} diff --git a/dist/vue-authenticate.common.js b/dist/vue-authenticate.common.js index 02c2cf9..63d1b55 100644 --- a/dist/vue-authenticate.common.js +++ b/dist/vue-authenticate.common.js @@ -1,16 +1,14 @@ -/*! - * vue-authenticate v1.3.5-beta.1 +/** + * vue-authenticate v1.5.0 * https://github.com/dgrubelic/vue-authenticate * Released under the MIT License. + * */ 'use strict'; if (typeof Object.assign != 'function') { - Object.assign = function(target, varArgs) { - 'use strict'; - var arguments$1 = arguments; - + Object.assign = function (target, varArgs) { if (target == null) { throw new TypeError('Cannot convert undefined or null to object'); } @@ -18,9 +16,10 @@ if (typeof Object.assign != 'function') { var to = Object(target); for (var index = 1; index < arguments.length; index++) { - var nextSource = arguments$1[index]; + var nextSource = arguments[index]; - if (nextSource != null) { // Skip over if undefined or null + if (nextSource != null) { + // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { @@ -34,33 +33,33 @@ if (typeof Object.assign != 'function') { } function camelCase(name) { - return name.replace(/([\:\-\_]+(.))/g, function (_, separator, letter, offset) { + return name.replace(/([\:\-\_]+(.))/g, function ( + _, + separator, + letter, + offset + ) { return offset ? letter.toUpperCase() : letter; }); } function isUndefined(value) { - return typeof value === 'undefined' + return typeof value === 'undefined'; } - - function isObject(value) { - return value !== null && typeof value === 'object' + return value !== null && typeof value === 'object'; } function isString(value) { - return typeof value === 'string' + return typeof value === 'string'; } - - function isFunction(value) { - return typeof value === 'function' + return typeof value === 'function'; } function objectExtend(a, b) { - // Don't touch 'null' or 'undefined' objects. if (a == null || b == null) { return a; @@ -83,10 +82,10 @@ function objectExtend(a, b) { /** * Assemble url from two segments - * + * * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {String} baseUrl Base url * @param {String} url URI * @return {String} @@ -95,8 +94,8 @@ function joinUrl(baseUrl, url) { if (/^(?:[a-z]+:)?\/\//i.test(url)) { return url; } - var joined = [baseUrl, url].join('/'); - var normalize = function (str) { + let joined = [baseUrl, url].join('/'); + let normalize = function (str) { return str .replace(/[\/]+/g, '/') .replace(/\/\?/g, '?') @@ -108,38 +107,45 @@ function joinUrl(baseUrl, url) { /** * Get full path based on current location - * + * * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {Location} location * @return {String} */ function getFullUrlPath(location) { - var isHttps = location.protocol === 'https:'; - return location.protocol + '//' + location.hostname + - ':' + (location.port || (isHttps ? '443' : '80')) + - (/^\//.test(location.pathname) ? location.pathname : '/' + location.pathname); + const isHttps = location.protocol === 'https:'; + return ( + location.protocol + + '//' + + location.hostname + + ':' + + (location.port || (isHttps ? '443' : '80')) + + (/^\//.test(location.pathname) + ? location.pathname + : '/' + location.pathname) + ); } /** * Parse query string variables - * + * * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {String} Query string * @return {String} */ function parseQueryString(str) { - var obj = {}; - var key; - var value; - (str || '').split('&').forEach(function (keyValue) { + let obj = {}; + let key; + let value; + (str || '').split('&').forEach(keyValue => { if (keyValue) { value = keyValue.split('='); key = decodeURIComponent(value[0]); - obj[key] = (!!value[1]) ? decodeURIComponent(value[1]) : true; + obj[key] = !!value[1] ? decodeURIComponent(value[1]) : true; } }); return obj; @@ -149,12 +155,12 @@ function parseQueryString(str) { * Decode base64 string * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {String} str base64 encoded string * @return {Object} */ function decodeBase64(str) { - var buffer; + let buffer; if (typeof module !== 'undefined' && module.exports) { try { buffer = require('buffer').Buffer; @@ -163,87 +169,91 @@ function decodeBase64(str) { } } - var fromCharCode = String.fromCharCode; + let fromCharCode = String.fromCharCode; - var re_btou = new RegExp([ - '[\xC0-\xDF][\x80-\xBF]', - '[\xE0-\xEF][\x80-\xBF]{2}', - '[\xF0-\xF7][\x80-\xBF]{3}' - ].join('|'), 'g'); + let re_btou = new RegExp( + [ + '[\xC0-\xDF][\x80-\xBF]', + '[\xE0-\xEF][\x80-\xBF]{2}', + '[\xF0-\xF7][\x80-\xBF]{3}', + ].join('|'), + 'g' + ); - var cb_btou = function (cccc) { + let cb_btou = function (cccc) { switch (cccc.length) { case 4: - var cp = ((0x07 & cccc.charCodeAt(0)) << 18) - | ((0x3f & cccc.charCodeAt(1)) << 12) - | ((0x3f & cccc.charCodeAt(2)) << 6) - | (0x3f & cccc.charCodeAt(3)); - var offset = cp - 0x10000; - return (fromCharCode((offset >>> 10) + 0xD800) - + fromCharCode((offset & 0x3FF) + 0xDC00)); + let cp = + ((0x07 & cccc.charCodeAt(0)) << 18) | + ((0x3f & cccc.charCodeAt(1)) << 12) | + ((0x3f & cccc.charCodeAt(2)) << 6) | + (0x3f & cccc.charCodeAt(3)); + let offset = cp - 0x10000; + return ( + fromCharCode((offset >>> 10) + 0xd800) + + fromCharCode((offset & 0x3ff) + 0xdc00) + ); case 3: return fromCharCode( - ((0x0f & cccc.charCodeAt(0)) << 12) - | ((0x3f & cccc.charCodeAt(1)) << 6) - | (0x3f & cccc.charCodeAt(2)) + ((0x0f & cccc.charCodeAt(0)) << 12) | + ((0x3f & cccc.charCodeAt(1)) << 6) | + (0x3f & cccc.charCodeAt(2)) ); default: return fromCharCode( - ((0x1f & cccc.charCodeAt(0)) << 6) - | (0x3f & cccc.charCodeAt(1)) + ((0x1f & cccc.charCodeAt(0)) << 6) | (0x3f & cccc.charCodeAt(1)) ); } }; - var btou = function (b) { + let btou = function (b) { return b.replace(re_btou, cb_btou); }; - var _decode = buffer ? function (a) { - return (a.constructor === buffer.constructor - ? a : new buffer(a, 'base64')).toString(); - } + let _decode = buffer + ? function (a) { + return (a.constructor === buffer.constructor + ? a + : new buffer(a, 'base64') + ).toString(); + } : function (a) { - return btou(atob(a)); - }; + return btou(atob(a)); + }; return _decode( - String(str).replace(/[-_]/g, function (m0) { - return m0 === '-' ? '+' : '/'; - }) + String(str) + .replace(/[-_]/g, function (m0) { + return m0 === '-' ? '+' : '/'; + }) .replace(/[^A-Za-z0-9\+\/]/g, '') ); } -function parseCookies(str) { - if (str.length === 0) { return {}; } - var parsed = {}; - var pattern = new RegExp('\\s*;\\s*'); - str.split(pattern).forEach(function (i) { - var ref = i.split('='); - var encodedKey = ref[0]; - var encodedValue = ref[1]; - var key = decodeURIComponent(encodedKey); - var value = decodeURIComponent(encodedValue); +function parseCookies(str = '') { + if (str.length === 0) return {}; + const parsed = {}; + const pattern = new RegExp('\\s*;\\s*'); + str.split(pattern).forEach(i => { + const [encodedKey, encodedValue] = i.split('='); + const key = decodeURIComponent(encodedKey); + const value = decodeURIComponent(encodedValue); parsed[key] = value; }); return parsed; } function formatOptions(options) { - var path = options.path; - var domain = options.domain; - var expires = options.expires; - var secure = options.secure; + const { path, domain, expires, secure } = options; return [ - typeof path === 'undefined' || path === null - ? '' : ';path=' + path, - typeof domain === 'undefined' || domain === null - ? '' : ';domain=' + domain, + typeof path === 'undefined' || path === null ? '' : ';path=' + path, + typeof domain === 'undefined' || domain === null ? '' : ';domain=' + domain, typeof expires === 'undefined' || expires === null - ? '' : ';expires=' + expires.toUTCString(), + ? '' + : ';expires=' + expires.toUTCString(), typeof secure === 'undefined' || secure === null || secure === false - ? '' : ';secure' + ? '' + : ';secure', ].join(''); } @@ -252,10 +262,29 @@ function formatCookie(key, value, options) { encodeURIComponent(key), '=', encodeURIComponent(value), - formatOptions(options) + formatOptions(options), ].join(''); } +function getObjectProperty(objectRef, propertyName) { + let value = undefined; + let valueRef = objectRef; + const propNames = propertyName.split('.'); + + for (var i = 0; i < propNames.length; i++) { + const key = propNames[i]; + value = valueRef[key]; + + if (isObject(value)) { + valueRef = valueRef[key]; + } else { + break; + } + } + + return value; +} + // Store setTimeout reference so promise-polyfill will be unaffected by // other code modifying setTimeout (like sinon.useFakeTimers()) var setTimeoutFunc = setTimeout; @@ -270,8 +299,9 @@ function bind(fn, thisArg) { } function Promise$1(fn) { - if (typeof this !== 'object') { throw new TypeError('Promises must be constructed via new'); } - if (typeof fn !== 'function') { throw new TypeError('not a function'); } + if (typeof this !== 'object') + throw new TypeError('Promises must be constructed via new'); + if (typeof fn !== 'function') throw new TypeError('not a function'); this._state = 0; this._handled = false; this._value = undefined; @@ -309,8 +339,12 @@ function handle(self, deferred) { function resolve(self, newValue) { try { // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure - if (newValue === self) { throw new TypeError('A promise cannot be resolved with itself.'); } - if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { + if (newValue === self) + throw new TypeError('A promise cannot be resolved with itself.'); + if ( + newValue && + (typeof newValue === 'object' || typeof newValue === 'function') + ) { var then = newValue.then; if (newValue instanceof Promise$1) { self._state = 3; @@ -338,7 +372,7 @@ function reject(self, newValue) { function finale(self) { if (self._state === 2 && self._deferreds.length === 0) { - Promise$1._immediateFn(function() { + Promise$1._immediateFn(function () { if (!self._handled) { Promise$1._unhandledRejectionFn(self._value); } @@ -366,17 +400,20 @@ function Handler(onFulfilled, onRejected, promise) { function doResolve(fn, self) { var done = false; try { - fn(function (value) { - if (done) { return; } - done = true; - resolve(self, value); - }, function (reason) { - if (done) { return; } - done = true; - reject(self, reason); - }); + fn( + function (value) { + if (done) return; + done = true; + resolve(self, value); + }, + function (reason) { + if (done) return; + done = true; + reject(self, reason); + } + ); } catch (ex) { - if (done) { return; } + if (done) return; done = true; reject(self, ex); } @@ -387,7 +424,7 @@ Promise$1.prototype['catch'] = function (onRejected) { }; Promise$1.prototype.then = function (onFulfilled, onRejected) { - var prom = new (this.constructor)(noop); + var prom = new this.constructor(noop); handle(this, new Handler(onFulfilled, onRejected, prom)); return prom; @@ -397,7 +434,7 @@ Promise$1.all = function (arr) { var args = Array.prototype.slice.call(arr); return new Promise$1(function (resolve, reject) { - if (args.length === 0) { return resolve([]); } + if (args.length === 0) return resolve([]); var remaining = args.length; function res(i, val) { @@ -405,9 +442,13 @@ Promise$1.all = function (arr) { if (val && (typeof val === 'object' || typeof val === 'function')) { var then = val.then; if (typeof then === 'function') { - then.call(val, function (val) { - res(i, val); - }, reject); + then.call( + val, + function (val) { + res(i, val); + }, + reject + ); return; } } @@ -451,7 +492,11 @@ Promise$1.race = function (values) { }; // Use polyfill for setImmediate for performance gains -Promise$1._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) || +Promise$1._immediateFn = + (typeof setImmediate === 'function' && + function (fn) { + setImmediate(fn); + }) || function (fn) { setTimeoutFunc(fn, 0); }; @@ -480,9 +525,37 @@ Promise$1._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { Promise$1._unhandledRejectionFn = fn; }; +const fakeDocument = { + createElement() { }, +}; + +const fakeWindow = { + atob() { }, + open() { }, + location: {}, + localStorage: { + setItem() { }, + getItem() { }, + removeItem() { }, + }, + sessionStorage: { + setItem() { }, + getItem() { }, + removeItem() { }, + }, +}; + +const $document = (typeof document !== undefined) + ? document + : fakeDocument; + +const $window = (typeof window !== undefined) + ? window + : fakeWindow; + function getCookieDomainUrl() { try { - return window.location.hostname + return $window.location.hostname; } catch (e) {} return ''; @@ -490,9 +563,9 @@ function getCookieDomainUrl() { function getRedirectUri(uri) { try { - return (!isUndefined(uri)) - ? ("" + (window.location.origin) + uri) - : window.location.origin + return !isUndefined(uri) + ? `${$window.location.origin}${uri}` + : $window.location.origin; } catch (e) {} return uri || null; @@ -503,6 +576,7 @@ function getRedirectUri(uri) { */ var defaultOptions = { baseUrl: null, + tokenPath: 'access_token', tokenName: 'token', tokenPrefix: 'vueauth', tokenHeader: 'Authorization', @@ -515,7 +589,7 @@ var defaultOptions = { cookieStorage: { domain: getCookieDomainUrl(), path: '/', - secure: false + secure: false, }, requestDataKey: 'data', responseDataKey: 'data', @@ -525,17 +599,18 @@ var defaultOptions = { * @context {VueAuthenticate} */ bindRequestInterceptor: function ($auth) { - var tokenHeader = $auth.options.tokenHeader; + const tokenHeader = $auth.options.tokenHeader; - $auth.$http.interceptors.request.use(function (config) { + $auth.$http.interceptors.request.use(config => { if ($auth.isAuthenticated()) { config.headers[tokenHeader] = [ - $auth.options.tokenType, $auth.getToken() + $auth.options.tokenType, + $auth.getToken(), ].join(' '); } else { delete config.headers[tokenHeader]; } - return config + return config; }); }, @@ -543,14 +618,14 @@ var defaultOptions = { facebook: { name: 'facebook', url: '/auth/facebook', - authorizationEndpoint: 'https://www.facebook.com/v2.5/dialog/oauth', + authorizationEndpoint: 'https://www.facebook.com/v10.0/dialog/oauth', redirectUri: getRedirectUri('/'), requiredUrlParams: ['display', 'scope'], scope: ['email'], scopeDelimiter: ',', display: 'popup', oauthType: '2.0', - popupOptions: { width: 580, height: 400 } + popupOptions: { width: 580, height: 400 }, }, google: { @@ -565,7 +640,7 @@ var defaultOptions = { scopeDelimiter: ' ', display: 'popup', oauthType: '2.0', - popupOptions: { width: 452, height: 633 } + popupOptions: { width: 452, height: 633 }, }, github: { @@ -577,7 +652,7 @@ var defaultOptions = { scope: ['user:email'], scopeDelimiter: ' ', oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } + popupOptions: { width: 1020, height: 618 }, }, instagram: { @@ -589,7 +664,7 @@ var defaultOptions = { scope: ['basic'], scopeDelimiter: '+', oauthType: '2.0', - popupOptions: { width: null, height: null } + popupOptions: { width: null, height: null }, }, twitter: { @@ -598,7 +673,7 @@ var defaultOptions = { authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate', redirectUri: getRedirectUri(), oauthType: '1.0', - popupOptions: { width: 495, height: 645 } + popupOptions: { width: 495, height: 645 }, }, bitbucket: { @@ -610,7 +685,7 @@ var defaultOptions = { scope: ['email'], scopeDelimiter: ' ', oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } + popupOptions: { width: 1020, height: 618 }, }, linkedin: { @@ -623,7 +698,7 @@ var defaultOptions = { scopeDelimiter: ' ', state: 'STATE', oauthType: '2.0', - popupOptions: { width: 527, height: 582 } + popupOptions: { width: 527, height: 582 }, }, live: { @@ -636,7 +711,7 @@ var defaultOptions = { scopeDelimiter: ' ', display: 'popup', oauthType: '2.0', - popupOptions: { width: 500, height: 560 } + popupOptions: { width: 500, height: 560 }, }, oauth1: { @@ -645,7 +720,7 @@ var defaultOptions = { authorizationEndpoint: null, redirectUri: getRedirectUri(), oauthType: '1.0', - popupOptions: null + popupOptions: null, }, oauth2: { @@ -667,243 +742,261 @@ var defaultOptions = { responseParams: { code: 'code', clientId: 'clientId', - redirectUri: 'redirectUri' - } - } - } + redirectUri: 'redirectUri', + }, + }, + }, }; -var CookieStorage = function CookieStorage(defaultOptions) { - this._defaultOptions = objectExtend({ - domain: getCookieDomainUrl(), - expires: null, - path: '/', - secure: false - }, defaultOptions); -}; +class CookieStorage { + constructor(defaultOptions) { + this._defaultOptions = objectExtend( + { + domain: getCookieDomainUrl(), + expires: null, + path: '/', + secure: false, + }, + defaultOptions + ); + } -CookieStorage.prototype.setItem = function setItem (key, value) { - var options = objectExtend({}, this._defaultOptions); - var cookie = formatCookie(key, value, options); - this._setCookie(cookie); -}; + setItem(key, value) { + const options = objectExtend({}, this._defaultOptions); + const cookie = formatCookie(key, value, options); + this._setCookie(cookie); + } -CookieStorage.prototype.getItem = function getItem (key) { - var cookies = parseCookies(this._getCookie()); - return cookies.hasOwnProperty(key) ? cookies[key] : null; -}; + getItem(key) { + const cookies = parseCookies(this._getCookie()); + return cookies.hasOwnProperty(key) ? cookies[key] : null; + } -CookieStorage.prototype.removeItem = function removeItem (key) { - var value = ''; - var defaultOptions = objectExtend({}, this._defaultOptions); - var options = objectExtend(defaultOptions, { - expires: new Date(0) - }); - var cookie = formatCookie(key, value, options); - this._setCookie(cookie); -}; + removeItem(key) { + const value = ''; + const defaultOptions = objectExtend({}, this._defaultOptions); + const options = objectExtend(defaultOptions, { + expires: new Date(0), + }); + const cookie = formatCookie(key, value, options); + this._setCookie(cookie); + } -CookieStorage.prototype._getCookie = function _getCookie () { - try { - return typeof document === 'undefined' - ? '' : typeof document.cookie === 'undefined' - ? '' : document.cookie; - } catch (e) {} - - return ''; -}; + _getCookie() { + try { + return $document.cookie === 'undefined' ? '' : $document.cookie; + } catch (e) {} -CookieStorage.prototype._setCookie = function _setCookie (cookie) { - try { - document.cookie = cookie; - } catch (e) {} -}; + return ''; + } -var LocalStorage = function LocalStorage(namespace) { - this.namespace = namespace || null; -}; + _setCookie(cookie) { + try { + $document.cookie = cookie; + } catch (e) {} + } +} -LocalStorage.prototype.setItem = function setItem (key, value) { - window.localStorage.setItem(this._getStorageKey(key), value); -}; +class LocalStorage { + constructor(namespace) { + this.namespace = namespace || null; + } -LocalStorage.prototype.getItem = function getItem (key) { - return window.localStorage.getItem(this._getStorageKey(key)) -}; + setItem(key, value) { + $window.localStorage.setItem(this._getStorageKey(key), value); + } -LocalStorage.prototype.removeItem = function removeItem (key) { - window.localStorage.removeItem(this._getStorageKey(key)); -}; + getItem(key) { + return $window.localStorage.getItem(this._getStorageKey(key)); + } -LocalStorage.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') + removeItem(key) { + $window.localStorage.removeItem(this._getStorageKey(key)); } - return key; -}; -var MemoryStorage = function MemoryStorage(namespace) { - this.namespace = namespace || null; - this._storage = {}; -}; + _getStorageKey(key) { + if (this.namespace) { + return [this.namespace, key].join('.'); + } + return key; + } +} -MemoryStorage.prototype.setItem = function setItem (key, value) { - this._storage[this._getStorageKey(key)] = value; -}; +class MemoryStorage { + constructor(namespace) { + this.namespace = namespace || null; + this._storage = {}; + } -MemoryStorage.prototype.getItem = function getItem (key) { - return this._storage[this._getStorageKey(key)] -}; + setItem(key, value) { + this._storage[this._getStorageKey(key)] = value; + } -MemoryStorage.prototype.removeItem = function removeItem (key) { - delete this._storage[this._getStorageKey(key)]; -}; + getItem(key) { + return this._storage[this._getStorageKey(key)]; + } -MemoryStorage.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') + removeItem(key) { + delete this._storage[this._getStorageKey(key)]; } - return key; -}; -var LocalStorage$2 = function LocalStorage(namespace) { - this.namespace = namespace || null; -}; + _getStorageKey(key) { + if (this.namespace) { + return [this.namespace, key].join('.'); + } + return key; + } +} -LocalStorage$2.prototype.setItem = function setItem (key, value) { - window.sessionStorage.setItem(this._getStorageKey(key), value); -}; +class SessionStorage { + constructor(namespace) { + this.namespace = namespace || null; + } -LocalStorage$2.prototype.getItem = function getItem (key) { - return window.sessionStorage.getItem(this._getStorageKey(key)) -}; + setItem(key, value) { + $window.sessionStorage.setItem(this._getStorageKey(key), value); + } -LocalStorage$2.prototype.removeItem = function removeItem (key) { - window.sessionStorage.removeItem(this._getStorageKey(key)); -}; + getItem(key) { + return $window.sessionStorage.getItem(this._getStorageKey(key)); + } -LocalStorage$2.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') + removeItem(key) { + $window.sessionStorage.removeItem(this._getStorageKey(key)); } - return key; -}; + + _getStorageKey(key) { + if (this.namespace) { + return [this.namespace, key].join('.'); + } + return key; + } +} function StorageFactory(options) { switch (options.storageType) { case 'localStorage': try { - window.localStorage.setItem('testKey', 'test'); - window.localStorage.removeItem('testKey'); - return new LocalStorage(options.storageNamespace) - } catch(e) {} + $window.localStorage.setItem('testKey', 'test'); + $window.localStorage.removeItem('testKey'); + return new LocalStorage(options.storageNamespace); + } catch (e) {} case 'sessionStorage': try { - window.sessionStorage.setItem('testKey', 'test'); - window.sessionStorage.removeItem('testKey'); - return new LocalStorage$2(options.storageNamespace) + $window.sessionStorage.setItem('testKey', 'test'); + $window.sessionStorage.removeItem('testKey'); + return new SessionStorage(options.storageNamespace); } catch (e) {} - + case 'cookieStorage': return new CookieStorage(options.cookieStorage); - case 'memoryStorage': + case 'memoryStorage': default: - return new MemoryStorage(options.storageNamespace) - break; + return new MemoryStorage(options.storageNamespace); } } /** * OAuth2 popup management class - * + * * @author Sahat Yalkabov - * @copyright Class mostly taken from https://github.com/sahat/satellizer + * @copyright Class mostly taken from https://github.com/sahat/satellizer * and adjusted to fit vue-authenticate library */ -var OAuthPopup = function OAuthPopup(url, name, popupOptions) { - this.popup = null; - this.url = url; - this.name = name; - this.popupOptions = popupOptions; -}; - -OAuthPopup.prototype.open = function open (redirectUri, skipPooling) { - try { - this.popup = window.open(this.url, this.name, this._stringifyOptions()); - if (this.popup && this.popup.focus) { - this.popup.focus(); - } - - if (skipPooling) { - return Promise$1.resolve() - } else { - return this.pooling(redirectUri) - } - } catch(e) { - return Promise$1.reject(new Error('OAuth popup error occurred')) +class OAuthPopup { + constructor(url, name, popupOptions) { + this.popup = null; + this.url = url; + this.name = name; + this.popupOptions = popupOptions; } -}; - -OAuthPopup.prototype.pooling = function pooling (redirectUri) { - var this$1 = this; - return new Promise$1(function (resolve, reject) { - var redirectUriParser = document.createElement('a'); - redirectUriParser.href = redirectUri; - var redirectUriPath = getFullUrlPath(redirectUriParser); - - var poolingInterval = setInterval(function () { - if (!this$1.popup || this$1.popup.closed || this$1.popup.closed === undefined) { - clearInterval(poolingInterval); - poolingInterval = null; - reject(new Error('Auth popup window closed')); + open(redirectUri, skipPooling) { + try { + this.popup = $window.open(this.url, this.name, this._stringifyOptions()); + if (this.popup && this.popup.focus) { + this.popup.focus(); } - try { - var popupWindowPath = getFullUrlPath(this$1.popup.location); + if (skipPooling) { + return Promise$1.resolve(); + } else { + return this.pooling(redirectUri); + } + } catch (e) { + return Promise$1.reject(new Error('OAuth popup error occurred')); + } + } - if (popupWindowPath === redirectUriPath) { - if (this$1.popup.location.search || this$1.popup.location.hash) { - var query = parseQueryString(this$1.popup.location.search.substring(1).replace(/\/$/, '')); - var hash = parseQueryString(this$1.popup.location.hash.substring(1).replace(/[\/$]/, '')); - var params = objectExtend({}, query); - params = objectExtend(params, hash); + pooling(redirectUri) { + return new Promise$1((resolve, reject) => { + const redirectUriParser = $document.createElement('a'); + redirectUriParser.href = redirectUri; + const redirectUriPath = getFullUrlPath(redirectUriParser); + + let poolingInterval = setInterval(() => { + if ( + !this.popup || + this.popup.closed || + this.popup.closed === undefined + ) { + clearInterval(poolingInterval); + poolingInterval = null; + reject(new Error('Auth popup window closed')); + } - if (params.error) { - reject(new Error(params.error)); + try { + const popupWindowPath = getFullUrlPath(this.popup.location); + + if (popupWindowPath === redirectUriPath) { + if (this.popup.location.search || this.popup.location.hash) { + const query = parseQueryString( + this.popup.location.search.substring(1).replace(/\/$/, '') + ); + const hash = parseQueryString( + this.popup.location.hash.substring(1).replace(/[\/$]/, '') + ); + let params = objectExtend({}, query); + params = objectExtend(params, hash); + + if (params.error) { + reject(new Error(params.error)); + } else { + resolve(params); + } } else { - resolve(params); + reject( + new Error( + 'OAuth redirect has occurred but no query or hash parameters were found.' + ) + ); } - } else { - reject(new Error('OAuth redirect has occurred but no query or hash parameters were found.')); - } - clearInterval(poolingInterval); - poolingInterval = null; - this$1.popup.close(); + clearInterval(poolingInterval); + poolingInterval = null; + this.popup.close(); + } + } catch (e) { + // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame. } - } catch(e) { - // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame. - } - }, 250); - }) -}; - -OAuthPopup.prototype._stringifyOptions = function _stringifyOptions () { - var this$1 = this; + }, 250); + }); + } - var options = []; - for (var optionKey in this$1.popupOptions) { - if (!isUndefined(this$1.popupOptions[optionKey])) { - options.push((optionKey + "=" + (this$1.popupOptions[optionKey]))); + _stringifyOptions() { + let options = []; + for (var optionKey in this.popupOptions) { + if (!isUndefined(this.popupOptions[optionKey])) { + options.push(`${optionKey}=${this.popupOptions[optionKey]}`); + } } + return options.join(','); } - return options.join(',') -}; +} -var defaultProviderConfig = { +const defaultProviderConfig$1 = { name: null, url: null, authorizationEndpoint: null, @@ -914,107 +1007,125 @@ var defaultProviderConfig = { requiredUrlParams: null, defaultUrlParams: null, oauthType: '1.0', - popupOptions: {} + popupOptions: {}, }; -var OAuth = function OAuth($http, storage, providerConfig, options) { - this.$http = $http; - this.storage = storage; - this.providerConfig = objectExtend({}, defaultProviderConfig); - this.providerConfig = objectExtend(this.providerConfig, providerConfig); - this.options = options; -}; - -/** - * Initialize OAuth1 process - * @param{Object} userData User data - * @return {Promise} - */ -OAuth.prototype.init = function init (userData) { - var this$1 = this; +class OAuth { + constructor($http, storage, providerConfig, options) { + this.$http = $http; + this.storage = storage; + this.providerConfig = objectExtend({}, defaultProviderConfig$1); + this.providerConfig = objectExtend(this.providerConfig, providerConfig); + this.options = options; + } - this.oauthPopup = new OAuthPopup('about:blank', this.providerConfig.name, this.providerConfig.popupOptions); + /** + * Initialize OAuth1 process + * @param {Object} userData User data + * @return {Promise} + */ + init(userData) { + this.oauthPopup = new OAuthPopup( + 'about:blank', + this.providerConfig.name, + this.providerConfig.popupOptions + ); + + if (!$window['cordova']) { + this.oauthPopup.open(this.providerConfig.redirectUri, true); + } - if (window && !window['cordova']) { - this.oauthPopup.open(this.providerConfig.redirectUri, true); + return this.getRequestToken().then(response => { + return this.openPopup(response).then(popupResponse => { + return this.exchangeForToken(popupResponse, userData); + }); + }); } - return this.getRequestToken().then(function (response) { - return this$1.openPopup(response).then(function (popupResponse) { - return this$1.exchangeForToken(popupResponse, userData) - }) - }) -}; + /** + * Get OAuth1 request token + * @return {Promise} + */ + getRequestToken() { + let requestOptions = {}; + requestOptions.method = 'POST'; + requestOptions[this.options.requestDataKey] = objectExtend( + {}, + this.providerConfig + ); + requestOptions.withCredentials = this.options.withCredentials; + if (this.options.baseUrl) { + requestOptions.url = joinUrl( + this.options.baseUrl, + this.providerConfig.url + ); + } else { + requestOptions.url = this.providerConfig.url; + } -/** - * Get OAuth1 request token - * @return {Promise} - */ -OAuth.prototype.getRequestToken = function getRequestToken () { - var requestOptions = {}; - requestOptions.method = 'POST'; - requestOptions[this.options.requestDataKey] = objectExtend({}, this.providerConfig); - requestOptions.withCredentials = this.options.withCredentials; - if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - requestOptions.url = this.providerConfig.url; + return this.$http(requestOptions); } - return this.$http(requestOptions) -}; - -/** - * Open OAuth1 popup - * @param{Object} response Response object containing request token - * @return {Promise} - */ -OAuth.prototype.openPopup = function openPopup (response) { - var url = [this.providerConfig.authorizationEndpoint, this.buildQueryString(response[this.options.responseDataKey])].join('?'); - - this.oauthPopup.popup.location = url; - if (window && window['cordova']) { - return this.oauthPopup.open(this.providerConfig.redirectUri) - } else { - return this.oauthPopup.pooling(this.providerConfig.redirectUri) + /** + * Open OAuth1 popup + * @param {Object} response Response object containing request token + * @return {Promise} + */ + openPopup(response) { + const url = [ + this.providerConfig.authorizationEndpoint, + this.buildQueryString(response[this.options.responseDataKey]), + ].join('?'); + + this.oauthPopup.popup.location = url; + if ($window['cordova']) { + return this.oauthPopup.open(this.providerConfig.redirectUri); + } else { + return this.oauthPopup.pooling(this.providerConfig.redirectUri); + } } -}; -/** - * Exchange token and token verifier for access token - * @param{Object} oauth OAuth data containing token and token verifier - * @param{Object} userData User data - * @return {Promise} - */ -OAuth.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { - var payload = objectExtend({}, userData); - payload = objectExtend(payload, oauth); - var requestOptions = {}; - requestOptions.method = 'POST'; - requestOptions[this.options.requestDataKey] = payload; - requestOptions.withCredentials = this.options.withCredentials; - if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - requestOptions.url = this.providerConfig.url; + /** + * Exchange token and token verifier for access token + * @param {Object} oauth OAuth data containing token and token verifier + * @param {Object} userData User data + * @return {Promise} + */ + exchangeForToken(oauth, userData) { + let payload = objectExtend({}, userData); + payload = objectExtend(payload, oauth); + let requestOptions = {}; + requestOptions.method = 'POST'; + requestOptions[this.options.requestDataKey] = payload; + requestOptions.withCredentials = this.options.withCredentials; + if (this.options.baseUrl) { + requestOptions.url = joinUrl( + this.options.baseUrl, + this.providerConfig.url + ); + } else { + requestOptions.url = this.providerConfig.url; + } + return this.$http(requestOptions); } - return this.$http(requestOptions) -}; -OAuth.prototype.buildQueryString = function buildQueryString (params) { - var parsedParams = []; - for (var key in params) { - var value = params[key]; - parsedParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); + buildQueryString(params) { + const parsedParams = []; + for (var key in params) { + let value = params[key]; + parsedParams.push( + encodeURIComponent(key) + '=' + encodeURIComponent(value) + ); + } + return parsedParams.join('&'); } - return parsedParams.join('&'); -}; +} /** * Default provider configuration * @type {Object} */ -var defaultProviderConfig$1 = { +const defaultProviderConfig = { name: null, url: null, clientId: null, @@ -1030,371 +1141,463 @@ var defaultProviderConfig$1 = { responseParams: { code: 'code', clientId: 'clientId', - redirectUri: 'redirectUri' + redirectUri: 'redirectUri', }, oauthType: '2.0', - popupOptions: {} -}; - -var OAuth2 = function OAuth2($http, storage, providerConfig, options) { - this.$http = $http; - this.storage = storage; - this.providerConfig = objectExtend({}, defaultProviderConfig$1); - this.providerConfig = objectExtend(this.providerConfig, providerConfig); - this.options = options; + popupOptions: {}, }; -OAuth2.prototype.init = function init (userData) { - var this$1 = this; - - var stateName = this.providerConfig.name + '_state'; - if (isFunction(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state()); - } else if (isString(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state); +class OAuth2 { + constructor($http, storage, providerConfig, options) { + this.$http = $http; + this.storage = storage; + this.providerConfig = objectExtend({}, defaultProviderConfig); + this.providerConfig = objectExtend(this.providerConfig, providerConfig); + this.options = options; } - var url = [this.providerConfig.authorizationEndpoint, this._stringifyRequestParams()].join('?'); + init(userData) { + let stateName = this.providerConfig.name + '_state'; + if (isFunction(this.providerConfig.state)) { + this.storage.setItem(stateName, this.providerConfig.state()); + } else if (isString(this.providerConfig.state)) { + this.storage.setItem(stateName, this.providerConfig.state); + } - this.oauthPopup = new OAuthPopup(url, this.providerConfig.name, this.providerConfig.popupOptions); - - return new Promise(function (resolve, reject) { - this$1.oauthPopup.open(this$1.providerConfig.redirectUri).then(function (response) { - if (this$1.providerConfig.responseType === 'token' || !this$1.providerConfig.url) { - return resolve(response) - } + let url = [ + this.providerConfig.authorizationEndpoint, + this._stringifyRequestParams(), + ].join('?'); + + this.oauthPopup = new OAuthPopup( + url, + this.providerConfig.name, + this.providerConfig.popupOptions + ); + + return new Promise((resolve, reject) => { + this.oauthPopup + .open(this.providerConfig.redirectUri) + .then(response => { + if ( + this.providerConfig.responseType === 'token' || + !this.providerConfig.url + ) { + return resolve(response); + } - if (response.state && response.state !== this$1.storage.getItem(stateName)) { - return reject(new Error('State parameter value does not match original OAuth request state value')) - } + if ( + response.state && + response.state !== this.storage.getItem(stateName) + ) { + return reject( + new Error( + 'State parameter value does not match original OAuth request state value' + ) + ); + } - resolve(this$1.exchangeForToken(response, userData)); - }).catch(function (err) { - reject(err); + resolve(this.exchangeForToken(response, userData)); + }) + .catch(err => { + reject(err); + }); }); - }) -}; - -/** - * Exchange temporary oauth data for access token - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param{[type]} oauth [description] - * @param{[type]} userData [description] - * @return {[type]} [description] - */ -OAuth2.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { - var this$1 = this; - - var payload = objectExtend({}, userData); - - for (var key in defaultProviderConfig$1.responseParams) { - var value = defaultProviderConfig$1[key]; - - switch(key) { - case 'code': - payload[key] = oauth.code; - break - case 'clientId': - payload[key] = this$1.providerConfig.clientId; - break - case 'redirectUri': - payload[key] = this$1.providerConfig.redirectUri; - break - default: - payload[key] = oauth[key]; - } - } - - if (oauth.state) { - payload.state = oauth.state; - } - - var exchangeTokenUrl; - if (this.options.baseUrl) { - exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - exchangeTokenUrl = this.providerConfig.url; } - return this.$http.post(exchangeTokenUrl, payload, { - withCredentials: this.options.withCredentials - }) -}; - -/** - * Stringify oauth params - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @return {String} - */ -OAuth2.prototype._stringifyRequestParams = function _stringifyRequestParams () { - var this$1 = this; - - var keyValuePairs = []; - var paramCategories = ['defaultUrlParams', 'requiredUrlParams', 'optionalUrlParams']; + /** + * Exchange temporary oauth data for access token + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {[type]} oauth [description] + * @param {[type]} userData [description] + * @return {[type]} [description] + */ + exchangeForToken(oauth, userData) { + let payload = objectExtend({}, userData); + + for (let key in this.providerConfig.responseParams) { + this.providerConfig.responseParams[key]; + + switch (key) { + case 'code': + payload[key] = oauth.code; + break; + case 'clientId': + payload[key] = this.providerConfig.clientId; + break; + case 'redirectUri': + payload[key] = this.providerConfig.redirectUri; + break; + default: + payload[key] = oauth[key]; + } + } - paramCategories.forEach(function (categoryName) { - if (!this$1.providerConfig[categoryName]) { return } - if (!Array.isArray(this$1.providerConfig[categoryName])) { return } + if (oauth.state) { + payload.state = oauth.state; + } - this$1.providerConfig[categoryName].forEach(function (paramName) { - var camelCaseParamName = camelCase(paramName); - var paramValue = isFunction(this$1.providerConfig[paramName]) ? this$1.providerConfig[paramName]() : this$1.providerConfig[camelCaseParamName]; + let exchangeTokenUrl; + if (this.options.baseUrl) { + exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url); + } else { + exchangeTokenUrl = this.providerConfig.url; + } - if (paramName === 'redirect_uri' && !paramValue) { return } + return this.$http.post(exchangeTokenUrl, payload, { + withCredentials: this.options.withCredentials, + }); + } - if (paramName === 'state') { - var stateName = this$1.providerConfig.name + '_state'; - paramValue = encodeURIComponent(this$1.storage.getItem(stateName)); - } - if (paramName === 'scope' && Array.isArray(paramValue)) { - paramValue = paramValue.join(this$1.providerConfig.scopeDelimiter); - if (this$1.providerConfig.scopePrefix) { - paramValue = [this$1.providerConfig.scopePrefix, paramValue].join(this$1.providerConfig.scopeDelimiter); + /** + * Stringify oauth params + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @return {String} + */ + _stringifyRequestParams() { + let keyValuePairs = []; + let paramCategories = [ + 'defaultUrlParams', + 'requiredUrlParams', + 'optionalUrlParams', + ]; + + paramCategories.forEach(categoryName => { + if (!this.providerConfig[categoryName]) return; + if (!Array.isArray(this.providerConfig[categoryName])) return; + + this.providerConfig[categoryName].forEach(paramName => { + let camelCaseParamName = camelCase(paramName); + let paramValue = isFunction(this.providerConfig[paramName]) + ? this.providerConfig[paramName]() + : this.providerConfig[camelCaseParamName]; + + if (paramName === 'redirect_uri' && !paramValue) return; + + if (paramName === 'state') { + let stateName = this.providerConfig.name + '_state'; + paramValue = encodeURIComponent(this.storage.getItem(stateName)); + } + if (paramName === 'scope' && Array.isArray(paramValue)) { + paramValue = paramValue.join(this.providerConfig.scopeDelimiter); + if (this.providerConfig.scopePrefix) { + paramValue = [this.providerConfig.scopePrefix, paramValue].join( + this.providerConfig.scopeDelimiter + ); + } } - } - keyValuePairs.push([paramName, paramValue]); + keyValuePairs.push([paramName, paramValue]); + }); }); - }); - return keyValuePairs.map(function (param) { - return param.join('=') - }).join('&') -}; - -var VueAuthenticate = function VueAuthenticate($http, overrideOptions) { - var options = objectExtend({}, defaultOptions); - options = objectExtend(options, overrideOptions); - var storage = StorageFactory(options); - - Object.defineProperties(this, { - $http: { - get: function get() { - return $http - } - }, + return keyValuePairs + .map(param => { + return param.join('='); + }) + .join('&'); + } +} - options: { - get: function get() { - return options - } - }, +class VueAuthenticate { + constructor($http, overrideOptions) { + let options = objectExtend({}, defaultOptions); + options = objectExtend(options, overrideOptions); + let storage = StorageFactory(options); + + Object.defineProperties(this, { + $http: { + get() { + return $http; + }, + }, + + options: { + get() { + return options; + }, + }, + + storage: { + get() { + return storage; + }, + }, + + tokenName: { + get() { + if (this.options.tokenPrefix) { + return [this.options.tokenPrefix, this.options.tokenName].join('_'); + } else { + return this.options.tokenName; + } + }, + }, + }); - storage: { - get: function get() { - return storage - } - }, + // Setup request interceptors + if ( + this.options.bindRequestInterceptor && + isFunction(this.options.bindRequestInterceptor) + ) { + this.options.bindRequestInterceptor.call(this, this); + } else { + throw new Error('Request interceptor must be functions'); + } + } - tokenName: { - get: function get() { - if (this.options.tokenPrefix) { - return [this.options.tokenPrefix, this.options.tokenName].join('_') - } else { - return this.options.tokenName + /** + * Check if user is authenticated + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * @return {Boolean} + */ + isAuthenticated() { + let token = this.storage.getItem(this.tokenName); + + if (token) { + // Token is present + if (token.split('.').length === 3) { + // Token with a valid JWT format XXX.YYY.ZZZ + try { + // Could be a valid JWT or an access token with the same format + const base64Url = token.split('.')[1]; + const base64 = base64Url.replace('-', '+').replace('_', '/'); + const exp = JSON.parse($window.atob(base64)).exp; + if (typeof exp === 'number') { + // JWT with an optonal expiration claims + return Math.round(new Date().getTime() / 1000) < exp; + } + } catch (e) { + return true; // Pass: Non-JWT token that looks like JWT } } + return true; // Pass: All other tokens } - }); + return false; + } - // Setup request interceptors - if (this.options.bindRequestInterceptor && isFunction(this.options.bindRequestInterceptor)) { - this.options.bindRequestInterceptor.call(this, this); - } else { - throw new Error('Request interceptor must be functions') + /** + * Get token if user is authenticated + * @return {String} Authentication token + */ + getToken() { + return this.storage.getItem(this.tokenName); } -}; -/** - * Check if user is authenticated - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * @return {Boolean} - */ -VueAuthenticate.prototype.isAuthenticated = function isAuthenticated () { - var token = this.storage.getItem(this.tokenName); - - if (token) {// Token is present - if (token.split('.').length === 3) {// Token with a valid JWT format XXX.YYY.ZZZ - try { // Could be a valid JWT or an access token with the same format - var base64Url = token.split('.')[1]; - var base64 = base64Url.replace('-', '+').replace('_', '/'); - var exp = JSON.parse(window.atob(base64)).exp; - if (typeof exp === 'number') {// JWT with an optonal expiration claims - return Math.round(new Date().getTime() / 1000) < exp; - } - } catch (e) { - return true;// Pass: Non-JWT token that looks like JWT - } + /** + * Set new authentication token + * @param {String|Object} token + */ + setToken(response, tokenPath) { + if (response[this.options.responseDataKey]) { + response = response[this.options.responseDataKey]; } - return true;// Pass: All other tokens - } - return false -}; -/** - * Get token if user is authenticated - * @return {String} Authentication token - */ -VueAuthenticate.prototype.getToken = function getToken () { - return this.storage.getItem(this.tokenName) -}; + const responseTokenPath = tokenPath || this.options.tokenPath; + const token = getObjectProperty(response, responseTokenPath); -/** - * Set new authentication token - * @param {String|Object} token - */ -VueAuthenticate.prototype.setToken = function setToken (response) { - if (response[this.options.responseDataKey]) { - response = response[this.options.responseDataKey]; - } - - var token; - if (response.access_token) { - if (isObject(response.access_token) && isObject(response.access_token[this.options.responseDataKey])) { - response = response.access_token; - } else if (isString(response.access_token)) { - token = response.access_token; + if (token) { + this.storage.setItem(this.tokenName, token); } } - if (!token && response) { - token = response[this.options.tokenName]; - } + getPayload() { + const token = this.storage.getItem(this.tokenName); - if (token) { - this.storage.setItem(this.tokenName, token); + if (token && token.split('.').length === 3) { + try { + const base64Url = token.split('.')[1]; + const base64 = base64Url.replace('-', '+').replace('_', '/'); + return JSON.parse(decodeBase64(base64)); + } catch (e) {} + } } -}; -VueAuthenticate.prototype.getPayload = function getPayload () { - var token = this.storage.getItem(this.tokenName); + /** + * Login user using email and password + * @param {Object} user User data + * @param {Object} requestOptions Request options + * @return {Promise} Request promise + */ + login(user, requestOptions) { + requestOptions = requestOptions || {}; + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.loginUrl); + requestOptions[this.options.requestDataKey] = + user || requestOptions[this.options.requestDataKey]; + requestOptions.method = requestOptions.method || 'POST'; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; - if (token && token.split('.').length === 3) { - try { - var base64Url = token.split('.')[1]; - var base64 = base64Url.replace('-', '+').replace('_', '/'); - return JSON.parse(decodeBase64(base64)); - } catch (e) {} + return this.$http(requestOptions).then(response => { + this.setToken(response); + return response; + }); } -}; - -/** - * Login user using email and password - * @param{Object} user User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.login = function login (user, requestOptions) { - var this$1 = this; - - requestOptions = requestOptions || {}; - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.loginUrl); - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey]; - requestOptions.method = requestOptions.method || 'POST'; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.setToken(response); - return response - }) -}; - -/** - * Register new user - * @param{Object} user User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.register = function register (user, requestOptions) { - var this$1 = this; - - requestOptions = requestOptions || {}; - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.registerUrl); - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey]; - requestOptions.method = requestOptions.method || 'POST'; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.setToken(response); - return response - }) -}; -/** - * Logout current user - * @param{Object} requestOptionsLogout request options object - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.logout = function logout (requestOptions) { - var this$1 = this; + /** + * Register new user + * @param {Object} user User data + * @param {Object} requestOptions Request options + * @return {Promise} Request promise + */ + register(user, requestOptions) { + requestOptions = requestOptions || {}; + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.registerUrl); + requestOptions[this.options.requestDataKey] = + user || requestOptions[this.options.requestDataKey]; + requestOptions.method = requestOptions.method || 'POST'; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; - if (!this.isAuthenticated()) { - return Promise$1.reject(new Error('There is no currently authenticated user')) + return this.$http(requestOptions).then(response => { + this.setToken(response); + return response; + }); } - requestOptions = requestOptions || {}; + /** + * Logout current user + * @param {Object} requestOptions Logout request options object + * @return {Promise} Request promise + */ + logout(requestOptions) { + if (!this.isAuthenticated()) { + return Promise$1.reject( + new Error('There is no currently authenticated user') + ); + } - if (requestOptions.url) { - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.logoutUrl); - requestOptions.method = requestOptions.method || 'POST'; - requestOptions[this.options.requestDataKey] = requestOptions[this.options.requestDataKey] || undefined; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.storage.removeItem(this$1.tokenName); - }) - } else { - this.storage.removeItem(this.tokenName); - return Promise$1.resolve(); + requestOptions = requestOptions || {}; + + if (requestOptions.url || this.options.logoutUrl) { + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.logoutUrl); + requestOptions.method = requestOptions.method || 'POST'; + requestOptions[this.options.requestDataKey] = + requestOptions[this.options.requestDataKey] || undefined; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; + + return this.$http(requestOptions).then(response => { + this.storage.removeItem(this.tokenName); + return response; + }); + } else { + this.storage.removeItem(this.tokenName); + return Promise$1.resolve(); + } } -}; -/** - * Authenticate user using authentication provider - * - * @param{String} provider Provider name - * @param{Object} userData User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.authenticate = function authenticate (provider, userData, requestOptions) { - var this$1 = this; + /** + * Authenticate user using authentication provider + * + * @param {String} provider Provider name + * @param {Object} userData User data + * @return {Promise} Request promise + */ + authenticate(provider, userData) { + return new Promise$1((resolve, reject) => { + var providerConfig = this.options.providers[provider]; + if (!providerConfig) { + return reject(new Error('Unknown provider')); + } - return new Promise$1(function (resolve, reject) { - var providerConfig = this$1.options.providers[provider]; - if (!providerConfig) { - return reject(new Error('Unknown provider')) - } + let providerInstance; + switch (providerConfig.oauthType) { + case '1.0': + providerInstance = new OAuth( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + case '2.0': + providerInstance = new OAuth2( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + default: + return reject(new Error('Invalid OAuth type')); + } - var providerInstance; - switch (providerConfig.oauthType) { - case '1.0': - providerInstance = new OAuth(this$1.$http, this$1.storage, providerConfig, this$1.options); - break - case '2.0': - providerInstance = new OAuth2(this$1.$http, this$1.storage, providerConfig, this$1.options); - break - default: - return reject(new Error('Invalid OAuth type')) - break - } + return providerInstance + .init(userData) + .then(response => { + this.setToken(response, providerConfig.tokenPath); - return providerInstance.init(userData).then(function (response) { - this$1.setToken(response); + if (this.isAuthenticated()) { + return resolve(response); + } else { + return reject(new Error('Authentication failed')); + } + }) + .catch(err => reject(err)); + }); + } - if (this$1.isAuthenticated()) { - return resolve(response) - } else { - return reject(new Error('Authentication failed')) + /** + * Link user using authentication provider without login + * + * @param {String} provider Provider name + * @param {Object} userData User data + * @return {Promise} Request promise + */ + link(provider, userData) { + return new Promise$1((resolve, reject) => { + var providerConfig = this.options.providers[provider]; + if (!providerConfig) { + return reject(new Error('Unknown provider')); } - }).catch(function (err) { return reject(err); }) - }) -}; + + let providerInstance; + switch (providerConfig.oauthType) { + case '1.0': + providerInstance = new OAuth( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + case '2.0': + providerInstance = new OAuth2( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + default: + return reject(new Error('Invalid OAuth type')); + } + + return providerInstance + .init(userData) + .then(response => { + if (response[this.options.responseDataKey]) { + response = response[this.options.responseDataKey]; + } + + resolve(response); + }) + .catch(reject); + }); + } +} /** * VueAuthenticate plugin @@ -1403,25 +1606,26 @@ VueAuthenticate.prototype.authenticate = function authenticate (provider, userDa */ function plugin(Vue, options) { if (plugin.installed) { - return + return; } + plugin.installed = true; - var vueAuthInstance = null; + let vueAuthInstance = null; Object.defineProperties(Vue.prototype, { $auth: { - get: function get() { + get() { if (!vueAuthInstance) { // Request handler library not found, throw error if (!this.$http) { - throw new Error('Request handler instance not found') + throw new Error('Request handler instance not found'); } vueAuthInstance = new VueAuthenticate(this.$http, options); } - return vueAuthInstance - } - } + return vueAuthInstance; + }, + }, }); } @@ -1432,7 +1636,7 @@ function plugin(Vue, options) { * @return {VueAuthenticate} VueAuthenticate instance */ plugin.factory = function ($http, options) { - return new VueAuthenticate($http, options) + return new VueAuthenticate($http, options); }; module.exports = plugin; diff --git a/dist/vue-authenticate.es2015.js b/dist/vue-authenticate.es2015.js deleted file mode 100644 index a0ca007..0000000 --- a/dist/vue-authenticate.es2015.js +++ /dev/null @@ -1,1437 +0,0 @@ -/*! - * vue-authenticate v1.3.5-beta.1 - * https://github.com/dgrubelic/vue-authenticate - * Released under the MIT License. - */ - -if (typeof Object.assign != 'function') { - Object.assign = function(target, varArgs) { - 'use strict'; - var arguments$1 = arguments; - - if (target == null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var to = Object(target); - - for (var index = 1; index < arguments.length; index++) { - var nextSource = arguments$1[index]; - - if (nextSource != null) { // Skip over if undefined or null - for (var nextKey in nextSource) { - // Avoid bugs when hasOwnProperty is shadowed - if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { - to[nextKey] = nextSource[nextKey]; - } - } - } - } - return to; - }; -} - -function camelCase(name) { - return name.replace(/([\:\-\_]+(.))/g, function (_, separator, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }); -} - -function isUndefined(value) { - return typeof value === 'undefined' -} - - - -function isObject(value) { - return value !== null && typeof value === 'object' -} - -function isString(value) { - return typeof value === 'string' -} - - - -function isFunction(value) { - return typeof value === 'function' -} - -function objectExtend(a, b) { - - // Don't touch 'null' or 'undefined' objects. - if (a == null || b == null) { - return a; - } - - Object.keys(b).forEach(function (key) { - if (Object.prototype.toString.call(b[key]) == '[object Object]') { - if (Object.prototype.toString.call(a[key]) != '[object Object]') { - a[key] = b[key]; - } else { - a[key] = objectExtend(a[key], b[key]); - } - } else { - a[key] = b[key]; - } - }); - - return a; -} - -/** - * Assemble url from two segments - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} baseUrl Base url - * @param {String} url URI - * @return {String} - */ -function joinUrl(baseUrl, url) { - if (/^(?:[a-z]+:)?\/\//i.test(url)) { - return url; - } - var joined = [baseUrl, url].join('/'); - var normalize = function (str) { - return str - .replace(/[\/]+/g, '/') - .replace(/\/\?/g, '?') - .replace(/\/\#/g, '#') - .replace(/\:\//g, '://'); - }; - return normalize(joined); -} - -/** - * Get full path based on current location - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {Location} location - * @return {String} - */ -function getFullUrlPath(location) { - var isHttps = location.protocol === 'https:'; - return location.protocol + '//' + location.hostname + - ':' + (location.port || (isHttps ? '443' : '80')) + - (/^\//.test(location.pathname) ? location.pathname : '/' + location.pathname); -} - -/** - * Parse query string variables - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} Query string - * @return {String} - */ -function parseQueryString(str) { - var obj = {}; - var key; - var value; - (str || '').split('&').forEach(function (keyValue) { - if (keyValue) { - value = keyValue.split('='); - key = decodeURIComponent(value[0]); - obj[key] = (!!value[1]) ? decodeURIComponent(value[1]) : true; - } - }); - return obj; -} - -/** - * Decode base64 string - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} str base64 encoded string - * @return {Object} - */ -function decodeBase64(str) { - var buffer; - if (typeof module !== 'undefined' && module.exports) { - try { - buffer = require('buffer').Buffer; - } catch (err) { - // noop - } - } - - var fromCharCode = String.fromCharCode; - - var re_btou = new RegExp([ - '[\xC0-\xDF][\x80-\xBF]', - '[\xE0-\xEF][\x80-\xBF]{2}', - '[\xF0-\xF7][\x80-\xBF]{3}' - ].join('|'), 'g'); - - var cb_btou = function (cccc) { - switch (cccc.length) { - case 4: - var cp = ((0x07 & cccc.charCodeAt(0)) << 18) - | ((0x3f & cccc.charCodeAt(1)) << 12) - | ((0x3f & cccc.charCodeAt(2)) << 6) - | (0x3f & cccc.charCodeAt(3)); - var offset = cp - 0x10000; - return (fromCharCode((offset >>> 10) + 0xD800) - + fromCharCode((offset & 0x3FF) + 0xDC00)); - case 3: - return fromCharCode( - ((0x0f & cccc.charCodeAt(0)) << 12) - | ((0x3f & cccc.charCodeAt(1)) << 6) - | (0x3f & cccc.charCodeAt(2)) - ); - default: - return fromCharCode( - ((0x1f & cccc.charCodeAt(0)) << 6) - | (0x3f & cccc.charCodeAt(1)) - ); - } - }; - - var btou = function (b) { - return b.replace(re_btou, cb_btou); - }; - - var _decode = buffer ? function (a) { - return (a.constructor === buffer.constructor - ? a : new buffer(a, 'base64')).toString(); - } - : function (a) { - return btou(atob(a)); - }; - - return _decode( - String(str).replace(/[-_]/g, function (m0) { - return m0 === '-' ? '+' : '/'; - }) - .replace(/[^A-Za-z0-9\+\/]/g, '') - ); -} - -function parseCookies(str) { - if (str.length === 0) { return {}; } - var parsed = {}; - var pattern = new RegExp('\\s*;\\s*'); - str.split(pattern).forEach(function (i) { - var ref = i.split('='); - var encodedKey = ref[0]; - var encodedValue = ref[1]; - var key = decodeURIComponent(encodedKey); - var value = decodeURIComponent(encodedValue); - parsed[key] = value; - }); - return parsed; -} - -function formatOptions(options) { - var path = options.path; - var domain = options.domain; - var expires = options.expires; - var secure = options.secure; - return [ - typeof path === 'undefined' || path === null - ? '' : ';path=' + path, - typeof domain === 'undefined' || domain === null - ? '' : ';domain=' + domain, - typeof expires === 'undefined' || expires === null - ? '' : ';expires=' + expires.toUTCString(), - typeof secure === 'undefined' || secure === null || secure === false - ? '' : ';secure' - ].join(''); -} - -function formatCookie(key, value, options) { - return [ - encodeURIComponent(key), - '=', - encodeURIComponent(value), - formatOptions(options) - ].join(''); -} - -// Store setTimeout reference so promise-polyfill will be unaffected by -// other code modifying setTimeout (like sinon.useFakeTimers()) -var setTimeoutFunc = setTimeout; - -function noop() {} - -// Polyfill for Function.prototype.bind -function bind(fn, thisArg) { - return function () { - fn.apply(thisArg, arguments); - }; -} - -function Promise$1(fn) { - if (typeof this !== 'object') { throw new TypeError('Promises must be constructed via new'); } - if (typeof fn !== 'function') { throw new TypeError('not a function'); } - this._state = 0; - this._handled = false; - this._value = undefined; - this._deferreds = []; - - doResolve(fn, this); -} - -function handle(self, deferred) { - while (self._state === 3) { - self = self._value; - } - if (self._state === 0) { - self._deferreds.push(deferred); - return; - } - self._handled = true; - Promise$1._immediateFn(function () { - var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; - if (cb === null) { - (self._state === 1 ? resolve : reject)(deferred.promise, self._value); - return; - } - var ret; - try { - ret = cb(self._value); - } catch (e) { - reject(deferred.promise, e); - return; - } - resolve(deferred.promise, ret); - }); -} - -function resolve(self, newValue) { - try { - // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure - if (newValue === self) { throw new TypeError('A promise cannot be resolved with itself.'); } - if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { - var then = newValue.then; - if (newValue instanceof Promise$1) { - self._state = 3; - self._value = newValue; - finale(self); - return; - } else if (typeof then === 'function') { - doResolve(bind(then, newValue), self); - return; - } - } - self._state = 1; - self._value = newValue; - finale(self); - } catch (e) { - reject(self, e); - } -} - -function reject(self, newValue) { - self._state = 2; - self._value = newValue; - finale(self); -} - -function finale(self) { - if (self._state === 2 && self._deferreds.length === 0) { - Promise$1._immediateFn(function() { - if (!self._handled) { - Promise$1._unhandledRejectionFn(self._value); - } - }); - } - - for (var i = 0, len = self._deferreds.length; i < len; i++) { - handle(self, self._deferreds[i]); - } - self._deferreds = null; -} - -function Handler(onFulfilled, onRejected, promise) { - this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; - this.onRejected = typeof onRejected === 'function' ? onRejected : null; - this.promise = promise; -} - -/** - * Take a potentially misbehaving resolver function and make sure - * onFulfilled and onRejected are only called once. - * - * Makes no guarantees about asynchrony. - */ -function doResolve(fn, self) { - var done = false; - try { - fn(function (value) { - if (done) { return; } - done = true; - resolve(self, value); - }, function (reason) { - if (done) { return; } - done = true; - reject(self, reason); - }); - } catch (ex) { - if (done) { return; } - done = true; - reject(self, ex); - } -} - -Promise$1.prototype['catch'] = function (onRejected) { - return this.then(null, onRejected); -}; - -Promise$1.prototype.then = function (onFulfilled, onRejected) { - var prom = new (this.constructor)(noop); - - handle(this, new Handler(onFulfilled, onRejected, prom)); - return prom; -}; - -Promise$1.all = function (arr) { - var args = Array.prototype.slice.call(arr); - - return new Promise$1(function (resolve, reject) { - if (args.length === 0) { return resolve([]); } - var remaining = args.length; - - function res(i, val) { - try { - if (val && (typeof val === 'object' || typeof val === 'function')) { - var then = val.then; - if (typeof then === 'function') { - then.call(val, function (val) { - res(i, val); - }, reject); - return; - } - } - args[i] = val; - if (--remaining === 0) { - resolve(args); - } - } catch (ex) { - reject(ex); - } - } - - for (var i = 0; i < args.length; i++) { - res(i, args[i]); - } - }); -}; - -Promise$1.resolve = function (value) { - if (value && typeof value === 'object' && value.constructor === Promise$1) { - return value; - } - - return new Promise$1(function (resolve) { - resolve(value); - }); -}; - -Promise$1.reject = function (value) { - return new Promise$1(function (resolve, reject) { - reject(value); - }); -}; - -Promise$1.race = function (values) { - return new Promise$1(function (resolve, reject) { - for (var i = 0, len = values.length; i < len; i++) { - values[i].then(resolve, reject); - } - }); -}; - -// Use polyfill for setImmediate for performance gains -Promise$1._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) || - function (fn) { - setTimeoutFunc(fn, 0); - }; - -Promise$1._unhandledRejectionFn = function _unhandledRejectionFn(err) { - if (typeof console !== 'undefined' && console) { - console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console - } -}; - -/** - * Set the immediate function to execute callbacks - * @param fn {function} Function to execute - * @deprecated - */ -Promise$1._setImmediateFn = function _setImmediateFn(fn) { - Promise$1._immediateFn = fn; -}; - -/** - * Change the function to execute on unhandled rejection - * @param {function} fn Function to execute on unhandled rejection - * @deprecated - */ -Promise$1._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { - Promise$1._unhandledRejectionFn = fn; -}; - -function getCookieDomainUrl() { - try { - return window.location.hostname - } catch (e) {} - - return ''; -} - -function getRedirectUri(uri) { - try { - return (!isUndefined(uri)) - ? ("" + (window.location.origin) + uri) - : window.location.origin - } catch (e) {} - - return uri || null; -} - -/** - * Default configuration - */ -var defaultOptions = { - baseUrl: null, - tokenName: 'token', - tokenPrefix: 'vueauth', - tokenHeader: 'Authorization', - tokenType: 'Bearer', - loginUrl: '/auth/login', - registerUrl: '/auth/register', - logoutUrl: null, - storageType: 'localStorage', - storageNamespace: 'vue-authenticate', - cookieStorage: { - domain: getCookieDomainUrl(), - path: '/', - secure: false - }, - requestDataKey: 'data', - responseDataKey: 'data', - - /** - * Default request interceptor for Axios library - * @context {VueAuthenticate} - */ - bindRequestInterceptor: function ($auth) { - var tokenHeader = $auth.options.tokenHeader; - - $auth.$http.interceptors.request.use(function (config) { - if ($auth.isAuthenticated()) { - config.headers[tokenHeader] = [ - $auth.options.tokenType, $auth.getToken() - ].join(' '); - } else { - delete config.headers[tokenHeader]; - } - return config - }); - }, - - providers: { - facebook: { - name: 'facebook', - url: '/auth/facebook', - authorizationEndpoint: 'https://www.facebook.com/v2.5/dialog/oauth', - redirectUri: getRedirectUri('/'), - requiredUrlParams: ['display', 'scope'], - scope: ['email'], - scopeDelimiter: ',', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 580, height: 400 } - }, - - google: { - name: 'google', - url: '/auth/google', - authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth', - redirectUri: getRedirectUri(), - requiredUrlParams: ['scope'], - optionalUrlParams: ['display'], - scope: ['profile', 'email'], - scopePrefix: 'openid', - scopeDelimiter: ' ', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 452, height: 633 } - }, - - github: { - name: 'github', - url: '/auth/github', - authorizationEndpoint: 'https://github.com/login/oauth/authorize', - redirectUri: getRedirectUri(), - optionalUrlParams: ['scope'], - scope: ['user:email'], - scopeDelimiter: ' ', - oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } - }, - - instagram: { - name: 'instagram', - url: '/auth/instagram', - authorizationEndpoint: 'https://api.instagram.com/oauth/authorize', - redirectUri: getRedirectUri(), - requiredUrlParams: ['scope'], - scope: ['basic'], - scopeDelimiter: '+', - oauthType: '2.0', - popupOptions: { width: null, height: null } - }, - - twitter: { - name: 'twitter', - url: '/auth/twitter', - authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate', - redirectUri: getRedirectUri(), - oauthType: '1.0', - popupOptions: { width: 495, height: 645 } - }, - - bitbucket: { - name: 'bitbucket', - url: '/auth/bitbucket', - authorizationEndpoint: 'https://bitbucket.org/site/oauth2/authorize', - redirectUri: getRedirectUri('/'), - optionalUrlParams: ['scope'], - scope: ['email'], - scopeDelimiter: ' ', - oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } - }, - - linkedin: { - name: 'linkedin', - url: '/auth/linkedin', - authorizationEndpoint: 'https://www.linkedin.com/oauth/v2/authorization', - redirectUri: getRedirectUri(), - requiredUrlParams: ['state'], - scope: ['r_emailaddress'], - scopeDelimiter: ' ', - state: 'STATE', - oauthType: '2.0', - popupOptions: { width: 527, height: 582 } - }, - - live: { - name: 'live', - url: '/auth/live', - authorizationEndpoint: 'https://login.live.com/oauth20_authorize.srf', - redirectUri: getRedirectUri(), - requiredUrlParams: ['display', 'scope'], - scope: ['wl.emails'], - scopeDelimiter: ' ', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 500, height: 560 } - }, - - oauth1: { - name: null, - url: '/auth/oauth1', - authorizationEndpoint: null, - redirectUri: getRedirectUri(), - oauthType: '1.0', - popupOptions: null - }, - - oauth2: { - name: null, - url: '/auth/oauth2', - clientId: null, - redirectUri: getRedirectUri(), - authorizationEndpoint: null, - defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], - requiredUrlParams: null, - optionalUrlParams: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - state: null, - oauthType: '2.0', - popupOptions: null, - responseType: 'code', - responseParams: { - code: 'code', - clientId: 'clientId', - redirectUri: 'redirectUri' - } - } - } -}; - -var CookieStorage = function CookieStorage(defaultOptions) { - this._defaultOptions = objectExtend({ - domain: getCookieDomainUrl(), - expires: null, - path: '/', - secure: false - }, defaultOptions); -}; - -CookieStorage.prototype.setItem = function setItem (key, value) { - var options = objectExtend({}, this._defaultOptions); - var cookie = formatCookie(key, value, options); - this._setCookie(cookie); -}; - -CookieStorage.prototype.getItem = function getItem (key) { - var cookies = parseCookies(this._getCookie()); - return cookies.hasOwnProperty(key) ? cookies[key] : null; -}; - -CookieStorage.prototype.removeItem = function removeItem (key) { - var value = ''; - var defaultOptions = objectExtend({}, this._defaultOptions); - var options = objectExtend(defaultOptions, { - expires: new Date(0) - }); - var cookie = formatCookie(key, value, options); - this._setCookie(cookie); -}; - -CookieStorage.prototype._getCookie = function _getCookie () { - try { - return typeof document === 'undefined' - ? '' : typeof document.cookie === 'undefined' - ? '' : document.cookie; - } catch (e) {} - - return ''; -}; - -CookieStorage.prototype._setCookie = function _setCookie (cookie) { - try { - document.cookie = cookie; - } catch (e) {} -}; - -var LocalStorage = function LocalStorage(namespace) { - this.namespace = namespace || null; -}; - -LocalStorage.prototype.setItem = function setItem (key, value) { - window.localStorage.setItem(this._getStorageKey(key), value); -}; - -LocalStorage.prototype.getItem = function getItem (key) { - return window.localStorage.getItem(this._getStorageKey(key)) -}; - -LocalStorage.prototype.removeItem = function removeItem (key) { - window.localStorage.removeItem(this._getStorageKey(key)); -}; - -LocalStorage.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; - -var MemoryStorage = function MemoryStorage(namespace) { - this.namespace = namespace || null; - this._storage = {}; -}; - -MemoryStorage.prototype.setItem = function setItem (key, value) { - this._storage[this._getStorageKey(key)] = value; -}; - -MemoryStorage.prototype.getItem = function getItem (key) { - return this._storage[this._getStorageKey(key)] -}; - -MemoryStorage.prototype.removeItem = function removeItem (key) { - delete this._storage[this._getStorageKey(key)]; -}; - -MemoryStorage.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; - -var LocalStorage$2 = function LocalStorage(namespace) { - this.namespace = namespace || null; -}; - -LocalStorage$2.prototype.setItem = function setItem (key, value) { - window.sessionStorage.setItem(this._getStorageKey(key), value); -}; - -LocalStorage$2.prototype.getItem = function getItem (key) { - return window.sessionStorage.getItem(this._getStorageKey(key)) -}; - -LocalStorage$2.prototype.removeItem = function removeItem (key) { - window.sessionStorage.removeItem(this._getStorageKey(key)); -}; - -LocalStorage$2.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; - -function StorageFactory(options) { - switch (options.storageType) { - case 'localStorage': - try { - window.localStorage.setItem('testKey', 'test'); - window.localStorage.removeItem('testKey'); - return new LocalStorage(options.storageNamespace) - } catch(e) {} - - case 'sessionStorage': - try { - window.sessionStorage.setItem('testKey', 'test'); - window.sessionStorage.removeItem('testKey'); - return new LocalStorage$2(options.storageNamespace) - } catch (e) {} - - case 'cookieStorage': - return new CookieStorage(options.cookieStorage); - - case 'memoryStorage': - default: - return new MemoryStorage(options.storageNamespace) - break; - } -} - -/** - * OAuth2 popup management class - * - * @author Sahat Yalkabov - * @copyright Class mostly taken from https://github.com/sahat/satellizer - * and adjusted to fit vue-authenticate library - */ -var OAuthPopup = function OAuthPopup(url, name, popupOptions) { - this.popup = null; - this.url = url; - this.name = name; - this.popupOptions = popupOptions; -}; - -OAuthPopup.prototype.open = function open (redirectUri, skipPooling) { - try { - this.popup = window.open(this.url, this.name, this._stringifyOptions()); - if (this.popup && this.popup.focus) { - this.popup.focus(); - } - - if (skipPooling) { - return Promise$1.resolve() - } else { - return this.pooling(redirectUri) - } - } catch(e) { - return Promise$1.reject(new Error('OAuth popup error occurred')) - } -}; - -OAuthPopup.prototype.pooling = function pooling (redirectUri) { - var this$1 = this; - - return new Promise$1(function (resolve, reject) { - var redirectUriParser = document.createElement('a'); - redirectUriParser.href = redirectUri; - var redirectUriPath = getFullUrlPath(redirectUriParser); - - var poolingInterval = setInterval(function () { - if (!this$1.popup || this$1.popup.closed || this$1.popup.closed === undefined) { - clearInterval(poolingInterval); - poolingInterval = null; - reject(new Error('Auth popup window closed')); - } - - try { - var popupWindowPath = getFullUrlPath(this$1.popup.location); - - if (popupWindowPath === redirectUriPath) { - if (this$1.popup.location.search || this$1.popup.location.hash) { - var query = parseQueryString(this$1.popup.location.search.substring(1).replace(/\/$/, '')); - var hash = parseQueryString(this$1.popup.location.hash.substring(1).replace(/[\/$]/, '')); - var params = objectExtend({}, query); - params = objectExtend(params, hash); - - if (params.error) { - reject(new Error(params.error)); - } else { - resolve(params); - } - } else { - reject(new Error('OAuth redirect has occurred but no query or hash parameters were found.')); - } - - clearInterval(poolingInterval); - poolingInterval = null; - this$1.popup.close(); - } - } catch(e) { - // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame. - } - }, 250); - }) -}; - -OAuthPopup.prototype._stringifyOptions = function _stringifyOptions () { - var this$1 = this; - - var options = []; - for (var optionKey in this$1.popupOptions) { - if (!isUndefined(this$1.popupOptions[optionKey])) { - options.push((optionKey + "=" + (this$1.popupOptions[optionKey]))); - } - } - return options.join(',') -}; - -var defaultProviderConfig = { - name: null, - url: null, - authorizationEndpoint: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - redirectUri: null, - requiredUrlParams: null, - defaultUrlParams: null, - oauthType: '1.0', - popupOptions: {} -}; - -var OAuth = function OAuth($http, storage, providerConfig, options) { - this.$http = $http; - this.storage = storage; - this.providerConfig = objectExtend({}, defaultProviderConfig); - this.providerConfig = objectExtend(this.providerConfig, providerConfig); - this.options = options; -}; - -/** - * Initialize OAuth1 process - * @param{Object} userData User data - * @return {Promise} - */ -OAuth.prototype.init = function init (userData) { - var this$1 = this; - - this.oauthPopup = new OAuthPopup('about:blank', this.providerConfig.name, this.providerConfig.popupOptions); - - if (window && !window['cordova']) { - this.oauthPopup.open(this.providerConfig.redirectUri, true); - } - - return this.getRequestToken().then(function (response) { - return this$1.openPopup(response).then(function (popupResponse) { - return this$1.exchangeForToken(popupResponse, userData) - }) - }) -}; - -/** - * Get OAuth1 request token - * @return {Promise} - */ -OAuth.prototype.getRequestToken = function getRequestToken () { - var requestOptions = {}; - requestOptions.method = 'POST'; - requestOptions[this.options.requestDataKey] = objectExtend({}, this.providerConfig); - requestOptions.withCredentials = this.options.withCredentials; - if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - requestOptions.url = this.providerConfig.url; - } - - return this.$http(requestOptions) -}; - -/** - * Open OAuth1 popup - * @param{Object} response Response object containing request token - * @return {Promise} - */ -OAuth.prototype.openPopup = function openPopup (response) { - var url = [this.providerConfig.authorizationEndpoint, this.buildQueryString(response[this.options.responseDataKey])].join('?'); - - this.oauthPopup.popup.location = url; - if (window && window['cordova']) { - return this.oauthPopup.open(this.providerConfig.redirectUri) - } else { - return this.oauthPopup.pooling(this.providerConfig.redirectUri) - } -}; - -/** - * Exchange token and token verifier for access token - * @param{Object} oauth OAuth data containing token and token verifier - * @param{Object} userData User data - * @return {Promise} - */ -OAuth.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { - var payload = objectExtend({}, userData); - payload = objectExtend(payload, oauth); - var requestOptions = {}; - requestOptions.method = 'POST'; - requestOptions[this.options.requestDataKey] = payload; - requestOptions.withCredentials = this.options.withCredentials; - if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - requestOptions.url = this.providerConfig.url; - } - return this.$http(requestOptions) -}; - -OAuth.prototype.buildQueryString = function buildQueryString (params) { - var parsedParams = []; - for (var key in params) { - var value = params[key]; - parsedParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); - } - return parsedParams.join('&'); -}; - -/** - * Default provider configuration - * @type {Object} - */ -var defaultProviderConfig$1 = { - name: null, - url: null, - clientId: null, - authorizationEndpoint: null, - redirectUri: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - state: null, - requiredUrlParams: null, - defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], - responseType: 'code', - responseParams: { - code: 'code', - clientId: 'clientId', - redirectUri: 'redirectUri' - }, - oauthType: '2.0', - popupOptions: {} -}; - -var OAuth2 = function OAuth2($http, storage, providerConfig, options) { - this.$http = $http; - this.storage = storage; - this.providerConfig = objectExtend({}, defaultProviderConfig$1); - this.providerConfig = objectExtend(this.providerConfig, providerConfig); - this.options = options; -}; - -OAuth2.prototype.init = function init (userData) { - var this$1 = this; - - var stateName = this.providerConfig.name + '_state'; - if (isFunction(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state()); - } else if (isString(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state); - } - - var url = [this.providerConfig.authorizationEndpoint, this._stringifyRequestParams()].join('?'); - - this.oauthPopup = new OAuthPopup(url, this.providerConfig.name, this.providerConfig.popupOptions); - - return new Promise(function (resolve, reject) { - this$1.oauthPopup.open(this$1.providerConfig.redirectUri).then(function (response) { - if (this$1.providerConfig.responseType === 'token' || !this$1.providerConfig.url) { - return resolve(response) - } - - if (response.state && response.state !== this$1.storage.getItem(stateName)) { - return reject(new Error('State parameter value does not match original OAuth request state value')) - } - - resolve(this$1.exchangeForToken(response, userData)); - }).catch(function (err) { - reject(err); - }); - }) -}; - -/** - * Exchange temporary oauth data for access token - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param{[type]} oauth [description] - * @param{[type]} userData [description] - * @return {[type]} [description] - */ -OAuth2.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { - var this$1 = this; - - var payload = objectExtend({}, userData); - - for (var key in defaultProviderConfig$1.responseParams) { - var value = defaultProviderConfig$1[key]; - - switch(key) { - case 'code': - payload[key] = oauth.code; - break - case 'clientId': - payload[key] = this$1.providerConfig.clientId; - break - case 'redirectUri': - payload[key] = this$1.providerConfig.redirectUri; - break - default: - payload[key] = oauth[key]; - } - } - - if (oauth.state) { - payload.state = oauth.state; - } - - var exchangeTokenUrl; - if (this.options.baseUrl) { - exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - exchangeTokenUrl = this.providerConfig.url; - } - - return this.$http.post(exchangeTokenUrl, payload, { - withCredentials: this.options.withCredentials - }) -}; - -/** - * Stringify oauth params - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @return {String} - */ -OAuth2.prototype._stringifyRequestParams = function _stringifyRequestParams () { - var this$1 = this; - - var keyValuePairs = []; - var paramCategories = ['defaultUrlParams', 'requiredUrlParams', 'optionalUrlParams']; - - paramCategories.forEach(function (categoryName) { - if (!this$1.providerConfig[categoryName]) { return } - if (!Array.isArray(this$1.providerConfig[categoryName])) { return } - - this$1.providerConfig[categoryName].forEach(function (paramName) { - var camelCaseParamName = camelCase(paramName); - var paramValue = isFunction(this$1.providerConfig[paramName]) ? this$1.providerConfig[paramName]() : this$1.providerConfig[camelCaseParamName]; - - if (paramName === 'redirect_uri' && !paramValue) { return } - - if (paramName === 'state') { - var stateName = this$1.providerConfig.name + '_state'; - paramValue = encodeURIComponent(this$1.storage.getItem(stateName)); - } - if (paramName === 'scope' && Array.isArray(paramValue)) { - paramValue = paramValue.join(this$1.providerConfig.scopeDelimiter); - if (this$1.providerConfig.scopePrefix) { - paramValue = [this$1.providerConfig.scopePrefix, paramValue].join(this$1.providerConfig.scopeDelimiter); - } - } - - keyValuePairs.push([paramName, paramValue]); - }); - }); - - return keyValuePairs.map(function (param) { - return param.join('=') - }).join('&') -}; - -var VueAuthenticate = function VueAuthenticate($http, overrideOptions) { - var options = objectExtend({}, defaultOptions); - options = objectExtend(options, overrideOptions); - var storage = StorageFactory(options); - - Object.defineProperties(this, { - $http: { - get: function get() { - return $http - } - }, - - options: { - get: function get() { - return options - } - }, - - storage: { - get: function get() { - return storage - } - }, - - tokenName: { - get: function get() { - if (this.options.tokenPrefix) { - return [this.options.tokenPrefix, this.options.tokenName].join('_') - } else { - return this.options.tokenName - } - } - } - }); - - // Setup request interceptors - if (this.options.bindRequestInterceptor && isFunction(this.options.bindRequestInterceptor)) { - this.options.bindRequestInterceptor.call(this, this); - } else { - throw new Error('Request interceptor must be functions') - } -}; - -/** - * Check if user is authenticated - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * @return {Boolean} - */ -VueAuthenticate.prototype.isAuthenticated = function isAuthenticated () { - var token = this.storage.getItem(this.tokenName); - - if (token) {// Token is present - if (token.split('.').length === 3) {// Token with a valid JWT format XXX.YYY.ZZZ - try { // Could be a valid JWT or an access token with the same format - var base64Url = token.split('.')[1]; - var base64 = base64Url.replace('-', '+').replace('_', '/'); - var exp = JSON.parse(window.atob(base64)).exp; - if (typeof exp === 'number') {// JWT with an optonal expiration claims - return Math.round(new Date().getTime() / 1000) < exp; - } - } catch (e) { - return true;// Pass: Non-JWT token that looks like JWT - } - } - return true;// Pass: All other tokens - } - return false -}; - -/** - * Get token if user is authenticated - * @return {String} Authentication token - */ -VueAuthenticate.prototype.getToken = function getToken () { - return this.storage.getItem(this.tokenName) -}; - -/** - * Set new authentication token - * @param {String|Object} token - */ -VueAuthenticate.prototype.setToken = function setToken (response) { - if (response[this.options.responseDataKey]) { - response = response[this.options.responseDataKey]; - } - - var token; - if (response.access_token) { - if (isObject(response.access_token) && isObject(response.access_token[this.options.responseDataKey])) { - response = response.access_token; - } else if (isString(response.access_token)) { - token = response.access_token; - } - } - - if (!token && response) { - token = response[this.options.tokenName]; - } - - if (token) { - this.storage.setItem(this.tokenName, token); - } -}; - -VueAuthenticate.prototype.getPayload = function getPayload () { - var token = this.storage.getItem(this.tokenName); - - if (token && token.split('.').length === 3) { - try { - var base64Url = token.split('.')[1]; - var base64 = base64Url.replace('-', '+').replace('_', '/'); - return JSON.parse(decodeBase64(base64)); - } catch (e) {} - } -}; - -/** - * Login user using email and password - * @param{Object} user User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.login = function login (user, requestOptions) { - var this$1 = this; - - requestOptions = requestOptions || {}; - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.loginUrl); - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey]; - requestOptions.method = requestOptions.method || 'POST'; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.setToken(response); - return response - }) -}; - -/** - * Register new user - * @param{Object} user User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.register = function register (user, requestOptions) { - var this$1 = this; - - requestOptions = requestOptions || {}; - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.registerUrl); - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey]; - requestOptions.method = requestOptions.method || 'POST'; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.setToken(response); - return response - }) -}; - -/** - * Logout current user - * @param{Object} requestOptionsLogout request options object - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.logout = function logout (requestOptions) { - var this$1 = this; - - if (!this.isAuthenticated()) { - return Promise$1.reject(new Error('There is no currently authenticated user')) - } - - requestOptions = requestOptions || {}; - - if (requestOptions.url) { - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.logoutUrl); - requestOptions.method = requestOptions.method || 'POST'; - requestOptions[this.options.requestDataKey] = requestOptions[this.options.requestDataKey] || undefined; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.storage.removeItem(this$1.tokenName); - }) - } else { - this.storage.removeItem(this.tokenName); - return Promise$1.resolve(); - } -}; - -/** - * Authenticate user using authentication provider - * - * @param{String} provider Provider name - * @param{Object} userData User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.authenticate = function authenticate (provider, userData, requestOptions) { - var this$1 = this; - - return new Promise$1(function (resolve, reject) { - var providerConfig = this$1.options.providers[provider]; - if (!providerConfig) { - return reject(new Error('Unknown provider')) - } - - var providerInstance; - switch (providerConfig.oauthType) { - case '1.0': - providerInstance = new OAuth(this$1.$http, this$1.storage, providerConfig, this$1.options); - break - case '2.0': - providerInstance = new OAuth2(this$1.$http, this$1.storage, providerConfig, this$1.options); - break - default: - return reject(new Error('Invalid OAuth type')) - break - } - - return providerInstance.init(userData).then(function (response) { - this$1.setToken(response); - - if (this$1.isAuthenticated()) { - return resolve(response) - } else { - return reject(new Error('Authentication failed')) - } - }).catch(function (err) { return reject(err); }) - }) -}; - -/** - * VueAuthenticate plugin - * @param {Object} Vue - * @param {Object} options - */ -function plugin(Vue, options) { - if (plugin.installed) { - return - } - plugin.installed = true; - - var vueAuthInstance = null; - Object.defineProperties(Vue.prototype, { - $auth: { - get: function get() { - if (!vueAuthInstance) { - // Request handler library not found, throw error - if (!this.$http) { - throw new Error('Request handler instance not found') - } - - vueAuthInstance = new VueAuthenticate(this.$http, options); - } - return vueAuthInstance - } - } - }); -} - -/** - * External factory helper for ES5 and CommonJS - * @param {Object} $http Instance of request handling library - * @param {Object} options Configuration object - * @return {VueAuthenticate} VueAuthenticate instance - */ -plugin.factory = function ($http, options) { - return new VueAuthenticate($http, options) -}; - -export default plugin; -export { VueAuthenticate }; diff --git a/dist/vue-authenticate.esm.js b/dist/vue-authenticate.esm.js new file mode 100644 index 0000000..6bef7ab --- /dev/null +++ b/dist/vue-authenticate.esm.js @@ -0,0 +1,1640 @@ +/** + * vue-authenticate v1.5.0 + * https://github.com/dgrubelic/vue-authenticate + * Released under the MIT License. + * + */ + +if (typeof Object.assign != 'function') { + Object.assign = function (target, varArgs) { + if (target == null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var to = Object(target); + + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + + if (nextSource != null) { + // Skip over if undefined or null + for (var nextKey in nextSource) { + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + }; +} + +function camelCase(name) { + return name.replace(/([\:\-\_]+(.))/g, function ( + _, + separator, + letter, + offset + ) { + return offset ? letter.toUpperCase() : letter; + }); +} + +function isUndefined(value) { + return typeof value === 'undefined'; +} + +function isObject(value) { + return value !== null && typeof value === 'object'; +} + +function isString(value) { + return typeof value === 'string'; +} + +function isFunction(value) { + return typeof value === 'function'; +} + +function objectExtend(a, b) { + // Don't touch 'null' or 'undefined' objects. + if (a == null || b == null) { + return a; + } + + Object.keys(b).forEach(function (key) { + if (Object.prototype.toString.call(b[key]) == '[object Object]') { + if (Object.prototype.toString.call(a[key]) != '[object Object]') { + a[key] = b[key]; + } else { + a[key] = objectExtend(a[key], b[key]); + } + } else { + a[key] = b[key]; + } + }); + + return a; +} + +/** + * Assemble url from two segments + * + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {String} baseUrl Base url + * @param {String} url URI + * @return {String} + */ +function joinUrl(baseUrl, url) { + if (/^(?:[a-z]+:)?\/\//i.test(url)) { + return url; + } + let joined = [baseUrl, url].join('/'); + let normalize = function (str) { + return str + .replace(/[\/]+/g, '/') + .replace(/\/\?/g, '?') + .replace(/\/\#/g, '#') + .replace(/\:\//g, '://'); + }; + return normalize(joined); +} + +/** + * Get full path based on current location + * + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {Location} location + * @return {String} + */ +function getFullUrlPath(location) { + const isHttps = location.protocol === 'https:'; + return ( + location.protocol + + '//' + + location.hostname + + ':' + + (location.port || (isHttps ? '443' : '80')) + + (/^\//.test(location.pathname) + ? location.pathname + : '/' + location.pathname) + ); +} + +/** + * Parse query string variables + * + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {String} Query string + * @return {String} + */ +function parseQueryString(str) { + let obj = {}; + let key; + let value; + (str || '').split('&').forEach(keyValue => { + if (keyValue) { + value = keyValue.split('='); + key = decodeURIComponent(value[0]); + obj[key] = !!value[1] ? decodeURIComponent(value[1]) : true; + } + }); + return obj; +} + +/** + * Decode base64 string + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {String} str base64 encoded string + * @return {Object} + */ +function decodeBase64(str) { + let buffer; + if (typeof module !== 'undefined' && module.exports) { + try { + buffer = require('buffer').Buffer; + } catch (err) { + // noop + } + } + + let fromCharCode = String.fromCharCode; + + let re_btou = new RegExp( + [ + '[\xC0-\xDF][\x80-\xBF]', + '[\xE0-\xEF][\x80-\xBF]{2}', + '[\xF0-\xF7][\x80-\xBF]{3}', + ].join('|'), + 'g' + ); + + let cb_btou = function (cccc) { + switch (cccc.length) { + case 4: + let cp = + ((0x07 & cccc.charCodeAt(0)) << 18) | + ((0x3f & cccc.charCodeAt(1)) << 12) | + ((0x3f & cccc.charCodeAt(2)) << 6) | + (0x3f & cccc.charCodeAt(3)); + let offset = cp - 0x10000; + return ( + fromCharCode((offset >>> 10) + 0xd800) + + fromCharCode((offset & 0x3ff) + 0xdc00) + ); + case 3: + return fromCharCode( + ((0x0f & cccc.charCodeAt(0)) << 12) | + ((0x3f & cccc.charCodeAt(1)) << 6) | + (0x3f & cccc.charCodeAt(2)) + ); + default: + return fromCharCode( + ((0x1f & cccc.charCodeAt(0)) << 6) | (0x3f & cccc.charCodeAt(1)) + ); + } + }; + + let btou = function (b) { + return b.replace(re_btou, cb_btou); + }; + + let _decode = buffer + ? function (a) { + return (a.constructor === buffer.constructor + ? a + : new buffer(a, 'base64') + ).toString(); + } + : function (a) { + return btou(atob(a)); + }; + + return _decode( + String(str) + .replace(/[-_]/g, function (m0) { + return m0 === '-' ? '+' : '/'; + }) + .replace(/[^A-Za-z0-9\+\/]/g, '') + ); +} + +function parseCookies(str = '') { + if (str.length === 0) return {}; + const parsed = {}; + const pattern = new RegExp('\\s*;\\s*'); + str.split(pattern).forEach(i => { + const [encodedKey, encodedValue] = i.split('='); + const key = decodeURIComponent(encodedKey); + const value = decodeURIComponent(encodedValue); + parsed[key] = value; + }); + return parsed; +} + +function formatOptions(options) { + const { path, domain, expires, secure } = options; + return [ + typeof path === 'undefined' || path === null ? '' : ';path=' + path, + typeof domain === 'undefined' || domain === null ? '' : ';domain=' + domain, + typeof expires === 'undefined' || expires === null + ? '' + : ';expires=' + expires.toUTCString(), + typeof secure === 'undefined' || secure === null || secure === false + ? '' + : ';secure', + ].join(''); +} + +function formatCookie(key, value, options) { + return [ + encodeURIComponent(key), + '=', + encodeURIComponent(value), + formatOptions(options), + ].join(''); +} + +function getObjectProperty(objectRef, propertyName) { + let value = undefined; + let valueRef = objectRef; + const propNames = propertyName.split('.'); + + for (var i = 0; i < propNames.length; i++) { + const key = propNames[i]; + value = valueRef[key]; + + if (isObject(value)) { + valueRef = valueRef[key]; + } else { + break; + } + } + + return value; +} + +// Store setTimeout reference so promise-polyfill will be unaffected by +// other code modifying setTimeout (like sinon.useFakeTimers()) +var setTimeoutFunc = setTimeout; + +function noop() {} + +// Polyfill for Function.prototype.bind +function bind(fn, thisArg) { + return function () { + fn.apply(thisArg, arguments); + }; +} + +function Promise$1(fn) { + if (typeof this !== 'object') + throw new TypeError('Promises must be constructed via new'); + if (typeof fn !== 'function') throw new TypeError('not a function'); + this._state = 0; + this._handled = false; + this._value = undefined; + this._deferreds = []; + + doResolve(fn, this); +} + +function handle(self, deferred) { + while (self._state === 3) { + self = self._value; + } + if (self._state === 0) { + self._deferreds.push(deferred); + return; + } + self._handled = true; + Promise$1._immediateFn(function () { + var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; + if (cb === null) { + (self._state === 1 ? resolve : reject)(deferred.promise, self._value); + return; + } + var ret; + try { + ret = cb(self._value); + } catch (e) { + reject(deferred.promise, e); + return; + } + resolve(deferred.promise, ret); + }); +} + +function resolve(self, newValue) { + try { + // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure + if (newValue === self) + throw new TypeError('A promise cannot be resolved with itself.'); + if ( + newValue && + (typeof newValue === 'object' || typeof newValue === 'function') + ) { + var then = newValue.then; + if (newValue instanceof Promise$1) { + self._state = 3; + self._value = newValue; + finale(self); + return; + } else if (typeof then === 'function') { + doResolve(bind(then, newValue), self); + return; + } + } + self._state = 1; + self._value = newValue; + finale(self); + } catch (e) { + reject(self, e); + } +} + +function reject(self, newValue) { + self._state = 2; + self._value = newValue; + finale(self); +} + +function finale(self) { + if (self._state === 2 && self._deferreds.length === 0) { + Promise$1._immediateFn(function () { + if (!self._handled) { + Promise$1._unhandledRejectionFn(self._value); + } + }); + } + + for (var i = 0, len = self._deferreds.length; i < len; i++) { + handle(self, self._deferreds[i]); + } + self._deferreds = null; +} + +function Handler(onFulfilled, onRejected, promise) { + this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; + this.onRejected = typeof onRejected === 'function' ? onRejected : null; + this.promise = promise; +} + +/** + * Take a potentially misbehaving resolver function and make sure + * onFulfilled and onRejected are only called once. + * + * Makes no guarantees about asynchrony. + */ +function doResolve(fn, self) { + var done = false; + try { + fn( + function (value) { + if (done) return; + done = true; + resolve(self, value); + }, + function (reason) { + if (done) return; + done = true; + reject(self, reason); + } + ); + } catch (ex) { + if (done) return; + done = true; + reject(self, ex); + } +} + +Promise$1.prototype['catch'] = function (onRejected) { + return this.then(null, onRejected); +}; + +Promise$1.prototype.then = function (onFulfilled, onRejected) { + var prom = new this.constructor(noop); + + handle(this, new Handler(onFulfilled, onRejected, prom)); + return prom; +}; + +Promise$1.all = function (arr) { + var args = Array.prototype.slice.call(arr); + + return new Promise$1(function (resolve, reject) { + if (args.length === 0) return resolve([]); + var remaining = args.length; + + function res(i, val) { + try { + if (val && (typeof val === 'object' || typeof val === 'function')) { + var then = val.then; + if (typeof then === 'function') { + then.call( + val, + function (val) { + res(i, val); + }, + reject + ); + return; + } + } + args[i] = val; + if (--remaining === 0) { + resolve(args); + } + } catch (ex) { + reject(ex); + } + } + + for (var i = 0; i < args.length; i++) { + res(i, args[i]); + } + }); +}; + +Promise$1.resolve = function (value) { + if (value && typeof value === 'object' && value.constructor === Promise$1) { + return value; + } + + return new Promise$1(function (resolve) { + resolve(value); + }); +}; + +Promise$1.reject = function (value) { + return new Promise$1(function (resolve, reject) { + reject(value); + }); +}; + +Promise$1.race = function (values) { + return new Promise$1(function (resolve, reject) { + for (var i = 0, len = values.length; i < len; i++) { + values[i].then(resolve, reject); + } + }); +}; + +// Use polyfill for setImmediate for performance gains +Promise$1._immediateFn = + (typeof setImmediate === 'function' && + function (fn) { + setImmediate(fn); + }) || + function (fn) { + setTimeoutFunc(fn, 0); + }; + +Promise$1._unhandledRejectionFn = function _unhandledRejectionFn(err) { + if (typeof console !== 'undefined' && console) { + console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console + } +}; + +/** + * Set the immediate function to execute callbacks + * @param fn {function} Function to execute + * @deprecated + */ +Promise$1._setImmediateFn = function _setImmediateFn(fn) { + Promise$1._immediateFn = fn; +}; + +/** + * Change the function to execute on unhandled rejection + * @param {function} fn Function to execute on unhandled rejection + * @deprecated + */ +Promise$1._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { + Promise$1._unhandledRejectionFn = fn; +}; + +const fakeDocument = { + createElement() { }, +}; + +const fakeWindow = { + atob() { }, + open() { }, + location: {}, + localStorage: { + setItem() { }, + getItem() { }, + removeItem() { }, + }, + sessionStorage: { + setItem() { }, + getItem() { }, + removeItem() { }, + }, +}; + +const $document = (typeof document !== undefined) + ? document + : fakeDocument; + +const $window = (typeof window !== undefined) + ? window + : fakeWindow; + +function getCookieDomainUrl() { + try { + return $window.location.hostname; + } catch (e) {} + + return ''; +} + +function getRedirectUri(uri) { + try { + return !isUndefined(uri) + ? `${$window.location.origin}${uri}` + : $window.location.origin; + } catch (e) {} + + return uri || null; +} + +/** + * Default configuration + */ +var defaultOptions = { + baseUrl: null, + tokenPath: 'access_token', + tokenName: 'token', + tokenPrefix: 'vueauth', + tokenHeader: 'Authorization', + tokenType: 'Bearer', + loginUrl: '/auth/login', + registerUrl: '/auth/register', + logoutUrl: null, + storageType: 'localStorage', + storageNamespace: 'vue-authenticate', + cookieStorage: { + domain: getCookieDomainUrl(), + path: '/', + secure: false, + }, + requestDataKey: 'data', + responseDataKey: 'data', + + /** + * Default request interceptor for Axios library + * @context {VueAuthenticate} + */ + bindRequestInterceptor: function ($auth) { + const tokenHeader = $auth.options.tokenHeader; + + $auth.$http.interceptors.request.use(config => { + if ($auth.isAuthenticated()) { + config.headers[tokenHeader] = [ + $auth.options.tokenType, + $auth.getToken(), + ].join(' '); + } else { + delete config.headers[tokenHeader]; + } + return config; + }); + }, + + providers: { + facebook: { + name: 'facebook', + url: '/auth/facebook', + authorizationEndpoint: 'https://www.facebook.com/v10.0/dialog/oauth', + redirectUri: getRedirectUri('/'), + requiredUrlParams: ['display', 'scope'], + scope: ['email'], + scopeDelimiter: ',', + display: 'popup', + oauthType: '2.0', + popupOptions: { width: 580, height: 400 }, + }, + + google: { + name: 'google', + url: '/auth/google', + authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth', + redirectUri: getRedirectUri(), + requiredUrlParams: ['scope'], + optionalUrlParams: ['display'], + scope: ['profile', 'email'], + scopePrefix: 'openid', + scopeDelimiter: ' ', + display: 'popup', + oauthType: '2.0', + popupOptions: { width: 452, height: 633 }, + }, + + github: { + name: 'github', + url: '/auth/github', + authorizationEndpoint: 'https://github.com/login/oauth/authorize', + redirectUri: getRedirectUri(), + optionalUrlParams: ['scope'], + scope: ['user:email'], + scopeDelimiter: ' ', + oauthType: '2.0', + popupOptions: { width: 1020, height: 618 }, + }, + + instagram: { + name: 'instagram', + url: '/auth/instagram', + authorizationEndpoint: 'https://api.instagram.com/oauth/authorize', + redirectUri: getRedirectUri(), + requiredUrlParams: ['scope'], + scope: ['basic'], + scopeDelimiter: '+', + oauthType: '2.0', + popupOptions: { width: null, height: null }, + }, + + twitter: { + name: 'twitter', + url: '/auth/twitter', + authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate', + redirectUri: getRedirectUri(), + oauthType: '1.0', + popupOptions: { width: 495, height: 645 }, + }, + + bitbucket: { + name: 'bitbucket', + url: '/auth/bitbucket', + authorizationEndpoint: 'https://bitbucket.org/site/oauth2/authorize', + redirectUri: getRedirectUri('/'), + optionalUrlParams: ['scope'], + scope: ['email'], + scopeDelimiter: ' ', + oauthType: '2.0', + popupOptions: { width: 1020, height: 618 }, + }, + + linkedin: { + name: 'linkedin', + url: '/auth/linkedin', + authorizationEndpoint: 'https://www.linkedin.com/oauth/v2/authorization', + redirectUri: getRedirectUri(), + requiredUrlParams: ['state'], + scope: ['r_emailaddress'], + scopeDelimiter: ' ', + state: 'STATE', + oauthType: '2.0', + popupOptions: { width: 527, height: 582 }, + }, + + live: { + name: 'live', + url: '/auth/live', + authorizationEndpoint: 'https://login.live.com/oauth20_authorize.srf', + redirectUri: getRedirectUri(), + requiredUrlParams: ['display', 'scope'], + scope: ['wl.emails'], + scopeDelimiter: ' ', + display: 'popup', + oauthType: '2.0', + popupOptions: { width: 500, height: 560 }, + }, + + oauth1: { + name: null, + url: '/auth/oauth1', + authorizationEndpoint: null, + redirectUri: getRedirectUri(), + oauthType: '1.0', + popupOptions: null, + }, + + oauth2: { + name: null, + url: '/auth/oauth2', + clientId: null, + redirectUri: getRedirectUri(), + authorizationEndpoint: null, + defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], + requiredUrlParams: null, + optionalUrlParams: null, + scope: null, + scopePrefix: null, + scopeDelimiter: null, + state: null, + oauthType: '2.0', + popupOptions: null, + responseType: 'code', + responseParams: { + code: 'code', + clientId: 'clientId', + redirectUri: 'redirectUri', + }, + }, + }, +}; + +class CookieStorage { + constructor(defaultOptions) { + this._defaultOptions = objectExtend( + { + domain: getCookieDomainUrl(), + expires: null, + path: '/', + secure: false, + }, + defaultOptions + ); + } + + setItem(key, value) { + const options = objectExtend({}, this._defaultOptions); + const cookie = formatCookie(key, value, options); + this._setCookie(cookie); + } + + getItem(key) { + const cookies = parseCookies(this._getCookie()); + return cookies.hasOwnProperty(key) ? cookies[key] : null; + } + + removeItem(key) { + const value = ''; + const defaultOptions = objectExtend({}, this._defaultOptions); + const options = objectExtend(defaultOptions, { + expires: new Date(0), + }); + const cookie = formatCookie(key, value, options); + this._setCookie(cookie); + } + + _getCookie() { + try { + return $document.cookie === 'undefined' ? '' : $document.cookie; + } catch (e) {} + + return ''; + } + + _setCookie(cookie) { + try { + $document.cookie = cookie; + } catch (e) {} + } +} + +class LocalStorage { + constructor(namespace) { + this.namespace = namespace || null; + } + + setItem(key, value) { + $window.localStorage.setItem(this._getStorageKey(key), value); + } + + getItem(key) { + return $window.localStorage.getItem(this._getStorageKey(key)); + } + + removeItem(key) { + $window.localStorage.removeItem(this._getStorageKey(key)); + } + + _getStorageKey(key) { + if (this.namespace) { + return [this.namespace, key].join('.'); + } + return key; + } +} + +class MemoryStorage { + constructor(namespace) { + this.namespace = namespace || null; + this._storage = {}; + } + + setItem(key, value) { + this._storage[this._getStorageKey(key)] = value; + } + + getItem(key) { + return this._storage[this._getStorageKey(key)]; + } + + removeItem(key) { + delete this._storage[this._getStorageKey(key)]; + } + + _getStorageKey(key) { + if (this.namespace) { + return [this.namespace, key].join('.'); + } + return key; + } +} + +class SessionStorage { + constructor(namespace) { + this.namespace = namespace || null; + } + + setItem(key, value) { + $window.sessionStorage.setItem(this._getStorageKey(key), value); + } + + getItem(key) { + return $window.sessionStorage.getItem(this._getStorageKey(key)); + } + + removeItem(key) { + $window.sessionStorage.removeItem(this._getStorageKey(key)); + } + + _getStorageKey(key) { + if (this.namespace) { + return [this.namespace, key].join('.'); + } + return key; + } +} + +function StorageFactory(options) { + switch (options.storageType) { + case 'localStorage': + try { + $window.localStorage.setItem('testKey', 'test'); + $window.localStorage.removeItem('testKey'); + return new LocalStorage(options.storageNamespace); + } catch (e) {} + + case 'sessionStorage': + try { + $window.sessionStorage.setItem('testKey', 'test'); + $window.sessionStorage.removeItem('testKey'); + return new SessionStorage(options.storageNamespace); + } catch (e) {} + + case 'cookieStorage': + return new CookieStorage(options.cookieStorage); + + case 'memoryStorage': + default: + return new MemoryStorage(options.storageNamespace); + } +} + +/** + * OAuth2 popup management class + * + * @author Sahat Yalkabov + * @copyright Class mostly taken from https://github.com/sahat/satellizer + * and adjusted to fit vue-authenticate library + */ +class OAuthPopup { + constructor(url, name, popupOptions) { + this.popup = null; + this.url = url; + this.name = name; + this.popupOptions = popupOptions; + } + + open(redirectUri, skipPooling) { + try { + this.popup = $window.open(this.url, this.name, this._stringifyOptions()); + if (this.popup && this.popup.focus) { + this.popup.focus(); + } + + if (skipPooling) { + return Promise$1.resolve(); + } else { + return this.pooling(redirectUri); + } + } catch (e) { + return Promise$1.reject(new Error('OAuth popup error occurred')); + } + } + + pooling(redirectUri) { + return new Promise$1((resolve, reject) => { + const redirectUriParser = $document.createElement('a'); + redirectUriParser.href = redirectUri; + const redirectUriPath = getFullUrlPath(redirectUriParser); + + let poolingInterval = setInterval(() => { + if ( + !this.popup || + this.popup.closed || + this.popup.closed === undefined + ) { + clearInterval(poolingInterval); + poolingInterval = null; + reject(new Error('Auth popup window closed')); + } + + try { + const popupWindowPath = getFullUrlPath(this.popup.location); + + if (popupWindowPath === redirectUriPath) { + if (this.popup.location.search || this.popup.location.hash) { + const query = parseQueryString( + this.popup.location.search.substring(1).replace(/\/$/, '') + ); + const hash = parseQueryString( + this.popup.location.hash.substring(1).replace(/[\/$]/, '') + ); + let params = objectExtend({}, query); + params = objectExtend(params, hash); + + if (params.error) { + reject(new Error(params.error)); + } else { + resolve(params); + } + } else { + reject( + new Error( + 'OAuth redirect has occurred but no query or hash parameters were found.' + ) + ); + } + + clearInterval(poolingInterval); + poolingInterval = null; + this.popup.close(); + } + } catch (e) { + // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame. + } + }, 250); + }); + } + + _stringifyOptions() { + let options = []; + for (var optionKey in this.popupOptions) { + if (!isUndefined(this.popupOptions[optionKey])) { + options.push(`${optionKey}=${this.popupOptions[optionKey]}`); + } + } + return options.join(','); + } +} + +const defaultProviderConfig$1 = { + name: null, + url: null, + authorizationEndpoint: null, + scope: null, + scopePrefix: null, + scopeDelimiter: null, + redirectUri: null, + requiredUrlParams: null, + defaultUrlParams: null, + oauthType: '1.0', + popupOptions: {}, +}; + +class OAuth { + constructor($http, storage, providerConfig, options) { + this.$http = $http; + this.storage = storage; + this.providerConfig = objectExtend({}, defaultProviderConfig$1); + this.providerConfig = objectExtend(this.providerConfig, providerConfig); + this.options = options; + } + + /** + * Initialize OAuth1 process + * @param {Object} userData User data + * @return {Promise} + */ + init(userData) { + this.oauthPopup = new OAuthPopup( + 'about:blank', + this.providerConfig.name, + this.providerConfig.popupOptions + ); + + if (!$window['cordova']) { + this.oauthPopup.open(this.providerConfig.redirectUri, true); + } + + return this.getRequestToken().then(response => { + return this.openPopup(response).then(popupResponse => { + return this.exchangeForToken(popupResponse, userData); + }); + }); + } + + /** + * Get OAuth1 request token + * @return {Promise} + */ + getRequestToken() { + let requestOptions = {}; + requestOptions.method = 'POST'; + requestOptions[this.options.requestDataKey] = objectExtend( + {}, + this.providerConfig + ); + requestOptions.withCredentials = this.options.withCredentials; + if (this.options.baseUrl) { + requestOptions.url = joinUrl( + this.options.baseUrl, + this.providerConfig.url + ); + } else { + requestOptions.url = this.providerConfig.url; + } + + return this.$http(requestOptions); + } + + /** + * Open OAuth1 popup + * @param {Object} response Response object containing request token + * @return {Promise} + */ + openPopup(response) { + const url = [ + this.providerConfig.authorizationEndpoint, + this.buildQueryString(response[this.options.responseDataKey]), + ].join('?'); + + this.oauthPopup.popup.location = url; + if ($window['cordova']) { + return this.oauthPopup.open(this.providerConfig.redirectUri); + } else { + return this.oauthPopup.pooling(this.providerConfig.redirectUri); + } + } + + /** + * Exchange token and token verifier for access token + * @param {Object} oauth OAuth data containing token and token verifier + * @param {Object} userData User data + * @return {Promise} + */ + exchangeForToken(oauth, userData) { + let payload = objectExtend({}, userData); + payload = objectExtend(payload, oauth); + let requestOptions = {}; + requestOptions.method = 'POST'; + requestOptions[this.options.requestDataKey] = payload; + requestOptions.withCredentials = this.options.withCredentials; + if (this.options.baseUrl) { + requestOptions.url = joinUrl( + this.options.baseUrl, + this.providerConfig.url + ); + } else { + requestOptions.url = this.providerConfig.url; + } + return this.$http(requestOptions); + } + + buildQueryString(params) { + const parsedParams = []; + for (var key in params) { + let value = params[key]; + parsedParams.push( + encodeURIComponent(key) + '=' + encodeURIComponent(value) + ); + } + return parsedParams.join('&'); + } +} + +/** + * Default provider configuration + * @type {Object} + */ +const defaultProviderConfig = { + name: null, + url: null, + clientId: null, + authorizationEndpoint: null, + redirectUri: null, + scope: null, + scopePrefix: null, + scopeDelimiter: null, + state: null, + requiredUrlParams: null, + defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], + responseType: 'code', + responseParams: { + code: 'code', + clientId: 'clientId', + redirectUri: 'redirectUri', + }, + oauthType: '2.0', + popupOptions: {}, +}; + +class OAuth2 { + constructor($http, storage, providerConfig, options) { + this.$http = $http; + this.storage = storage; + this.providerConfig = objectExtend({}, defaultProviderConfig); + this.providerConfig = objectExtend(this.providerConfig, providerConfig); + this.options = options; + } + + init(userData) { + let stateName = this.providerConfig.name + '_state'; + if (isFunction(this.providerConfig.state)) { + this.storage.setItem(stateName, this.providerConfig.state()); + } else if (isString(this.providerConfig.state)) { + this.storage.setItem(stateName, this.providerConfig.state); + } + + let url = [ + this.providerConfig.authorizationEndpoint, + this._stringifyRequestParams(), + ].join('?'); + + this.oauthPopup = new OAuthPopup( + url, + this.providerConfig.name, + this.providerConfig.popupOptions + ); + + return new Promise((resolve, reject) => { + this.oauthPopup + .open(this.providerConfig.redirectUri) + .then(response => { + if ( + this.providerConfig.responseType === 'token' || + !this.providerConfig.url + ) { + return resolve(response); + } + + if ( + response.state && + response.state !== this.storage.getItem(stateName) + ) { + return reject( + new Error( + 'State parameter value does not match original OAuth request state value' + ) + ); + } + + resolve(this.exchangeForToken(response, userData)); + }) + .catch(err => { + reject(err); + }); + }); + } + + /** + * Exchange temporary oauth data for access token + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {[type]} oauth [description] + * @param {[type]} userData [description] + * @return {[type]} [description] + */ + exchangeForToken(oauth, userData) { + let payload = objectExtend({}, userData); + + for (let key in this.providerConfig.responseParams) { + this.providerConfig.responseParams[key]; + + switch (key) { + case 'code': + payload[key] = oauth.code; + break; + case 'clientId': + payload[key] = this.providerConfig.clientId; + break; + case 'redirectUri': + payload[key] = this.providerConfig.redirectUri; + break; + default: + payload[key] = oauth[key]; + } + } + + if (oauth.state) { + payload.state = oauth.state; + } + + let exchangeTokenUrl; + if (this.options.baseUrl) { + exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url); + } else { + exchangeTokenUrl = this.providerConfig.url; + } + + return this.$http.post(exchangeTokenUrl, payload, { + withCredentials: this.options.withCredentials, + }); + } + + /** + * Stringify oauth params + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @return {String} + */ + _stringifyRequestParams() { + let keyValuePairs = []; + let paramCategories = [ + 'defaultUrlParams', + 'requiredUrlParams', + 'optionalUrlParams', + ]; + + paramCategories.forEach(categoryName => { + if (!this.providerConfig[categoryName]) return; + if (!Array.isArray(this.providerConfig[categoryName])) return; + + this.providerConfig[categoryName].forEach(paramName => { + let camelCaseParamName = camelCase(paramName); + let paramValue = isFunction(this.providerConfig[paramName]) + ? this.providerConfig[paramName]() + : this.providerConfig[camelCaseParamName]; + + if (paramName === 'redirect_uri' && !paramValue) return; + + if (paramName === 'state') { + let stateName = this.providerConfig.name + '_state'; + paramValue = encodeURIComponent(this.storage.getItem(stateName)); + } + if (paramName === 'scope' && Array.isArray(paramValue)) { + paramValue = paramValue.join(this.providerConfig.scopeDelimiter); + if (this.providerConfig.scopePrefix) { + paramValue = [this.providerConfig.scopePrefix, paramValue].join( + this.providerConfig.scopeDelimiter + ); + } + } + + keyValuePairs.push([paramName, paramValue]); + }); + }); + + return keyValuePairs + .map(param => { + return param.join('='); + }) + .join('&'); + } +} + +class VueAuthenticate { + constructor($http, overrideOptions) { + let options = objectExtend({}, defaultOptions); + options = objectExtend(options, overrideOptions); + let storage = StorageFactory(options); + + Object.defineProperties(this, { + $http: { + get() { + return $http; + }, + }, + + options: { + get() { + return options; + }, + }, + + storage: { + get() { + return storage; + }, + }, + + tokenName: { + get() { + if (this.options.tokenPrefix) { + return [this.options.tokenPrefix, this.options.tokenName].join('_'); + } else { + return this.options.tokenName; + } + }, + }, + }); + + // Setup request interceptors + if ( + this.options.bindRequestInterceptor && + isFunction(this.options.bindRequestInterceptor) + ) { + this.options.bindRequestInterceptor.call(this, this); + } else { + throw new Error('Request interceptor must be functions'); + } + } + + /** + * Check if user is authenticated + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * @return {Boolean} + */ + isAuthenticated() { + let token = this.storage.getItem(this.tokenName); + + if (token) { + // Token is present + if (token.split('.').length === 3) { + // Token with a valid JWT format XXX.YYY.ZZZ + try { + // Could be a valid JWT or an access token with the same format + const base64Url = token.split('.')[1]; + const base64 = base64Url.replace('-', '+').replace('_', '/'); + const exp = JSON.parse($window.atob(base64)).exp; + if (typeof exp === 'number') { + // JWT with an optonal expiration claims + return Math.round(new Date().getTime() / 1000) < exp; + } + } catch (e) { + return true; // Pass: Non-JWT token that looks like JWT + } + } + return true; // Pass: All other tokens + } + return false; + } + + /** + * Get token if user is authenticated + * @return {String} Authentication token + */ + getToken() { + return this.storage.getItem(this.tokenName); + } + + /** + * Set new authentication token + * @param {String|Object} token + */ + setToken(response, tokenPath) { + if (response[this.options.responseDataKey]) { + response = response[this.options.responseDataKey]; + } + + const responseTokenPath = tokenPath || this.options.tokenPath; + const token = getObjectProperty(response, responseTokenPath); + + if (token) { + this.storage.setItem(this.tokenName, token); + } + } + + getPayload() { + const token = this.storage.getItem(this.tokenName); + + if (token && token.split('.').length === 3) { + try { + const base64Url = token.split('.')[1]; + const base64 = base64Url.replace('-', '+').replace('_', '/'); + return JSON.parse(decodeBase64(base64)); + } catch (e) {} + } + } + + /** + * Login user using email and password + * @param {Object} user User data + * @param {Object} requestOptions Request options + * @return {Promise} Request promise + */ + login(user, requestOptions) { + requestOptions = requestOptions || {}; + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.loginUrl); + requestOptions[this.options.requestDataKey] = + user || requestOptions[this.options.requestDataKey]; + requestOptions.method = requestOptions.method || 'POST'; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; + + return this.$http(requestOptions).then(response => { + this.setToken(response); + return response; + }); + } + + /** + * Register new user + * @param {Object} user User data + * @param {Object} requestOptions Request options + * @return {Promise} Request promise + */ + register(user, requestOptions) { + requestOptions = requestOptions || {}; + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.registerUrl); + requestOptions[this.options.requestDataKey] = + user || requestOptions[this.options.requestDataKey]; + requestOptions.method = requestOptions.method || 'POST'; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; + + return this.$http(requestOptions).then(response => { + this.setToken(response); + return response; + }); + } + + /** + * Logout current user + * @param {Object} requestOptions Logout request options object + * @return {Promise} Request promise + */ + logout(requestOptions) { + if (!this.isAuthenticated()) { + return Promise$1.reject( + new Error('There is no currently authenticated user') + ); + } + + requestOptions = requestOptions || {}; + + if (requestOptions.url || this.options.logoutUrl) { + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.logoutUrl); + requestOptions.method = requestOptions.method || 'POST'; + requestOptions[this.options.requestDataKey] = + requestOptions[this.options.requestDataKey] || undefined; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; + + return this.$http(requestOptions).then(response => { + this.storage.removeItem(this.tokenName); + return response; + }); + } else { + this.storage.removeItem(this.tokenName); + return Promise$1.resolve(); + } + } + + /** + * Authenticate user using authentication provider + * + * @param {String} provider Provider name + * @param {Object} userData User data + * @return {Promise} Request promise + */ + authenticate(provider, userData) { + return new Promise$1((resolve, reject) => { + var providerConfig = this.options.providers[provider]; + if (!providerConfig) { + return reject(new Error('Unknown provider')); + } + + let providerInstance; + switch (providerConfig.oauthType) { + case '1.0': + providerInstance = new OAuth( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + case '2.0': + providerInstance = new OAuth2( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + default: + return reject(new Error('Invalid OAuth type')); + } + + return providerInstance + .init(userData) + .then(response => { + this.setToken(response, providerConfig.tokenPath); + + if (this.isAuthenticated()) { + return resolve(response); + } else { + return reject(new Error('Authentication failed')); + } + }) + .catch(err => reject(err)); + }); + } + + /** + * Link user using authentication provider without login + * + * @param {String} provider Provider name + * @param {Object} userData User data + * @return {Promise} Request promise + */ + link(provider, userData) { + return new Promise$1((resolve, reject) => { + var providerConfig = this.options.providers[provider]; + if (!providerConfig) { + return reject(new Error('Unknown provider')); + } + + let providerInstance; + switch (providerConfig.oauthType) { + case '1.0': + providerInstance = new OAuth( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + case '2.0': + providerInstance = new OAuth2( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + default: + return reject(new Error('Invalid OAuth type')); + } + + return providerInstance + .init(userData) + .then(response => { + if (response[this.options.responseDataKey]) { + response = response[this.options.responseDataKey]; + } + + resolve(response); + }) + .catch(reject); + }); + } +} + +/** + * VueAuthenticate plugin + * @param {Object} Vue + * @param {Object} options + */ +function plugin(Vue, options) { + if (plugin.installed) { + return; + } + + plugin.installed = true; + + let vueAuthInstance = null; + Object.defineProperties(Vue.prototype, { + $auth: { + get() { + if (!vueAuthInstance) { + // Request handler library not found, throw error + if (!this.$http) { + throw new Error('Request handler instance not found'); + } + + vueAuthInstance = new VueAuthenticate(this.$http, options); + } + return vueAuthInstance; + }, + }, + }); +} + +/** + * External factory helper for ES5 and CommonJS + * @param {Object} $http Instance of request handling library + * @param {Object} options Configuration object + * @return {VueAuthenticate} VueAuthenticate instance + */ +plugin.factory = function ($http, options) { + return new VueAuthenticate($http, options); +}; + +export default plugin; diff --git a/dist/vue-authenticate.js b/dist/vue-authenticate.js index bddb965..50d91cb 100644 --- a/dist/vue-authenticate.js +++ b/dist/vue-authenticate.js @@ -1,1444 +1,1652 @@ -/*! - * vue-authenticate v1.3.5-beta.1 +/** + * vue-authenticate v1.5.0 * https://github.com/dgrubelic/vue-authenticate * Released under the MIT License. + * */ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.VueAuthenticate = factory()); + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.VueAuthenticate = factory()); }(this, (function () { 'use strict'; -if (typeof Object.assign != 'function') { - Object.assign = function(target, varArgs) { - 'use strict'; - var arguments$1 = arguments; + if (typeof Object.assign != 'function') { + Object.assign = function (target, varArgs) { + var arguments$1 = arguments; - if (target == null) { - throw new TypeError('Cannot convert undefined or null to object'); - } + if (target == null) { + throw new TypeError('Cannot convert undefined or null to object'); + } - var to = Object(target); + var to = Object(target); - for (var index = 1; index < arguments.length; index++) { - var nextSource = arguments$1[index]; + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments$1[index]; - if (nextSource != null) { // Skip over if undefined or null - for (var nextKey in nextSource) { - // Avoid bugs when hasOwnProperty is shadowed - if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { - to[nextKey] = nextSource[nextKey]; + if (nextSource != null) { + // Skip over if undefined or null + for (var nextKey in nextSource) { + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } } } } - } - return to; - }; -} + return to; + }; + } -function camelCase(name) { - return name.replace(/([\:\-\_]+(.))/g, function (_, separator, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }); -} + function camelCase(name) { + return name.replace(/([\:\-\_]+(.))/g, function ( + _, + separator, + letter, + offset + ) { + return offset ? letter.toUpperCase() : letter; + }); + } -function isUndefined(value) { - return typeof value === 'undefined' -} + function isUndefined(value) { + return typeof value === 'undefined'; + } + function isObject(value) { + return value !== null && typeof value === 'object'; + } + function isString(value) { + return typeof value === 'string'; + } -function isObject(value) { - return value !== null && typeof value === 'object' -} + function isFunction(value) { + return typeof value === 'function'; + } -function isString(value) { - return typeof value === 'string' -} + function objectExtend(a, b) { + // Don't touch 'null' or 'undefined' objects. + if (a == null || b == null) { + return a; + } + Object.keys(b).forEach(function (key) { + if (Object.prototype.toString.call(b[key]) == '[object Object]') { + if (Object.prototype.toString.call(a[key]) != '[object Object]') { + a[key] = b[key]; + } else { + a[key] = objectExtend(a[key], b[key]); + } + } else { + a[key] = b[key]; + } + }); + return a; + } -function isFunction(value) { - return typeof value === 'function' -} + /** + * Assemble url from two segments + * + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {String} baseUrl Base url + * @param {String} url URI + * @return {String} + */ + function joinUrl(baseUrl, url) { + if (/^(?:[a-z]+:)?\/\//i.test(url)) { + return url; + } + var joined = [baseUrl, url].join('/'); + var normalize = function (str) { + return str + .replace(/[\/]+/g, '/') + .replace(/\/\?/g, '?') + .replace(/\/\#/g, '#') + .replace(/\:\//g, '://'); + }; + return normalize(joined); + } -function objectExtend(a, b) { + /** + * Get full path based on current location + * + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {Location} location + * @return {String} + */ + function getFullUrlPath(location) { + var isHttps = location.protocol === 'https:'; + return ( + location.protocol + + '//' + + location.hostname + + ':' + + (location.port || (isHttps ? '443' : '80')) + + (/^\//.test(location.pathname) + ? location.pathname + : '/' + location.pathname) + ); + } - // Don't touch 'null' or 'undefined' objects. - if (a == null || b == null) { - return a; + /** + * Parse query string variables + * + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {String} Query string + * @return {String} + */ + function parseQueryString(str) { + var obj = {}; + var key; + var value; + (str || '').split('&').forEach(function (keyValue) { + if (keyValue) { + value = keyValue.split('='); + key = decodeURIComponent(value[0]); + obj[key] = !!value[1] ? decodeURIComponent(value[1]) : true; + } + }); + return obj; } - Object.keys(b).forEach(function (key) { - if (Object.prototype.toString.call(b[key]) == '[object Object]') { - if (Object.prototype.toString.call(a[key]) != '[object Object]') { - a[key] = b[key]; - } else { - a[key] = objectExtend(a[key], b[key]); + /** + * Decode base64 string + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param {String} str base64 encoded string + * @return {Object} + */ + function decodeBase64(str) { + var buffer; + if (typeof module !== 'undefined' && module.exports) { + try { + buffer = require('buffer').Buffer; + } catch (err) { + // noop } - } else { - a[key] = b[key]; } - }); - return a; -} + var fromCharCode = String.fromCharCode; + + var re_btou = new RegExp( + [ + '[\xC0-\xDF][\x80-\xBF]', + '[\xE0-\xEF][\x80-\xBF]{2}', + '[\xF0-\xF7][\x80-\xBF]{3}' ].join('|'), + 'g' + ); + + var cb_btou = function (cccc) { + switch (cccc.length) { + case 4: + var cp = + ((0x07 & cccc.charCodeAt(0)) << 18) | + ((0x3f & cccc.charCodeAt(1)) << 12) | + ((0x3f & cccc.charCodeAt(2)) << 6) | + (0x3f & cccc.charCodeAt(3)); + var offset = cp - 0x10000; + return ( + fromCharCode((offset >>> 10) + 0xd800) + + fromCharCode((offset & 0x3ff) + 0xdc00) + ); + case 3: + return fromCharCode( + ((0x0f & cccc.charCodeAt(0)) << 12) | + ((0x3f & cccc.charCodeAt(1)) << 6) | + (0x3f & cccc.charCodeAt(2)) + ); + default: + return fromCharCode( + ((0x1f & cccc.charCodeAt(0)) << 6) | (0x3f & cccc.charCodeAt(1)) + ); + } + }; + + var btou = function (b) { + return b.replace(re_btou, cb_btou); + }; + + var _decode = buffer + ? function (a) { + return (a.constructor === buffer.constructor + ? a + : new buffer(a, 'base64') + ).toString(); + } + : function (a) { + return btou(atob(a)); + }; + + return _decode( + String(str) + .replace(/[-_]/g, function (m0) { + return m0 === '-' ? '+' : '/'; + }) + .replace(/[^A-Za-z0-9\+\/]/g, '') + ); + } -/** - * Assemble url from two segments - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} baseUrl Base url - * @param {String} url URI - * @return {String} - */ -function joinUrl(baseUrl, url) { - if (/^(?:[a-z]+:)?\/\//i.test(url)) { - return url; + function parseCookies(str) { + if ( str === void 0 ) str = ''; + + if (str.length === 0) { return {}; } + var parsed = {}; + var pattern = new RegExp('\\s*;\\s*'); + str.split(pattern).forEach(function (i) { + var ref = i.split('='); + var encodedKey = ref[0]; + var encodedValue = ref[1]; + var key = decodeURIComponent(encodedKey); + var value = decodeURIComponent(encodedValue); + parsed[key] = value; + }); + return parsed; } - var joined = [baseUrl, url].join('/'); - var normalize = function (str) { - return str - .replace(/[\/]+/g, '/') - .replace(/\/\?/g, '?') - .replace(/\/\#/g, '#') - .replace(/\:\//g, '://'); - }; - return normalize(joined); -} -/** - * Get full path based on current location - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {Location} location - * @return {String} - */ -function getFullUrlPath(location) { - var isHttps = location.protocol === 'https:'; - return location.protocol + '//' + location.hostname + - ':' + (location.port || (isHttps ? '443' : '80')) + - (/^\//.test(location.pathname) ? location.pathname : '/' + location.pathname); -} + function formatOptions(options) { + var path = options.path; + var domain = options.domain; + var expires = options.expires; + var secure = options.secure; + return [ + typeof path === 'undefined' || path === null ? '' : ';path=' + path, + typeof domain === 'undefined' || domain === null ? '' : ';domain=' + domain, + typeof expires === 'undefined' || expires === null + ? '' + : ';expires=' + expires.toUTCString(), + typeof secure === 'undefined' || secure === null || secure === false + ? '' + : ';secure' ].join(''); + } -/** - * Parse query string variables - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} Query string - * @return {String} - */ -function parseQueryString(str) { - var obj = {}; - var key; - var value; - (str || '').split('&').forEach(function (keyValue) { - if (keyValue) { - value = keyValue.split('='); - key = decodeURIComponent(value[0]); - obj[key] = (!!value[1]) ? decodeURIComponent(value[1]) : true; - } - }); - return obj; -} + function formatCookie(key, value, options) { + return [ + encodeURIComponent(key), + '=', + encodeURIComponent(value), + formatOptions(options) ].join(''); + } -/** - * Decode base64 string - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} str base64 encoded string - * @return {Object} - */ -function decodeBase64(str) { - var buffer; - if (typeof module !== 'undefined' && module.exports) { - try { - buffer = require('buffer').Buffer; - } catch (err) { - // noop + function getObjectProperty(objectRef, propertyName) { + var value = undefined; + var valueRef = objectRef; + var propNames = propertyName.split('.'); + + for (var i = 0; i < propNames.length; i++) { + var key = propNames[i]; + value = valueRef[key]; + + if (isObject(value)) { + valueRef = valueRef[key]; + } else { + break; + } } + + return value; } - var fromCharCode = String.fromCharCode; - - var re_btou = new RegExp([ - '[\xC0-\xDF][\x80-\xBF]', - '[\xE0-\xEF][\x80-\xBF]{2}', - '[\xF0-\xF7][\x80-\xBF]{3}' - ].join('|'), 'g'); - - var cb_btou = function (cccc) { - switch (cccc.length) { - case 4: - var cp = ((0x07 & cccc.charCodeAt(0)) << 18) - | ((0x3f & cccc.charCodeAt(1)) << 12) - | ((0x3f & cccc.charCodeAt(2)) << 6) - | (0x3f & cccc.charCodeAt(3)); - var offset = cp - 0x10000; - return (fromCharCode((offset >>> 10) + 0xD800) - + fromCharCode((offset & 0x3FF) + 0xDC00)); - case 3: - return fromCharCode( - ((0x0f & cccc.charCodeAt(0)) << 12) - | ((0x3f & cccc.charCodeAt(1)) << 6) - | (0x3f & cccc.charCodeAt(2)) - ); - default: - return fromCharCode( - ((0x1f & cccc.charCodeAt(0)) << 6) - | (0x3f & cccc.charCodeAt(1)) - ); - } - }; + // Store setTimeout reference so promise-polyfill will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + var setTimeoutFunc = setTimeout; - var btou = function (b) { - return b.replace(re_btou, cb_btou); - }; + function noop() {} - var _decode = buffer ? function (a) { - return (a.constructor === buffer.constructor - ? a : new buffer(a, 'base64')).toString(); + // Polyfill for Function.prototype.bind + function bind(fn, thisArg) { + return function () { + fn.apply(thisArg, arguments); + }; } - : function (a) { - return btou(atob(a)); - }; - return _decode( - String(str).replace(/[-_]/g, function (m0) { - return m0 === '-' ? '+' : '/'; - }) - .replace(/[^A-Za-z0-9\+\/]/g, '') - ); -} - -function parseCookies(str) { - if (str.length === 0) { return {}; } - var parsed = {}; - var pattern = new RegExp('\\s*;\\s*'); - str.split(pattern).forEach(function (i) { - var ref = i.split('='); - var encodedKey = ref[0]; - var encodedValue = ref[1]; - var key = decodeURIComponent(encodedKey); - var value = decodeURIComponent(encodedValue); - parsed[key] = value; - }); - return parsed; -} - -function formatOptions(options) { - var path = options.path; - var domain = options.domain; - var expires = options.expires; - var secure = options.secure; - return [ - typeof path === 'undefined' || path === null - ? '' : ';path=' + path, - typeof domain === 'undefined' || domain === null - ? '' : ';domain=' + domain, - typeof expires === 'undefined' || expires === null - ? '' : ';expires=' + expires.toUTCString(), - typeof secure === 'undefined' || secure === null || secure === false - ? '' : ';secure' - ].join(''); -} - -function formatCookie(key, value, options) { - return [ - encodeURIComponent(key), - '=', - encodeURIComponent(value), - formatOptions(options) - ].join(''); -} - -// Store setTimeout reference so promise-polyfill will be unaffected by -// other code modifying setTimeout (like sinon.useFakeTimers()) -var setTimeoutFunc = setTimeout; - -function noop() {} - -// Polyfill for Function.prototype.bind -function bind(fn, thisArg) { - return function () { - fn.apply(thisArg, arguments); - }; -} - -function Promise$1(fn) { - if (typeof this !== 'object') { throw new TypeError('Promises must be constructed via new'); } - if (typeof fn !== 'function') { throw new TypeError('not a function'); } - this._state = 0; - this._handled = false; - this._value = undefined; - this._deferreds = []; - - doResolve(fn, this); -} - -function handle(self, deferred) { - while (self._state === 3) { - self = self._value; - } - if (self._state === 0) { - self._deferreds.push(deferred); - return; + function Promise$1(fn) { + if (typeof this !== 'object') + { throw new TypeError('Promises must be constructed via new'); } + if (typeof fn !== 'function') { throw new TypeError('not a function'); } + this._state = 0; + this._handled = false; + this._value = undefined; + this._deferreds = []; + + doResolve(fn, this); } - self._handled = true; - Promise$1._immediateFn(function () { - var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; - if (cb === null) { - (self._state === 1 ? resolve : reject)(deferred.promise, self._value); - return; + + function handle(self, deferred) { + while (self._state === 3) { + self = self._value; } - var ret; - try { - ret = cb(self._value); - } catch (e) { - reject(deferred.promise, e); + if (self._state === 0) { + self._deferreds.push(deferred); return; } - resolve(deferred.promise, ret); - }); -} - -function resolve(self, newValue) { - try { - // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure - if (newValue === self) { throw new TypeError('A promise cannot be resolved with itself.'); } - if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { - var then = newValue.then; - if (newValue instanceof Promise$1) { - self._state = 3; - self._value = newValue; - finale(self); + self._handled = true; + Promise$1._immediateFn(function () { + var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; + if (cb === null) { + (self._state === 1 ? resolve : reject)(deferred.promise, self._value); return; - } else if (typeof then === 'function') { - doResolve(bind(then, newValue), self); + } + var ret; + try { + ret = cb(self._value); + } catch (e) { + reject(deferred.promise, e); return; } + resolve(deferred.promise, ret); + }); + } + + function resolve(self, newValue) { + try { + // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure + if (newValue === self) + { throw new TypeError('A promise cannot be resolved with itself.'); } + if ( + newValue && + (typeof newValue === 'object' || typeof newValue === 'function') + ) { + var then = newValue.then; + if (newValue instanceof Promise$1) { + self._state = 3; + self._value = newValue; + finale(self); + return; + } else if (typeof then === 'function') { + doResolve(bind(then, newValue), self); + return; + } + } + self._state = 1; + self._value = newValue; + finale(self); + } catch (e) { + reject(self, e); } - self._state = 1; + } + + function reject(self, newValue) { + self._state = 2; self._value = newValue; finale(self); - } catch (e) { - reject(self, e); - } -} - -function reject(self, newValue) { - self._state = 2; - self._value = newValue; - finale(self); -} - -function finale(self) { - if (self._state === 2 && self._deferreds.length === 0) { - Promise$1._immediateFn(function() { - if (!self._handled) { - Promise$1._unhandledRejectionFn(self._value); - } - }); } - for (var i = 0, len = self._deferreds.length; i < len; i++) { - handle(self, self._deferreds[i]); + function finale(self) { + if (self._state === 2 && self._deferreds.length === 0) { + Promise$1._immediateFn(function () { + if (!self._handled) { + Promise$1._unhandledRejectionFn(self._value); + } + }); + } + + for (var i = 0, len = self._deferreds.length; i < len; i++) { + handle(self, self._deferreds[i]); + } + self._deferreds = null; } - self._deferreds = null; -} -function Handler(onFulfilled, onRejected, promise) { - this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; - this.onRejected = typeof onRejected === 'function' ? onRejected : null; - this.promise = promise; -} + function Handler(onFulfilled, onRejected, promise) { + this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; + this.onRejected = typeof onRejected === 'function' ? onRejected : null; + this.promise = promise; + } -/** - * Take a potentially misbehaving resolver function and make sure - * onFulfilled and onRejected are only called once. - * - * Makes no guarantees about asynchrony. - */ -function doResolve(fn, self) { - var done = false; - try { - fn(function (value) { - if (done) { return; } - done = true; - resolve(self, value); - }, function (reason) { + /** + * Take a potentially misbehaving resolver function and make sure + * onFulfilled and onRejected are only called once. + * + * Makes no guarantees about asynchrony. + */ + function doResolve(fn, self) { + var done = false; + try { + fn( + function (value) { + if (done) { return; } + done = true; + resolve(self, value); + }, + function (reason) { + if (done) { return; } + done = true; + reject(self, reason); + } + ); + } catch (ex) { if (done) { return; } done = true; - reject(self, reason); - }); - } catch (ex) { - if (done) { return; } - done = true; - reject(self, ex); + reject(self, ex); + } } -} - -Promise$1.prototype['catch'] = function (onRejected) { - return this.then(null, onRejected); -}; -Promise$1.prototype.then = function (onFulfilled, onRejected) { - var prom = new (this.constructor)(noop); - - handle(this, new Handler(onFulfilled, onRejected, prom)); - return prom; -}; + Promise$1.prototype['catch'] = function (onRejected) { + return this.then(null, onRejected); + }; -Promise$1.all = function (arr) { - var args = Array.prototype.slice.call(arr); + Promise$1.prototype.then = function (onFulfilled, onRejected) { + var prom = new this.constructor(noop); - return new Promise$1(function (resolve, reject) { - if (args.length === 0) { return resolve([]); } - var remaining = args.length; + handle(this, new Handler(onFulfilled, onRejected, prom)); + return prom; + }; - function res(i, val) { - try { - if (val && (typeof val === 'object' || typeof val === 'function')) { - var then = val.then; - if (typeof then === 'function') { - then.call(val, function (val) { - res(i, val); - }, reject); - return; + Promise$1.all = function (arr) { + var args = Array.prototype.slice.call(arr); + + return new Promise$1(function (resolve, reject) { + if (args.length === 0) { return resolve([]); } + var remaining = args.length; + + function res(i, val) { + try { + if (val && (typeof val === 'object' || typeof val === 'function')) { + var then = val.then; + if (typeof then === 'function') { + then.call( + val, + function (val) { + res(i, val); + }, + reject + ); + return; + } } + args[i] = val; + if (--remaining === 0) { + resolve(args); + } + } catch (ex) { + reject(ex); } - args[i] = val; - if (--remaining === 0) { - resolve(args); - } - } catch (ex) { - reject(ex); } - } - for (var i = 0; i < args.length; i++) { - res(i, args[i]); + for (var i = 0; i < args.length; i++) { + res(i, args[i]); + } + }); + }; + + Promise$1.resolve = function (value) { + if (value && typeof value === 'object' && value.constructor === Promise$1) { + return value; } - }); -}; -Promise$1.resolve = function (value) { - if (value && typeof value === 'object' && value.constructor === Promise$1) { - return value; - } + return new Promise$1(function (resolve) { + resolve(value); + }); + }; + + Promise$1.reject = function (value) { + return new Promise$1(function (resolve, reject) { + reject(value); + }); + }; - return new Promise$1(function (resolve) { - resolve(value); - }); -}; - -Promise$1.reject = function (value) { - return new Promise$1(function (resolve, reject) { - reject(value); - }); -}; - -Promise$1.race = function (values) { - return new Promise$1(function (resolve, reject) { - for (var i = 0, len = values.length; i < len; i++) { - values[i].then(resolve, reject); + Promise$1.race = function (values) { + return new Promise$1(function (resolve, reject) { + for (var i = 0, len = values.length; i < len; i++) { + values[i].then(resolve, reject); + } + }); + }; + + // Use polyfill for setImmediate for performance gains + Promise$1._immediateFn = + (typeof setImmediate === 'function' && + function (fn) { + setImmediate(fn); + }) || + function (fn) { + setTimeoutFunc(fn, 0); + }; + + Promise$1._unhandledRejectionFn = function _unhandledRejectionFn(err) { + if (typeof console !== 'undefined' && console) { + console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console } - }); -}; + }; + + /** + * Set the immediate function to execute callbacks + * @param fn {function} Function to execute + * @deprecated + */ + Promise$1._setImmediateFn = function _setImmediateFn(fn) { + Promise$1._immediateFn = fn; + }; -// Use polyfill for setImmediate for performance gains -Promise$1._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) || - function (fn) { - setTimeoutFunc(fn, 0); + /** + * Change the function to execute on unhandled rejection + * @param {function} fn Function to execute on unhandled rejection + * @deprecated + */ + Promise$1._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { + Promise$1._unhandledRejectionFn = fn; }; -Promise$1._unhandledRejectionFn = function _unhandledRejectionFn(err) { - if (typeof console !== 'undefined' && console) { - console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console - } -}; + var fakeDocument = { + createElement: function createElement() { }, + }; -/** - * Set the immediate function to execute callbacks - * @param fn {function} Function to execute - * @deprecated - */ -Promise$1._setImmediateFn = function _setImmediateFn(fn) { - Promise$1._immediateFn = fn; -}; + var fakeWindow = { + atob: function atob() { }, + open: function open() { }, + location: {}, + localStorage: { + setItem: function setItem() { }, + getItem: function getItem() { }, + removeItem: function removeItem() { }, + }, + sessionStorage: { + setItem: function setItem() { }, + getItem: function getItem() { }, + removeItem: function removeItem() { }, + }, + }; -/** - * Change the function to execute on unhandled rejection - * @param {function} fn Function to execute on unhandled rejection - * @deprecated - */ -Promise$1._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { - Promise$1._unhandledRejectionFn = fn; -}; + var $document = (typeof document !== undefined) + ? document + : fakeDocument; -function getCookieDomainUrl() { - try { - return window.location.hostname - } catch (e) {} + var $window = (typeof window !== undefined) + ? window + : fakeWindow; - return ''; -} + function getCookieDomainUrl() { + try { + return $window.location.hostname; + } catch (e) {} -function getRedirectUri(uri) { - try { - return (!isUndefined(uri)) - ? ("" + (window.location.origin) + uri) - : window.location.origin - } catch (e) {} + return ''; + } - return uri || null; -} + function getRedirectUri(uri) { + try { + return !isUndefined(uri) + ? ("" + ($window.location.origin) + uri) + : $window.location.origin; + } catch (e) {} -/** - * Default configuration - */ -var defaultOptions = { - baseUrl: null, - tokenName: 'token', - tokenPrefix: 'vueauth', - tokenHeader: 'Authorization', - tokenType: 'Bearer', - loginUrl: '/auth/login', - registerUrl: '/auth/register', - logoutUrl: null, - storageType: 'localStorage', - storageNamespace: 'vue-authenticate', - cookieStorage: { - domain: getCookieDomainUrl(), - path: '/', - secure: false - }, - requestDataKey: 'data', - responseDataKey: 'data', + return uri || null; + } /** - * Default request interceptor for Axios library - * @context {VueAuthenticate} + * Default configuration */ - bindRequestInterceptor: function ($auth) { - var tokenHeader = $auth.options.tokenHeader; - - $auth.$http.interceptors.request.use(function (config) { - if ($auth.isAuthenticated()) { - config.headers[tokenHeader] = [ - $auth.options.tokenType, $auth.getToken() - ].join(' '); - } else { - delete config.headers[tokenHeader]; - } - return config - }); - }, - - providers: { - facebook: { - name: 'facebook', - url: '/auth/facebook', - authorizationEndpoint: 'https://www.facebook.com/v2.5/dialog/oauth', - redirectUri: getRedirectUri('/'), - requiredUrlParams: ['display', 'scope'], - scope: ['email'], - scopeDelimiter: ',', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 580, height: 400 } + var defaultOptions = { + baseUrl: null, + tokenPath: 'access_token', + tokenName: 'token', + tokenPrefix: 'vueauth', + tokenHeader: 'Authorization', + tokenType: 'Bearer', + loginUrl: '/auth/login', + registerUrl: '/auth/register', + logoutUrl: null, + storageType: 'localStorage', + storageNamespace: 'vue-authenticate', + cookieStorage: { + domain: getCookieDomainUrl(), + path: '/', + secure: false, }, - - google: { - name: 'google', - url: '/auth/google', - authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth', - redirectUri: getRedirectUri(), - requiredUrlParams: ['scope'], - optionalUrlParams: ['display'], - scope: ['profile', 'email'], - scopePrefix: 'openid', - scopeDelimiter: ' ', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 452, height: 633 } + requestDataKey: 'data', + responseDataKey: 'data', + + /** + * Default request interceptor for Axios library + * @context {VueAuthenticate} + */ + bindRequestInterceptor: function ($auth) { + var tokenHeader = $auth.options.tokenHeader; + + $auth.$http.interceptors.request.use(function (config) { + if ($auth.isAuthenticated()) { + config.headers[tokenHeader] = [ + $auth.options.tokenType, + $auth.getToken() ].join(' '); + } else { + delete config.headers[tokenHeader]; + } + return config; + }); }, - github: { - name: 'github', - url: '/auth/github', - authorizationEndpoint: 'https://github.com/login/oauth/authorize', - redirectUri: getRedirectUri(), - optionalUrlParams: ['scope'], - scope: ['user:email'], - scopeDelimiter: ' ', - oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } + providers: { + facebook: { + name: 'facebook', + url: '/auth/facebook', + authorizationEndpoint: 'https://www.facebook.com/v10.0/dialog/oauth', + redirectUri: getRedirectUri('/'), + requiredUrlParams: ['display', 'scope'], + scope: ['email'], + scopeDelimiter: ',', + display: 'popup', + oauthType: '2.0', + popupOptions: { width: 580, height: 400 }, + }, + + google: { + name: 'google', + url: '/auth/google', + authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth', + redirectUri: getRedirectUri(), + requiredUrlParams: ['scope'], + optionalUrlParams: ['display'], + scope: ['profile', 'email'], + scopePrefix: 'openid', + scopeDelimiter: ' ', + display: 'popup', + oauthType: '2.0', + popupOptions: { width: 452, height: 633 }, + }, + + github: { + name: 'github', + url: '/auth/github', + authorizationEndpoint: 'https://github.com/login/oauth/authorize', + redirectUri: getRedirectUri(), + optionalUrlParams: ['scope'], + scope: ['user:email'], + scopeDelimiter: ' ', + oauthType: '2.0', + popupOptions: { width: 1020, height: 618 }, + }, + + instagram: { + name: 'instagram', + url: '/auth/instagram', + authorizationEndpoint: 'https://api.instagram.com/oauth/authorize', + redirectUri: getRedirectUri(), + requiredUrlParams: ['scope'], + scope: ['basic'], + scopeDelimiter: '+', + oauthType: '2.0', + popupOptions: { width: null, height: null }, + }, + + twitter: { + name: 'twitter', + url: '/auth/twitter', + authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate', + redirectUri: getRedirectUri(), + oauthType: '1.0', + popupOptions: { width: 495, height: 645 }, + }, + + bitbucket: { + name: 'bitbucket', + url: '/auth/bitbucket', + authorizationEndpoint: 'https://bitbucket.org/site/oauth2/authorize', + redirectUri: getRedirectUri('/'), + optionalUrlParams: ['scope'], + scope: ['email'], + scopeDelimiter: ' ', + oauthType: '2.0', + popupOptions: { width: 1020, height: 618 }, + }, + + linkedin: { + name: 'linkedin', + url: '/auth/linkedin', + authorizationEndpoint: 'https://www.linkedin.com/oauth/v2/authorization', + redirectUri: getRedirectUri(), + requiredUrlParams: ['state'], + scope: ['r_emailaddress'], + scopeDelimiter: ' ', + state: 'STATE', + oauthType: '2.0', + popupOptions: { width: 527, height: 582 }, + }, + + live: { + name: 'live', + url: '/auth/live', + authorizationEndpoint: 'https://login.live.com/oauth20_authorize.srf', + redirectUri: getRedirectUri(), + requiredUrlParams: ['display', 'scope'], + scope: ['wl.emails'], + scopeDelimiter: ' ', + display: 'popup', + oauthType: '2.0', + popupOptions: { width: 500, height: 560 }, + }, + + oauth1: { + name: null, + url: '/auth/oauth1', + authorizationEndpoint: null, + redirectUri: getRedirectUri(), + oauthType: '1.0', + popupOptions: null, + }, + + oauth2: { + name: null, + url: '/auth/oauth2', + clientId: null, + redirectUri: getRedirectUri(), + authorizationEndpoint: null, + defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], + requiredUrlParams: null, + optionalUrlParams: null, + scope: null, + scopePrefix: null, + scopeDelimiter: null, + state: null, + oauthType: '2.0', + popupOptions: null, + responseType: 'code', + responseParams: { + code: 'code', + clientId: 'clientId', + redirectUri: 'redirectUri', + }, + }, }, + }; - instagram: { - name: 'instagram', - url: '/auth/instagram', - authorizationEndpoint: 'https://api.instagram.com/oauth/authorize', - redirectUri: getRedirectUri(), - requiredUrlParams: ['scope'], - scope: ['basic'], - scopeDelimiter: '+', - oauthType: '2.0', - popupOptions: { width: null, height: null } - }, + var CookieStorage = function CookieStorage(defaultOptions) { + this._defaultOptions = objectExtend( + { + domain: getCookieDomainUrl(), + expires: null, + path: '/', + secure: false, + }, + defaultOptions + ); + }; - twitter: { - name: 'twitter', - url: '/auth/twitter', - authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate', - redirectUri: getRedirectUri(), - oauthType: '1.0', - popupOptions: { width: 495, height: 645 } - }, + CookieStorage.prototype.setItem = function setItem (key, value) { + var options = objectExtend({}, this._defaultOptions); + var cookie = formatCookie(key, value, options); + this._setCookie(cookie); + }; - bitbucket: { - name: 'bitbucket', - url: '/auth/bitbucket', - authorizationEndpoint: 'https://bitbucket.org/site/oauth2/authorize', - redirectUri: getRedirectUri('/'), - optionalUrlParams: ['scope'], - scope: ['email'], - scopeDelimiter: ' ', - oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } - }, + CookieStorage.prototype.getItem = function getItem (key) { + var cookies = parseCookies(this._getCookie()); + return cookies.hasOwnProperty(key) ? cookies[key] : null; + }; - linkedin: { - name: 'linkedin', - url: '/auth/linkedin', - authorizationEndpoint: 'https://www.linkedin.com/oauth/v2/authorization', - redirectUri: getRedirectUri(), - requiredUrlParams: ['state'], - scope: ['r_emailaddress'], - scopeDelimiter: ' ', - state: 'STATE', - oauthType: '2.0', - popupOptions: { width: 527, height: 582 } - }, + CookieStorage.prototype.removeItem = function removeItem (key) { + var value = ''; + var defaultOptions = objectExtend({}, this._defaultOptions); + var options = objectExtend(defaultOptions, { + expires: new Date(0), + }); + var cookie = formatCookie(key, value, options); + this._setCookie(cookie); + }; - live: { - name: 'live', - url: '/auth/live', - authorizationEndpoint: 'https://login.live.com/oauth20_authorize.srf', - redirectUri: getRedirectUri(), - requiredUrlParams: ['display', 'scope'], - scope: ['wl.emails'], - scopeDelimiter: ' ', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 500, height: 560 } - }, + CookieStorage.prototype._getCookie = function _getCookie () { + try { + return $document.cookie === 'undefined' ? '' : $document.cookie; + } catch (e) {} - oauth1: { - name: null, - url: '/auth/oauth1', - authorizationEndpoint: null, - redirectUri: getRedirectUri(), - oauthType: '1.0', - popupOptions: null - }, + return ''; + }; - oauth2: { - name: null, - url: '/auth/oauth2', - clientId: null, - redirectUri: getRedirectUri(), - authorizationEndpoint: null, - defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], - requiredUrlParams: null, - optionalUrlParams: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - state: null, - oauthType: '2.0', - popupOptions: null, - responseType: 'code', - responseParams: { - code: 'code', - clientId: 'clientId', - redirectUri: 'redirectUri' - } - } - } -}; - -var CookieStorage = function CookieStorage(defaultOptions) { - this._defaultOptions = objectExtend({ - domain: getCookieDomainUrl(), - expires: null, - path: '/', - secure: false - }, defaultOptions); -}; - -CookieStorage.prototype.setItem = function setItem (key, value) { - var options = objectExtend({}, this._defaultOptions); - var cookie = formatCookie(key, value, options); - this._setCookie(cookie); -}; - -CookieStorage.prototype.getItem = function getItem (key) { - var cookies = parseCookies(this._getCookie()); - return cookies.hasOwnProperty(key) ? cookies[key] : null; -}; - -CookieStorage.prototype.removeItem = function removeItem (key) { - var value = ''; - var defaultOptions = objectExtend({}, this._defaultOptions); - var options = objectExtend(defaultOptions, { - expires: new Date(0) - }); - var cookie = formatCookie(key, value, options); - this._setCookie(cookie); -}; - -CookieStorage.prototype._getCookie = function _getCookie () { - try { - return typeof document === 'undefined' - ? '' : typeof document.cookie === 'undefined' - ? '' : document.cookie; - } catch (e) {} - - return ''; -}; - -CookieStorage.prototype._setCookie = function _setCookie (cookie) { - try { - document.cookie = cookie; - } catch (e) {} -}; - -var LocalStorage = function LocalStorage(namespace) { - this.namespace = namespace || null; -}; - -LocalStorage.prototype.setItem = function setItem (key, value) { - window.localStorage.setItem(this._getStorageKey(key), value); -}; - -LocalStorage.prototype.getItem = function getItem (key) { - return window.localStorage.getItem(this._getStorageKey(key)) -}; - -LocalStorage.prototype.removeItem = function removeItem (key) { - window.localStorage.removeItem(this._getStorageKey(key)); -}; - -LocalStorage.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; + CookieStorage.prototype._setCookie = function _setCookie (cookie) { + try { + $document.cookie = cookie; + } catch (e) {} + }; -var MemoryStorage = function MemoryStorage(namespace) { - this.namespace = namespace || null; - this._storage = {}; -}; + var LocalStorage = function LocalStorage(namespace) { + this.namespace = namespace || null; + }; -MemoryStorage.prototype.setItem = function setItem (key, value) { - this._storage[this._getStorageKey(key)] = value; -}; + LocalStorage.prototype.setItem = function setItem (key, value) { + $window.localStorage.setItem(this._getStorageKey(key), value); + }; -MemoryStorage.prototype.getItem = function getItem (key) { - return this._storage[this._getStorageKey(key)] -}; + LocalStorage.prototype.getItem = function getItem (key) { + return $window.localStorage.getItem(this._getStorageKey(key)); + }; -MemoryStorage.prototype.removeItem = function removeItem (key) { - delete this._storage[this._getStorageKey(key)]; -}; + LocalStorage.prototype.removeItem = function removeItem (key) { + $window.localStorage.removeItem(this._getStorageKey(key)); + }; -MemoryStorage.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; + LocalStorage.prototype._getStorageKey = function _getStorageKey (key) { + if (this.namespace) { + return [this.namespace, key].join('.'); + } + return key; + }; -var LocalStorage$2 = function LocalStorage(namespace) { - this.namespace = namespace || null; -}; + var MemoryStorage = function MemoryStorage(namespace) { + this.namespace = namespace || null; + this._storage = {}; + }; -LocalStorage$2.prototype.setItem = function setItem (key, value) { - window.sessionStorage.setItem(this._getStorageKey(key), value); -}; + MemoryStorage.prototype.setItem = function setItem (key, value) { + this._storage[this._getStorageKey(key)] = value; + }; -LocalStorage$2.prototype.getItem = function getItem (key) { - return window.sessionStorage.getItem(this._getStorageKey(key)) -}; + MemoryStorage.prototype.getItem = function getItem (key) { + return this._storage[this._getStorageKey(key)]; + }; -LocalStorage$2.prototype.removeItem = function removeItem (key) { - window.sessionStorage.removeItem(this._getStorageKey(key)); -}; + MemoryStorage.prototype.removeItem = function removeItem (key) { + delete this._storage[this._getStorageKey(key)]; + }; -LocalStorage$2.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; + MemoryStorage.prototype._getStorageKey = function _getStorageKey (key) { + if (this.namespace) { + return [this.namespace, key].join('.'); + } + return key; + }; -function StorageFactory(options) { - switch (options.storageType) { - case 'localStorage': - try { - window.localStorage.setItem('testKey', 'test'); - window.localStorage.removeItem('testKey'); - return new LocalStorage(options.storageNamespace) - } catch(e) {} + var SessionStorage = function SessionStorage(namespace) { + this.namespace = namespace || null; + }; - case 'sessionStorage': - try { - window.sessionStorage.setItem('testKey', 'test'); - window.sessionStorage.removeItem('testKey'); - return new LocalStorage$2(options.storageNamespace) - } catch (e) {} - - case 'cookieStorage': - return new CookieStorage(options.cookieStorage); - - case 'memoryStorage': - default: - return new MemoryStorage(options.storageNamespace) - break; - } -} + SessionStorage.prototype.setItem = function setItem (key, value) { + $window.sessionStorage.setItem(this._getStorageKey(key), value); + }; -/** - * OAuth2 popup management class - * - * @author Sahat Yalkabov - * @copyright Class mostly taken from https://github.com/sahat/satellizer - * and adjusted to fit vue-authenticate library - */ -var OAuthPopup = function OAuthPopup(url, name, popupOptions) { - this.popup = null; - this.url = url; - this.name = name; - this.popupOptions = popupOptions; -}; - -OAuthPopup.prototype.open = function open (redirectUri, skipPooling) { - try { - this.popup = window.open(this.url, this.name, this._stringifyOptions()); - if (this.popup && this.popup.focus) { - this.popup.focus(); + SessionStorage.prototype.getItem = function getItem (key) { + return $window.sessionStorage.getItem(this._getStorageKey(key)); + }; + + SessionStorage.prototype.removeItem = function removeItem (key) { + $window.sessionStorage.removeItem(this._getStorageKey(key)); + }; + + SessionStorage.prototype._getStorageKey = function _getStorageKey (key) { + if (this.namespace) { + return [this.namespace, key].join('.'); } + return key; + }; - if (skipPooling) { - return Promise$1.resolve() - } else { - return this.pooling(redirectUri) + function StorageFactory(options) { + switch (options.storageType) { + case 'localStorage': + try { + $window.localStorage.setItem('testKey', 'test'); + $window.localStorage.removeItem('testKey'); + return new LocalStorage(options.storageNamespace); + } catch (e) {} + + case 'sessionStorage': + try { + $window.sessionStorage.setItem('testKey', 'test'); + $window.sessionStorage.removeItem('testKey'); + return new SessionStorage(options.storageNamespace); + } catch (e$1) {} + + case 'cookieStorage': + return new CookieStorage(options.cookieStorage); + + case 'memoryStorage': + default: + return new MemoryStorage(options.storageNamespace); } - } catch(e) { - return Promise$1.reject(new Error('OAuth popup error occurred')) } -}; -OAuthPopup.prototype.pooling = function pooling (redirectUri) { - var this$1 = this; + /** + * OAuth2 popup management class + * + * @author Sahat Yalkabov + * @copyright Class mostly taken from https://github.com/sahat/satellizer + * and adjusted to fit vue-authenticate library + */ + var OAuthPopup = function OAuthPopup(url, name, popupOptions) { + this.popup = null; + this.url = url; + this.name = name; + this.popupOptions = popupOptions; + }; - return new Promise$1(function (resolve, reject) { - var redirectUriParser = document.createElement('a'); - redirectUriParser.href = redirectUri; - var redirectUriPath = getFullUrlPath(redirectUriParser); + OAuthPopup.prototype.open = function open (redirectUri, skipPooling) { + try { + this.popup = $window.open(this.url, this.name, this._stringifyOptions()); + if (this.popup && this.popup.focus) { + this.popup.focus(); + } - var poolingInterval = setInterval(function () { - if (!this$1.popup || this$1.popup.closed || this$1.popup.closed === undefined) { - clearInterval(poolingInterval); - poolingInterval = null; - reject(new Error('Auth popup window closed')); + if (skipPooling) { + return Promise$1.resolve(); + } else { + return this.pooling(redirectUri); } + } catch (e) { + return Promise$1.reject(new Error('OAuth popup error occurred')); + } + }; - try { - var popupWindowPath = getFullUrlPath(this$1.popup.location); + OAuthPopup.prototype.pooling = function pooling (redirectUri) { + var this$1 = this; + + return new Promise$1(function (resolve, reject) { + var redirectUriParser = $document.createElement('a'); + redirectUriParser.href = redirectUri; + var redirectUriPath = getFullUrlPath(redirectUriParser); - if (popupWindowPath === redirectUriPath) { - if (this$1.popup.location.search || this$1.popup.location.hash) { - var query = parseQueryString(this$1.popup.location.search.substring(1).replace(/\/$/, '')); - var hash = parseQueryString(this$1.popup.location.hash.substring(1).replace(/[\/$]/, '')); - var params = objectExtend({}, query); - params = objectExtend(params, hash); + var poolingInterval = setInterval(function () { + if ( + !this$1.popup || + this$1.popup.closed || + this$1.popup.closed === undefined + ) { + clearInterval(poolingInterval); + poolingInterval = null; + reject(new Error('Auth popup window closed')); + } - if (params.error) { - reject(new Error(params.error)); + try { + var popupWindowPath = getFullUrlPath(this$1.popup.location); + + if (popupWindowPath === redirectUriPath) { + if (this$1.popup.location.search || this$1.popup.location.hash) { + var query = parseQueryString( + this$1.popup.location.search.substring(1).replace(/\/$/, '') + ); + var hash = parseQueryString( + this$1.popup.location.hash.substring(1).replace(/[\/$]/, '') + ); + var params = objectExtend({}, query); + params = objectExtend(params, hash); + + if (params.error) { + reject(new Error(params.error)); + } else { + resolve(params); + } } else { - resolve(params); + reject( + new Error( + 'OAuth redirect has occurred but no query or hash parameters were found.' + ) + ); } - } else { - reject(new Error('OAuth redirect has occurred but no query or hash parameters were found.')); - } - clearInterval(poolingInterval); - poolingInterval = null; - this$1.popup.close(); + clearInterval(poolingInterval); + poolingInterval = null; + this$1.popup.close(); + } + } catch (e) { + // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame. } - } catch(e) { - // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame. + }, 250); + }); + }; + + OAuthPopup.prototype._stringifyOptions = function _stringifyOptions () { + var options = []; + for (var optionKey in this.popupOptions) { + if (!isUndefined(this.popupOptions[optionKey])) { + options.push((optionKey + "=" + (this.popupOptions[optionKey]))); } - }, 250); - }) -}; + } + return options.join(','); + }; + + var defaultProviderConfig$1 = { + name: null, + url: null, + authorizationEndpoint: null, + scope: null, + scopePrefix: null, + scopeDelimiter: null, + redirectUri: null, + requiredUrlParams: null, + defaultUrlParams: null, + oauthType: '1.0', + popupOptions: {}, + }; -OAuthPopup.prototype._stringifyOptions = function _stringifyOptions () { - var this$1 = this; + var OAuth = function OAuth($http, storage, providerConfig, options) { + this.$http = $http; + this.storage = storage; + this.providerConfig = objectExtend({}, defaultProviderConfig$1); + this.providerConfig = objectExtend(this.providerConfig, providerConfig); + this.options = options; + }; - var options = []; - for (var optionKey in this$1.popupOptions) { - if (!isUndefined(this$1.popupOptions[optionKey])) { - options.push((optionKey + "=" + (this$1.popupOptions[optionKey]))); + /** + * Initialize OAuth1 process + * @param{Object} userData User data + * @return {Promise} + */ + OAuth.prototype.init = function init (userData) { + var this$1 = this; + + this.oauthPopup = new OAuthPopup( + 'about:blank', + this.providerConfig.name, + this.providerConfig.popupOptions + ); + + if (!$window['cordova']) { + this.oauthPopup.open(this.providerConfig.redirectUri, true); } - } - return options.join(',') -}; - -var defaultProviderConfig = { - name: null, - url: null, - authorizationEndpoint: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - redirectUri: null, - requiredUrlParams: null, - defaultUrlParams: null, - oauthType: '1.0', - popupOptions: {} -}; - -var OAuth = function OAuth($http, storage, providerConfig, options) { - this.$http = $http; - this.storage = storage; - this.providerConfig = objectExtend({}, defaultProviderConfig); - this.providerConfig = objectExtend(this.providerConfig, providerConfig); - this.options = options; -}; -/** - * Initialize OAuth1 process - * @param{Object} userData User data - * @return {Promise} - */ -OAuth.prototype.init = function init (userData) { - var this$1 = this; + return this.getRequestToken().then(function (response) { + return this$1.openPopup(response).then(function (popupResponse) { + return this$1.exchangeForToken(popupResponse, userData); + }); + }); + }; - this.oauthPopup = new OAuthPopup('about:blank', this.providerConfig.name, this.providerConfig.popupOptions); + /** + * Get OAuth1 request token + * @return {Promise} + */ + OAuth.prototype.getRequestToken = function getRequestToken () { + var requestOptions = {}; + requestOptions.method = 'POST'; + requestOptions[this.options.requestDataKey] = objectExtend( + {}, + this.providerConfig + ); + requestOptions.withCredentials = this.options.withCredentials; + if (this.options.baseUrl) { + requestOptions.url = joinUrl( + this.options.baseUrl, + this.providerConfig.url + ); + } else { + requestOptions.url = this.providerConfig.url; + } - if (window && !window['cordova']) { - this.oauthPopup.open(this.providerConfig.redirectUri, true); - } + return this.$http(requestOptions); + }; - return this.getRequestToken().then(function (response) { - return this$1.openPopup(response).then(function (popupResponse) { - return this$1.exchangeForToken(popupResponse, userData) - }) - }) -}; + /** + * Open OAuth1 popup + * @param{Object} response Response object containing request token + * @return {Promise} + */ + OAuth.prototype.openPopup = function openPopup (response) { + var url = [ + this.providerConfig.authorizationEndpoint, + this.buildQueryString(response[this.options.responseDataKey]) ].join('?'); + + this.oauthPopup.popup.location = url; + if ($window['cordova']) { + return this.oauthPopup.open(this.providerConfig.redirectUri); + } else { + return this.oauthPopup.pooling(this.providerConfig.redirectUri); + } + }; -/** - * Get OAuth1 request token - * @return {Promise} - */ -OAuth.prototype.getRequestToken = function getRequestToken () { - var requestOptions = {}; - requestOptions.method = 'POST'; - requestOptions[this.options.requestDataKey] = objectExtend({}, this.providerConfig); - requestOptions.withCredentials = this.options.withCredentials; - if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - requestOptions.url = this.providerConfig.url; - } + /** + * Exchange token and token verifier for access token + * @param{Object} oauth OAuth data containing token and token verifier + * @param{Object} userData User data + * @return {Promise} + */ + OAuth.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { + var payload = objectExtend({}, userData); + payload = objectExtend(payload, oauth); + var requestOptions = {}; + requestOptions.method = 'POST'; + requestOptions[this.options.requestDataKey] = payload; + requestOptions.withCredentials = this.options.withCredentials; + if (this.options.baseUrl) { + requestOptions.url = joinUrl( + this.options.baseUrl, + this.providerConfig.url + ); + } else { + requestOptions.url = this.providerConfig.url; + } + return this.$http(requestOptions); + }; - return this.$http(requestOptions) -}; + OAuth.prototype.buildQueryString = function buildQueryString (params) { + var parsedParams = []; + for (var key in params) { + var value = params[key]; + parsedParams.push( + encodeURIComponent(key) + '=' + encodeURIComponent(value) + ); + } + return parsedParams.join('&'); + }; -/** - * Open OAuth1 popup - * @param{Object} response Response object containing request token - * @return {Promise} - */ -OAuth.prototype.openPopup = function openPopup (response) { - var url = [this.providerConfig.authorizationEndpoint, this.buildQueryString(response[this.options.responseDataKey])].join('?'); - - this.oauthPopup.popup.location = url; - if (window && window['cordova']) { - return this.oauthPopup.open(this.providerConfig.redirectUri) - } else { - return this.oauthPopup.pooling(this.providerConfig.redirectUri) - } -}; + /** + * Default provider configuration + * @type {Object} + */ + var defaultProviderConfig = { + name: null, + url: null, + clientId: null, + authorizationEndpoint: null, + redirectUri: null, + scope: null, + scopePrefix: null, + scopeDelimiter: null, + state: null, + requiredUrlParams: null, + defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], + responseType: 'code', + responseParams: { + code: 'code', + clientId: 'clientId', + redirectUri: 'redirectUri', + }, + oauthType: '2.0', + popupOptions: {}, + }; -/** - * Exchange token and token verifier for access token - * @param{Object} oauth OAuth data containing token and token verifier - * @param{Object} userData User data - * @return {Promise} - */ -OAuth.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { - var payload = objectExtend({}, userData); - payload = objectExtend(payload, oauth); - var requestOptions = {}; - requestOptions.method = 'POST'; - requestOptions[this.options.requestDataKey] = payload; - requestOptions.withCredentials = this.options.withCredentials; - if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - requestOptions.url = this.providerConfig.url; - } - return this.$http(requestOptions) -}; - -OAuth.prototype.buildQueryString = function buildQueryString (params) { - var parsedParams = []; - for (var key in params) { - var value = params[key]; - parsedParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); - } - return parsedParams.join('&'); -}; + var OAuth2 = function OAuth2($http, storage, providerConfig, options) { + this.$http = $http; + this.storage = storage; + this.providerConfig = objectExtend({}, defaultProviderConfig); + this.providerConfig = objectExtend(this.providerConfig, providerConfig); + this.options = options; + }; -/** - * Default provider configuration - * @type {Object} - */ -var defaultProviderConfig$1 = { - name: null, - url: null, - clientId: null, - authorizationEndpoint: null, - redirectUri: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - state: null, - requiredUrlParams: null, - defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], - responseType: 'code', - responseParams: { - code: 'code', - clientId: 'clientId', - redirectUri: 'redirectUri' - }, - oauthType: '2.0', - popupOptions: {} -}; - -var OAuth2 = function OAuth2($http, storage, providerConfig, options) { - this.$http = $http; - this.storage = storage; - this.providerConfig = objectExtend({}, defaultProviderConfig$1); - this.providerConfig = objectExtend(this.providerConfig, providerConfig); - this.options = options; -}; - -OAuth2.prototype.init = function init (userData) { - var this$1 = this; - - var stateName = this.providerConfig.name + '_state'; - if (isFunction(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state()); - } else if (isString(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state); - } + OAuth2.prototype.init = function init (userData) { + var this$1 = this; - var url = [this.providerConfig.authorizationEndpoint, this._stringifyRequestParams()].join('?'); + var stateName = this.providerConfig.name + '_state'; + if (isFunction(this.providerConfig.state)) { + this.storage.setItem(stateName, this.providerConfig.state()); + } else if (isString(this.providerConfig.state)) { + this.storage.setItem(stateName, this.providerConfig.state); + } - this.oauthPopup = new OAuthPopup(url, this.providerConfig.name, this.providerConfig.popupOptions); - - return new Promise(function (resolve, reject) { - this$1.oauthPopup.open(this$1.providerConfig.redirectUri).then(function (response) { - if (this$1.providerConfig.responseType === 'token' || !this$1.providerConfig.url) { - return resolve(response) - } + var url = [ + this.providerConfig.authorizationEndpoint, + this._stringifyRequestParams() ].join('?'); + + this.oauthPopup = new OAuthPopup( + url, + this.providerConfig.name, + this.providerConfig.popupOptions + ); + + return new Promise(function (resolve, reject) { + this$1.oauthPopup + .open(this$1.providerConfig.redirectUri) + .then(function (response) { + if ( + this$1.providerConfig.responseType === 'token' || + !this$1.providerConfig.url + ) { + return resolve(response); + } - if (response.state && response.state !== this$1.storage.getItem(stateName)) { - return reject(new Error('State parameter value does not match original OAuth request state value')) - } + if ( + response.state && + response.state !== this$1.storage.getItem(stateName) + ) { + return reject( + new Error( + 'State parameter value does not match original OAuth request state value' + ) + ); + } - resolve(this$1.exchangeForToken(response, userData)); - }).catch(function (err) { - reject(err); + resolve(this$1.exchangeForToken(response, userData)); + }) + .catch(function (err) { + reject(err); + }); }); - }) -}; + }; -/** - * Exchange temporary oauth data for access token - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param{[type]} oauth [description] - * @param{[type]} userData [description] - * @return {[type]} [description] - */ -OAuth2.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { - var this$1 = this; - - var payload = objectExtend({}, userData); - - for (var key in defaultProviderConfig$1.responseParams) { - var value = defaultProviderConfig$1[key]; - - switch(key) { - case 'code': - payload[key] = oauth.code; - break - case 'clientId': - payload[key] = this$1.providerConfig.clientId; - break - case 'redirectUri': - payload[key] = this$1.providerConfig.redirectUri; - break - default: - payload[key] = oauth[key]; + /** + * Exchange temporary oauth data for access token + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @param{[type]} oauth [description] + * @param{[type]} userData [description] + * @return {[type]} [description] + */ + OAuth2.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { + var payload = objectExtend({}, userData); + + for (var key in this.providerConfig.responseParams) { + this.providerConfig.responseParams[key]; + + switch (key) { + case 'code': + payload[key] = oauth.code; + break; + case 'clientId': + payload[key] = this.providerConfig.clientId; + break; + case 'redirectUri': + payload[key] = this.providerConfig.redirectUri; + break; + default: + payload[key] = oauth[key]; + } } - } - if (oauth.state) { - payload.state = oauth.state; - } + if (oauth.state) { + payload.state = oauth.state; + } - var exchangeTokenUrl; - if (this.options.baseUrl) { - exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - exchangeTokenUrl = this.providerConfig.url; - } + var exchangeTokenUrl; + if (this.options.baseUrl) { + exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url); + } else { + exchangeTokenUrl = this.providerConfig.url; + } - return this.$http.post(exchangeTokenUrl, payload, { - withCredentials: this.options.withCredentials - }) -}; + return this.$http.post(exchangeTokenUrl, payload, { + withCredentials: this.options.withCredentials, + }); + }; -/** - * Stringify oauth params - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @return {String} - */ -OAuth2.prototype._stringifyRequestParams = function _stringifyRequestParams () { - var this$1 = this; + /** + * Stringify oauth params + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * + * @return {String} + */ + OAuth2.prototype._stringifyRequestParams = function _stringifyRequestParams () { + var this$1 = this; + + var keyValuePairs = []; + var paramCategories = [ + 'defaultUrlParams', + 'requiredUrlParams', + 'optionalUrlParams' ]; + + paramCategories.forEach(function (categoryName) { + if (!this$1.providerConfig[categoryName]) { return; } + if (!Array.isArray(this$1.providerConfig[categoryName])) { return; } + + this$1.providerConfig[categoryName].forEach(function (paramName) { + var camelCaseParamName = camelCase(paramName); + var paramValue = isFunction(this$1.providerConfig[paramName]) + ? this$1.providerConfig[paramName]() + : this$1.providerConfig[camelCaseParamName]; + + if (paramName === 'redirect_uri' && !paramValue) { return; } + + if (paramName === 'state') { + var stateName = this$1.providerConfig.name + '_state'; + paramValue = encodeURIComponent(this$1.storage.getItem(stateName)); + } + if (paramName === 'scope' && Array.isArray(paramValue)) { + paramValue = paramValue.join(this$1.providerConfig.scopeDelimiter); + if (this$1.providerConfig.scopePrefix) { + paramValue = [this$1.providerConfig.scopePrefix, paramValue].join( + this$1.providerConfig.scopeDelimiter + ); + } + } - var keyValuePairs = []; - var paramCategories = ['defaultUrlParams', 'requiredUrlParams', 'optionalUrlParams']; + keyValuePairs.push([paramName, paramValue]); + }); + }); - paramCategories.forEach(function (categoryName) { - if (!this$1.providerConfig[categoryName]) { return } - if (!Array.isArray(this$1.providerConfig[categoryName])) { return } + return keyValuePairs + .map(function (param) { + return param.join('='); + }) + .join('&'); + }; - this$1.providerConfig[categoryName].forEach(function (paramName) { - var camelCaseParamName = camelCase(paramName); - var paramValue = isFunction(this$1.providerConfig[paramName]) ? this$1.providerConfig[paramName]() : this$1.providerConfig[camelCaseParamName]; + var VueAuthenticate = function VueAuthenticate($http, overrideOptions) { + var options = objectExtend({}, defaultOptions); + options = objectExtend(options, overrideOptions); + var storage = StorageFactory(options); + + Object.defineProperties(this, { + $http: { + get: function get() { + return $http; + }, + }, + + options: { + get: function get() { + return options; + }, + }, + + storage: { + get: function get() { + return storage; + }, + }, + + tokenName: { + get: function get() { + if (this.options.tokenPrefix) { + return [this.options.tokenPrefix, this.options.tokenName].join('_'); + } else { + return this.options.tokenName; + } + }, + }, + }); - if (paramName === 'redirect_uri' && !paramValue) { return } + // Setup request interceptors + if ( + this.options.bindRequestInterceptor && + isFunction(this.options.bindRequestInterceptor) + ) { + this.options.bindRequestInterceptor.call(this, this); + } else { + throw new Error('Request interceptor must be functions'); + } + }; - if (paramName === 'state') { - var stateName = this$1.providerConfig.name + '_state'; - paramValue = encodeURIComponent(this$1.storage.getItem(stateName)); - } - if (paramName === 'scope' && Array.isArray(paramValue)) { - paramValue = paramValue.join(this$1.providerConfig.scopeDelimiter); - if (this$1.providerConfig.scopePrefix) { - paramValue = [this$1.providerConfig.scopePrefix, paramValue].join(this$1.providerConfig.scopeDelimiter); + /** + * Check if user is authenticated + * @author Sahat Yalkabov + * @copyright Method taken from https://github.com/sahat/satellizer + * @return {Boolean} + */ + VueAuthenticate.prototype.isAuthenticated = function isAuthenticated () { + var token = this.storage.getItem(this.tokenName); + + if (token) { + // Token is present + if (token.split('.').length === 3) { + // Token with a valid JWT format XXX.YYY.ZZZ + try { + // Could be a valid JWT or an access token with the same format + var base64Url = token.split('.')[1]; + var base64 = base64Url.replace('-', '+').replace('_', '/'); + var exp = JSON.parse($window.atob(base64)).exp; + if (typeof exp === 'number') { + // JWT with an optonal expiration claims + return Math.round(new Date().getTime() / 1000) < exp; + } + } catch (e) { + return true; // Pass: Non-JWT token that looks like JWT } } + return true; // Pass: All other tokens + } + return false; + }; - keyValuePairs.push([paramName, paramValue]); - }); - }); - - return keyValuePairs.map(function (param) { - return param.join('=') - }).join('&') -}; - -var VueAuthenticate = function VueAuthenticate($http, overrideOptions) { - var options = objectExtend({}, defaultOptions); - options = objectExtend(options, overrideOptions); - var storage = StorageFactory(options); - - Object.defineProperties(this, { - $http: { - get: function get() { - return $http - } - }, + /** + * Get token if user is authenticated + * @return {String} Authentication token + */ + VueAuthenticate.prototype.getToken = function getToken () { + return this.storage.getItem(this.tokenName); + }; - options: { - get: function get() { - return options - } - }, + /** + * Set new authentication token + * @param {String|Object} token + */ + VueAuthenticate.prototype.setToken = function setToken (response, tokenPath) { + if (response[this.options.responseDataKey]) { + response = response[this.options.responseDataKey]; + } - storage: { - get: function get() { - return storage - } - }, + var responseTokenPath = tokenPath || this.options.tokenPath; + var token = getObjectProperty(response, responseTokenPath); - tokenName: { - get: function get() { - if (this.options.tokenPrefix) { - return [this.options.tokenPrefix, this.options.tokenName].join('_') - } else { - return this.options.tokenName - } - } + if (token) { + this.storage.setItem(this.tokenName, token); } - }); + }; - // Setup request interceptors - if (this.options.bindRequestInterceptor && isFunction(this.options.bindRequestInterceptor)) { - this.options.bindRequestInterceptor.call(this, this); - } else { - throw new Error('Request interceptor must be functions') - } -}; + VueAuthenticate.prototype.getPayload = function getPayload () { + var token = this.storage.getItem(this.tokenName); -/** - * Check if user is authenticated - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * @return {Boolean} - */ -VueAuthenticate.prototype.isAuthenticated = function isAuthenticated () { - var token = this.storage.getItem(this.tokenName); - - if (token) {// Token is present - if (token.split('.').length === 3) {// Token with a valid JWT format XXX.YYY.ZZZ - try { // Could be a valid JWT or an access token with the same format + if (token && token.split('.').length === 3) { + try { var base64Url = token.split('.')[1]; var base64 = base64Url.replace('-', '+').replace('_', '/'); - var exp = JSON.parse(window.atob(base64)).exp; - if (typeof exp === 'number') {// JWT with an optonal expiration claims - return Math.round(new Date().getTime() / 1000) < exp; - } - } catch (e) { - return true;// Pass: Non-JWT token that looks like JWT - } + return JSON.parse(decodeBase64(base64)); + } catch (e) {} } - return true;// Pass: All other tokens - } - return false -}; - -/** - * Get token if user is authenticated - * @return {String} Authentication token - */ -VueAuthenticate.prototype.getToken = function getToken () { - return this.storage.getItem(this.tokenName) -}; + }; -/** - * Set new authentication token - * @param {String|Object} token - */ -VueAuthenticate.prototype.setToken = function setToken (response) { - if (response[this.options.responseDataKey]) { - response = response[this.options.responseDataKey]; - } - - var token; - if (response.access_token) { - if (isObject(response.access_token) && isObject(response.access_token[this.options.responseDataKey])) { - response = response.access_token; - } else if (isString(response.access_token)) { - token = response.access_token; - } - } + /** + * Login user using email and password + * @param{Object} user User data + * @param{Object} requestOptions Request options + * @return {Promise} Request promise + */ + VueAuthenticate.prototype.login = function login (user, requestOptions) { + var this$1 = this; + + requestOptions = requestOptions || {}; + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.loginUrl); + requestOptions[this.options.requestDataKey] = + user || requestOptions[this.options.requestDataKey]; + requestOptions.method = requestOptions.method || 'POST'; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; - if (!token && response) { - token = response[this.options.tokenName]; - } + return this.$http(requestOptions).then(function (response) { + this$1.setToken(response); + return response; + }); + }; - if (token) { - this.storage.setItem(this.tokenName, token); - } -}; + /** + * Register new user + * @param{Object} user User data + * @param{Object} requestOptions Request options + * @return {Promise} Request promise + */ + VueAuthenticate.prototype.register = function register (user, requestOptions) { + var this$1 = this; + + requestOptions = requestOptions || {}; + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.registerUrl); + requestOptions[this.options.requestDataKey] = + user || requestOptions[this.options.requestDataKey]; + requestOptions.method = requestOptions.method || 'POST'; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; -VueAuthenticate.prototype.getPayload = function getPayload () { - var token = this.storage.getItem(this.tokenName); + return this.$http(requestOptions).then(function (response) { + this$1.setToken(response); + return response; + }); + }; - if (token && token.split('.').length === 3) { - try { - var base64Url = token.split('.')[1]; - var base64 = base64Url.replace('-', '+').replace('_', '/'); - return JSON.parse(decodeBase64(base64)); - } catch (e) {} - } -}; - -/** - * Login user using email and password - * @param{Object} user User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.login = function login (user, requestOptions) { - var this$1 = this; + /** + * Logout current user + * @param{Object} requestOptionsLogout request options object + * @return {Promise} Request promise + */ + VueAuthenticate.prototype.logout = function logout (requestOptions) { + var this$1 = this; - requestOptions = requestOptions || {}; - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.loginUrl); - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey]; - requestOptions.method = requestOptions.method || 'POST'; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; + if (!this.isAuthenticated()) { + return Promise$1.reject( + new Error('There is no currently authenticated user') + ); + } - return this.$http(requestOptions).then(function (response) { - this$1.setToken(response); - return response - }) -}; + requestOptions = requestOptions || {}; + + if (requestOptions.url || this.options.logoutUrl) { + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.logoutUrl); + requestOptions.method = requestOptions.method || 'POST'; + requestOptions[this.options.requestDataKey] = + requestOptions[this.options.requestDataKey] || undefined; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; + + return this.$http(requestOptions).then(function (response) { + this$1.storage.removeItem(this$1.tokenName); + return response; + }); + } else { + this.storage.removeItem(this.tokenName); + return Promise$1.resolve(); + } + }; -/** - * Register new user - * @param{Object} user User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.register = function register (user, requestOptions) { - var this$1 = this; + /** + * Authenticate user using authentication provider + * + * @param{String} provider Provider name + * @param{Object} userData User data + * @return {Promise} Request promise + */ + VueAuthenticate.prototype.authenticate = function authenticate (provider, userData) { + var this$1 = this; - requestOptions = requestOptions || {}; - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.registerUrl); - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey]; - requestOptions.method = requestOptions.method || 'POST'; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; + return new Promise$1(function (resolve, reject) { + var providerConfig = this$1.options.providers[provider]; + if (!providerConfig) { + return reject(new Error('Unknown provider')); + } - return this.$http(requestOptions).then(function (response) { - this$1.setToken(response); - return response - }) -}; + var providerInstance; + switch (providerConfig.oauthType) { + case '1.0': + providerInstance = new OAuth( + this$1.$http, + this$1.storage, + providerConfig, + this$1.options + ); + break; + case '2.0': + providerInstance = new OAuth2( + this$1.$http, + this$1.storage, + providerConfig, + this$1.options + ); + break; + default: + return reject(new Error('Invalid OAuth type')); + } -/** - * Logout current user - * @param{Object} requestOptionsLogout request options object - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.logout = function logout (requestOptions) { - var this$1 = this; + return providerInstance + .init(userData) + .then(function (response) { + this$1.setToken(response, providerConfig.tokenPath); - if (!this.isAuthenticated()) { - return Promise$1.reject(new Error('There is no currently authenticated user')) - } + if (this$1.isAuthenticated()) { + return resolve(response); + } else { + return reject(new Error('Authentication failed')); + } + }) + .catch(function (err) { return reject(err); }); + }); + }; - requestOptions = requestOptions || {}; + /** + * Link user using authentication provider without login + * + * @param{String} provider Provider name + * @param{Object} userData User data + * @return {Promise} Request promise + */ + VueAuthenticate.prototype.link = function link (provider, userData) { + var this$1 = this; - if (requestOptions.url) { - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.logoutUrl); - requestOptions.method = requestOptions.method || 'POST'; - requestOptions[this.options.requestDataKey] = requestOptions[this.options.requestDataKey] || undefined; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; + return new Promise$1(function (resolve, reject) { + var providerConfig = this$1.options.providers[provider]; + if (!providerConfig) { + return reject(new Error('Unknown provider')); + } - return this.$http(requestOptions).then(function (response) { - this$1.storage.removeItem(this$1.tokenName); - }) - } else { - this.storage.removeItem(this.tokenName); - return Promise$1.resolve(); - } -}; + var providerInstance; + switch (providerConfig.oauthType) { + case '1.0': + providerInstance = new OAuth( + this$1.$http, + this$1.storage, + providerConfig, + this$1.options + ); + break; + case '2.0': + providerInstance = new OAuth2( + this$1.$http, + this$1.storage, + providerConfig, + this$1.options + ); + break; + default: + return reject(new Error('Invalid OAuth type')); + } -/** - * Authenticate user using authentication provider - * - * @param{String} provider Provider name - * @param{Object} userData User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.authenticate = function authenticate (provider, userData, requestOptions) { - var this$1 = this; + return providerInstance + .init(userData) + .then(function (response) { + if (response[this$1.options.responseDataKey]) { + response = response[this$1.options.responseDataKey]; + } - return new Promise$1(function (resolve, reject) { - var providerConfig = this$1.options.providers[provider]; - if (!providerConfig) { - return reject(new Error('Unknown provider')) - } + resolve(response); + }) + .catch(reject); + }); + }; - var providerInstance; - switch (providerConfig.oauthType) { - case '1.0': - providerInstance = new OAuth(this$1.$http, this$1.storage, providerConfig, this$1.options); - break - case '2.0': - providerInstance = new OAuth2(this$1.$http, this$1.storage, providerConfig, this$1.options); - break - default: - return reject(new Error('Invalid OAuth type')) - break + /** + * VueAuthenticate plugin + * @param {Object} Vue + * @param {Object} options + */ + function plugin(Vue, options) { + if (plugin.installed) { + return; } - return providerInstance.init(userData).then(function (response) { - this$1.setToken(response); + plugin.installed = true; - if (this$1.isAuthenticated()) { - return resolve(response) - } else { - return reject(new Error('Authentication failed')) - } - }).catch(function (err) { return reject(err); }) - }) -}; + var vueAuthInstance = null; + Object.defineProperties(Vue.prototype, { + $auth: { + get: function get() { + if (!vueAuthInstance) { + // Request handler library not found, throw error + if (!this.$http) { + throw new Error('Request handler instance not found'); + } -/** - * VueAuthenticate plugin - * @param {Object} Vue - * @param {Object} options - */ -function plugin(Vue, options) { - if (plugin.installed) { - return - } - plugin.installed = true; - - var vueAuthInstance = null; - Object.defineProperties(Vue.prototype, { - $auth: { - get: function get() { - if (!vueAuthInstance) { - // Request handler library not found, throw error - if (!this.$http) { - throw new Error('Request handler instance not found') + vueAuthInstance = new VueAuthenticate(this.$http, options); } + return vueAuthInstance; + }, + }, + }); + } - vueAuthInstance = new VueAuthenticate(this.$http, options); - } - return vueAuthInstance - } - } - }); -} - -/** - * External factory helper for ES5 and CommonJS - * @param {Object} $http Instance of request handling library - * @param {Object} options Configuration object - * @return {VueAuthenticate} VueAuthenticate instance - */ -plugin.factory = function ($http, options) { - return new VueAuthenticate($http, options) -}; + /** + * External factory helper for ES5 and CommonJS + * @param {Object} $http Instance of request handling library + * @param {Object} options Configuration object + * @return {VueAuthenticate} VueAuthenticate instance + */ + plugin.factory = function ($http, options) { + return new VueAuthenticate($http, options); + }; -return plugin; + return plugin; }))); diff --git a/dist/vue-authenticate.min.js b/dist/vue-authenticate.min.js index ef6d989..419d08f 100644 --- a/dist/vue-authenticate.min.js +++ b/dist/vue-authenticate.min.js @@ -1,7 +1,8 @@ -/*! - * vue-authenticate v1.3.5-beta.1 +/** + * vue-authenticate v1.5.0 * https://github.com/dgrubelic/vue-authenticate * Released under the MIT License. + * */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.VueAuthenticate=e()}(this,function(){"use strict";function t(t){return t.replace(/([\:\-\_]+(.))/g,function(t,e,o,n){return n?o.toUpperCase():o})}function e(t){return void 0===t}function o(t){return null!==t&&"object"==typeof t}function n(t){return"string"==typeof t}function r(t){return"function"==typeof t}function i(t,e){return null==t||null==e?t:(Object.keys(e).forEach(function(o){"[object Object]"==Object.prototype.toString.call(e[o])?"[object Object]"!=Object.prototype.toString.call(t[o])?t[o]=e[o]:t[o]=i(t[o],e[o]):t[o]=e[o]}),t)}function a(t,e){if(/^(?:[a-z]+:)?\/\//i.test(e))return e;var o=[t,e].join("/");return function(t){return t.replace(/[\/]+/g,"/").replace(/\/\?/g,"?").replace(/\/\#/g,"#").replace(/\:\//g,"://")}(o)}function s(t){var e="https:"===t.protocol;return t.protocol+"//"+t.hostname+":"+(t.port||(e?"443":"80"))+(/^\//.test(t.pathname)?t.pathname:"/"+t.pathname)}function u(t){var e,o,n={};return(t||"").split("&").forEach(function(t){t&&(o=t.split("="),e=decodeURIComponent(o[0]),n[e]=!o[1]||decodeURIComponent(o[1]))}),n}function p(t){var e;if("undefined"!=typeof module&&module.exports)try{e=require("buffer").Buffer}catch(t){}var o=String.fromCharCode,n=new RegExp(["[À-ß][€-¿]","[à-ï][€-¿]{2}","[ð-÷][€-¿]{3}"].join("|"),"g"),r=function(t){switch(t.length){case 4:var e=(7&t.charCodeAt(0))<<18|(63&t.charCodeAt(1))<<12|(63&t.charCodeAt(2))<<6|63&t.charCodeAt(3),n=e-65536;return o(55296+(n>>>10))+o(56320+(1023&n));case 3:return o((15&t.charCodeAt(0))<<12|(63&t.charCodeAt(1))<<6|63&t.charCodeAt(2));default:return o((31&t.charCodeAt(0))<<6|63&t.charCodeAt(1))}},i=function(t){return t.replace(n,r)};return(e?function(t){return(t.constructor===e.constructor?t:new e(t,"base64")).toString()}:function(t){return i(atob(t))})(String(t).replace(/[-_]/g,function(t){return"-"===t?"+":"/"}).replace(/[^A-Za-z0-9\+\/]/g,""))}function c(t){if(0===t.length)return{};var e={},o=new RegExp("\\s*;\\s*");return t.split(o).forEach(function(t){var o=t.split("="),n=o[0],r=o[1],i=decodeURIComponent(n),a=decodeURIComponent(r);e[i]=a}),e}function h(t){var e=t.path,o=t.domain,n=t.expires,r=t.secure;return[void 0===e||null===e?"":";path="+e,void 0===o||null===o?"":";domain="+o,void 0===n||null===n?"":";expires="+n.toUTCString(),void 0===r||null===r||!1===r?"":";secure"].join("")}function l(t,e,o){return[encodeURIComponent(t),"=",encodeURIComponent(e),h(o)].join("")}function d(){}function f(t,e){return function(){t.apply(e,arguments)}}function g(t){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],_(t,this)}function m(t,e){for(;3===t._state;)t=t._value;if(0===t._state)return void t._deferreds.push(e);t._handled=!0,g._immediateFn(function(){var o=1===t._state?e.onFulfilled:e.onRejected;if(null===o)return void(1===t._state?v:y)(e.promise,t._value);var n;try{n=o(t._value)}catch(t){return void y(e.promise,t)}v(e.promise,n)})}function v(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var o=e.then;if(e instanceof g)return t._state=3,t._value=e,void w(t);if("function"==typeof o)return void _(f(o,e),t)}t._state=1,t._value=e,w(t)}catch(e){y(t,e)}}function y(t,e){t._state=2,t._value=e,w(t)}function w(t){2===t._state&&0===t._deferreds.length&&g._immediateFn(function(){t._handled||g._unhandledRejectionFn(t._value)});for(var e=0,o=t._deferreds.length;e>>10))+r(56320+(1023&e));case 3:return r((15&t.charCodeAt(0))<<12|(63&t.charCodeAt(1))<<6|63&t.charCodeAt(2));default:return r((31&t.charCodeAt(0))<<6|63&t.charCodeAt(1))}}var r=String.fromCharCode,n=new RegExp(["[À-ß][€-¿]","[à-ï][€-¿]{2}","[ð-÷][€-¿]{3}"].join("|"),"g");return(e?function(t){return(t.constructor===e.constructor?t:new e(t,"base64")).toString()}:function(t){return atob(t).replace(n,o)})(String(t).replace(/[-_]/g,function(t){return"-"===t?"+":"/"}).replace(/[^A-Za-z0-9\+\/]/g,""))}function i(t,e,o){return[encodeURIComponent(t),"=",encodeURIComponent(e),(t=(r=o).path,e=r.domain,o=r.expires,r=r.secure,[null==t?"":";path="+t,null==e?"":";domain="+e,null==o?"":";expires="+o.toUTCString(),null==r||!1===r?"":";secure"].join(""))].join("");var r}"function"!=typeof Object.assign&&(Object.assign=function(t,e){var o=arguments;if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var r=Object(t),n=1;n - - - - vue-authenticate - - - -
- -
- - - - - - - - - diff --git a/example/index.js b/example/index.js deleted file mode 100644 index cd8c608..0000000 --- a/example/index.js +++ /dev/null @@ -1,152 +0,0 @@ -axios.defaults.baseURL = 'http://localhost:4000/'; - -Vue.use(VueRouter) -Vue.use(VueAuthenticate, { - tokenName: 'access_token', - baseUrl: 'http://localhost:4000/', - storageType: 'cookieStorage', - providers: { - // Define OAuth providers config - } -}) - -var router = new VueRouter({ - mode: 'history', - routes: [ - { - path: '/', - name: 'index', - component: { - data: function () { - return { - access_token: null, - response: null - } - }, - template: ` -
-
- You are successfully authenticated -
{{$auth.getToken()}}
-
- - - - - -
- - - - - - -
- - - - - - -
{{JSON.stringify(response, null, 2)}}
-
- `, - methods: { - - authLogin: function () { - var this_ = this; - let user = { - email: 'john.doe@domain.com', - password: 'pass123456' - }; - - if (this.$auth.isAuthenticated()) { - this.$auth.logout() - } - - this.$auth.login(user).then(function (response) { - this_.response = response - }) - }, - - authRegister: function () { - var this_ = this; - let user = { - name: 'John Doe', - email: 'john.doe@domain.com', - password: 'pass123456' - }; - - if (this.$auth.isAuthenticated()) { - this.$auth.logout() - } - - this.$auth.register(user).then(function (response) { - this_.response = response - }) - }, - - authLogout: function() { - this.$auth.logout().then(() => { - if (!this.$auth.isAuthenticated()) { - this.response = null - } - }) - }, - - auth: function(provider) { - if (this.$auth.isAuthenticated()) { - this.$auth.logout() - } - - this.response = null - - var this_ = this; - this.$auth.authenticate(provider).then(function (authResponse) { - if (provider === 'github') { - this_.$http.get('https://api.github.com/user').then(function (response) { - this_.response = response - }) - } else if (provider === 'facebook') { - this_.$http.get('https://graph.facebook.com/v2.5/me', { - params: { access_token: this_.$auth.getToken() } - }).then(function (response) { - this_.response = response - }) - } else if (provider === 'google') { - this_.$http.get('https://www.googleapis.com/plus/v1/people/me/openIdConnect').then(function (response) { - this_.response = response - }) - } else if (provider === 'twitter') { - this_.response = authResponse.body.profile - } else if (provider === 'instagram') { - this_.response = authResponse - } else if (provider === 'bitbucket') { - this_.$http.get('https://api.bitbucket.org/2.0/user').then(function (response) { - this_.response = response - }) - } else if (provider === 'linkedin') { - this_.response = authResponse - } else if (provider === 'live') { - this_.response = authResponse - } - }).catch(function (err) { - this_.response = err - }) - } - } - } - }, - - { - path: '/auth/callback', - component: { - template: '
' - } - } - ] -}) - -var app = new Vue({ - router: router -}).$mount('#app') diff --git a/example/server.js b/example/server.js deleted file mode 100644 index 5ec2c2c..0000000 --- a/example/server.js +++ /dev/null @@ -1,337 +0,0 @@ -var express = require('express') -var bodyParser = require('body-parser') -var Axios = require('axios') -var Request = require('request') -var cors = require('cors') -var config = require('./config.json') -var OAuth = require('oauth') -var timestamp = require('unix-timestamp') -var oauthSignature = require('oauth-signature') - -var app = express() -app.use(cors()) -app.use(bodyParser.json()) -// app.use(allowCrossDomain); - -app.get('/', function (req, res) { - res.send('vue-authenticate') -}) - -app.post('/auth/:provider', function(req, res){ - switch(req.params.provider) { - case 'github': - githubAuth(req, res) - break - case 'facebook': - facebookAuth(req, res) - break - case 'google': - googleAuth(req, res) - break - case 'twitter': - twitterAuth(req, res) - break - case 'instagram': - instagramAuth(req, res) - break - case 'bitbucket': - bitbucketAuth(req, res) - break - case 'linkedin': - linkedinAuth(req, res) - break - case 'live': - liveAuth(req, res) - break - case 'login': - loginAuth(req, res) - break - case 'register': - registerAuth(req, res) - break - } -}); - -app.listen(4000); - -function allowCrossDomain(req, res, next) { - res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE'); - res.header('Access-Control-Allow-Headers', 'Content-Type'); - next(); -} - -function loginAuth(req, res) { - res.json({ - id: 1, - name: 'John Doe', - email: 'john.doe@domain.com', - created_at: new Date(), - access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiSm9obiBMb2dpbiBEb2UiLCJhZG1pbiI6dHJ1ZX0.VHK2sCbj5nKJ8oC44UTHuhQHXEdPN8zjKjaFT0OZ-LY' - }) -} - -function registerAuth(req, res) { - res.json({ - id: 1, - name: 'John Doe', - email: 'john.doe@domain.com', - created_at: new Date(), - access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJKb2huIFJlZ2lzdGVyIERvZSIsImFkbWluIjp0cnVlfQ.zTR57xocFkGp2UdFwBLk1cZUeqgSujvTqVAFagBlU4I' - }) -} - -function githubAuth(req, res) { - Axios.post('https://github.com/login/oauth/access_token', { - client_id: config.auth.github.clientId, - client_secret: config.auth.github.clientSecret, - code: req.body.code, - redirect_uri: req.body.redirectUri, - state: req.body.state, - grant_type: 'authorization_code' - }, { 'Content-Type': 'application/json' }).then(function (response) { - var responseJson = parseQueryString(response.data) - if (responseJson.error) { - res.status(500).json({ error: responseJson.error }) - } else { - res.json(responseJson) - } - }).catch(function (err) { - res.status(500).json(err) - }) -} - -function facebookAuth(req, res) { - Axios.post('https://graph.facebook.com/v2.4/oauth/access_token', { - client_id: config.auth.facebook.clientId, - client_secret: config.auth.facebook.clientSecret, - code: req.body.code, - redirect_uri: req.body.redirectUri - }, { 'Content-Type': 'application/json' }).then(function (response) { - var responseJson = response.data - res.json(responseJson) - }).catch(function (err) { - res.status(500).json(err) - }) -} - -function googleAuth(req, res) { - Request({ - method: 'post', - url: 'https://accounts.google.com/o/oauth2/token', - form: { - code: req.body.code, - client_id: config.auth.google.clientId, - client_secret: config.auth.google.clientSecret, - redirect_uri: req.body.redirectUri, - grant_type: 'authorization_code' - }, - headers: { - 'content-type': 'application/x-www-form-urlencoded' - } - }, function (err, response, body) { - try { - if (!err && response.statusCode === 200) { - var responseJson = JSON.parse(body) - res.json(responseJson) - } else { - res.status(response.statusCode).json(err) - } - } catch (e) { - res.status(500).json(err || e) - } - }) -} - -function instagramAuth(req, res) { - Request({ - method: 'post', - url: 'https://api.instagram.com/oauth/access_token', - form: { - code: req.body.code, - client_id: config.auth.instagram.clientId, - client_secret: config.auth.instagram.clientSecret, - redirect_uri: req.body.redirectUri, - grant_type: 'authorization_code' - }, - headers: { - 'content-type': 'application/x-www-form-urlencoded' - } - }, function (err, response, body) { - try { - if (!err && response.statusCode === 200) { - var responseJson = JSON.parse(body) - res.json(responseJson) - } else { - res.status(response.statusCode).json(err) - } - } catch (e) { - res.status(500).json(err || e) - } - }) -} - -function bitbucketAuth(req, res) { - Request({ - method: 'post', - url: 'https://bitbucket.org/site/oauth2/access_token', - form: { - code: req.body.code, - client_id: config.auth.bitbucket.clientId, - client_secret: config.auth.bitbucket.clientSecret, - redirect_uri: req.body.redirectUri, - grant_type: 'authorization_code' - }, - headers: { - 'content-type': 'application/x-www-form-urlencoded' - } - }, function (err, response, body) { - try { - if (!err && response.statusCode === 200) { - var responseJson = JSON.parse(body) - res.json(responseJson) - } else { - res.status(response.statusCode).json(err) - } - } catch (e) { - res.status(500).json(err || e) - } - }) -} - -function linkedinAuth(req, res) { - Request({ - method: 'post', - url: 'https://www.linkedin.com/oauth/v2/accessToken', - form: { - code: req.body.code, - client_id: config.auth.linkedin.clientId, - client_secret: config.auth.linkedin.clientSecret, - redirect_uri: req.body.redirectUri, - grant_type: 'authorization_code' - }, - headers: { - 'content-type': 'application/x-www-form-urlencoded' - } - }, function (err, response, body) { - try { - if (!err && response.statusCode === 200) { - var responseJson = JSON.parse(body) - res.json(responseJson) - } else { - res.status(response.statusCode).json(err) - } - } catch (e) { - res.status(500).json(err || e) - } - }) -} - -function liveAuth(req, res) { - Request({ - method: 'post', - url: 'https://login.live.com/oauth20_token.srf', - form: { - code: req.body.code, - client_id: config.auth.live.clientId, - client_secret: config.auth.live.clientSecret, - redirect_uri: req.body.redirectUri, - grant_type: 'authorization_code' - }, - headers: { - 'content-type': 'application/json' - } - }, function (err, response, body) { - try { - if (!err && response.statusCode === 200) { - var responseJson = JSON.parse(body) - res.json(responseJson) - } else { - res.status(response.statusCode).json(err) - } - } catch (e) { - res.status(500).json(err || e) - } - }) -} - -oauthService = new OAuth.OAuth( - 'https://api.twitter.com/oauth/request_token', - 'https://api.twitter.com/oauth/access_token', - config.auth.twitter.clientId, - config.auth.twitter.clientSecret, - '1.0A', - null, - 'HMAC-SHA1' -) - -function twitterAuth(req, res) { - if (!req.body.oauth_token) { - oauthService.getOAuthRequestToken({ oauth_callback: req.body.redirectUri }, function (error, oauthToken, oauthTokenSecret, results) { - if (error) { - res.status(500).json(error) - } else { - res.json({ - oauth_token: oauthToken, - oauth_token_secret: oauthTokenSecret - }) - } - }) - } else { - oauthService.getOAuthAccessToken(req.body.oauth_token, null, req.body.oauth_verifier, function (error, oauthAccessToken, oauthAccessTokenSecret, results) { - - if (error) { - res.status(500).json(error) - } else { - var verifyCredentialsUrl = 'https://api.twitter.com/1.1/account/verify_credentials.json' - var parameters = { - oauth_consumer_key: config.auth.twitter.clientId, - oauth_token: oauthAccessToken, - oauth_nonce: ('vueauth-' + new Date().getTime()), - oauth_timestamp: timestamp.now(), - oauth_signature_method: 'HMAC-SHA1', - oauth_version: '1.0' - } - - var signature = oauthSignature.generate('GET', verifyCredentialsUrl, parameters, config.auth.twitter.clientSecret, oauthAccessTokenSecret) - - Axios.get('https://api.twitter.com/1.1/account/verify_credentials.json', { - headers: { - Authorization: 'OAuth ' + - 'oauth_consumer_key="' + config.auth.twitter.clientId + '",' + - 'oauth_token="' + oauthAccessToken + '",' + - 'oauth_nonce="' + parameters.oauth_nonce + '",' + - 'oauth_timestamp="' + parameters.oauth_timestamp + '",' + - 'oauth_signature_method="HMAC-SHA1",'+ - 'oauth_version="1.0",' + - 'oauth_signature="' + signature + '"' - } - }).then(function (response) { - res.json({ - access_token: oauthAccessToken, - access_token_secret: oauthAccessTokenSecret, - - profile: response.data - }) - }).catch(function (err) { - console.log(err.response.data.errors) - res.status(500).json(err.response.data.errors) - }) - } - }) - } -} - -function parseQueryString(str) { - let obj = {}; - let key; - let value; - (str || '').split('&').forEach((keyValue) => { - if (keyValue) { - value = keyValue.split('='); - key = decodeURIComponent(value[0]); - obj[key] = (!!value[1]) ? decodeURIComponent(value[1]) : true; - } - }); - return obj; -} \ No newline at end of file diff --git a/example/vue-authenticate.js b/example/vue-authenticate.js deleted file mode 100644 index bddb965..0000000 --- a/example/vue-authenticate.js +++ /dev/null @@ -1,1444 +0,0 @@ -/*! - * vue-authenticate v1.3.5-beta.1 - * https://github.com/dgrubelic/vue-authenticate - * Released under the MIT License. - */ - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.VueAuthenticate = factory()); -}(this, (function () { 'use strict'; - -if (typeof Object.assign != 'function') { - Object.assign = function(target, varArgs) { - 'use strict'; - var arguments$1 = arguments; - - if (target == null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var to = Object(target); - - for (var index = 1; index < arguments.length; index++) { - var nextSource = arguments$1[index]; - - if (nextSource != null) { // Skip over if undefined or null - for (var nextKey in nextSource) { - // Avoid bugs when hasOwnProperty is shadowed - if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { - to[nextKey] = nextSource[nextKey]; - } - } - } - } - return to; - }; -} - -function camelCase(name) { - return name.replace(/([\:\-\_]+(.))/g, function (_, separator, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }); -} - -function isUndefined(value) { - return typeof value === 'undefined' -} - - - -function isObject(value) { - return value !== null && typeof value === 'object' -} - -function isString(value) { - return typeof value === 'string' -} - - - -function isFunction(value) { - return typeof value === 'function' -} - -function objectExtend(a, b) { - - // Don't touch 'null' or 'undefined' objects. - if (a == null || b == null) { - return a; - } - - Object.keys(b).forEach(function (key) { - if (Object.prototype.toString.call(b[key]) == '[object Object]') { - if (Object.prototype.toString.call(a[key]) != '[object Object]') { - a[key] = b[key]; - } else { - a[key] = objectExtend(a[key], b[key]); - } - } else { - a[key] = b[key]; - } - }); - - return a; -} - -/** - * Assemble url from two segments - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} baseUrl Base url - * @param {String} url URI - * @return {String} - */ -function joinUrl(baseUrl, url) { - if (/^(?:[a-z]+:)?\/\//i.test(url)) { - return url; - } - var joined = [baseUrl, url].join('/'); - var normalize = function (str) { - return str - .replace(/[\/]+/g, '/') - .replace(/\/\?/g, '?') - .replace(/\/\#/g, '#') - .replace(/\:\//g, '://'); - }; - return normalize(joined); -} - -/** - * Get full path based on current location - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {Location} location - * @return {String} - */ -function getFullUrlPath(location) { - var isHttps = location.protocol === 'https:'; - return location.protocol + '//' + location.hostname + - ':' + (location.port || (isHttps ? '443' : '80')) + - (/^\//.test(location.pathname) ? location.pathname : '/' + location.pathname); -} - -/** - * Parse query string variables - * - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} Query string - * @return {String} - */ -function parseQueryString(str) { - var obj = {}; - var key; - var value; - (str || '').split('&').forEach(function (keyValue) { - if (keyValue) { - value = keyValue.split('='); - key = decodeURIComponent(value[0]); - obj[key] = (!!value[1]) ? decodeURIComponent(value[1]) : true; - } - }); - return obj; -} - -/** - * Decode base64 string - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param {String} str base64 encoded string - * @return {Object} - */ -function decodeBase64(str) { - var buffer; - if (typeof module !== 'undefined' && module.exports) { - try { - buffer = require('buffer').Buffer; - } catch (err) { - // noop - } - } - - var fromCharCode = String.fromCharCode; - - var re_btou = new RegExp([ - '[\xC0-\xDF][\x80-\xBF]', - '[\xE0-\xEF][\x80-\xBF]{2}', - '[\xF0-\xF7][\x80-\xBF]{3}' - ].join('|'), 'g'); - - var cb_btou = function (cccc) { - switch (cccc.length) { - case 4: - var cp = ((0x07 & cccc.charCodeAt(0)) << 18) - | ((0x3f & cccc.charCodeAt(1)) << 12) - | ((0x3f & cccc.charCodeAt(2)) << 6) - | (0x3f & cccc.charCodeAt(3)); - var offset = cp - 0x10000; - return (fromCharCode((offset >>> 10) + 0xD800) - + fromCharCode((offset & 0x3FF) + 0xDC00)); - case 3: - return fromCharCode( - ((0x0f & cccc.charCodeAt(0)) << 12) - | ((0x3f & cccc.charCodeAt(1)) << 6) - | (0x3f & cccc.charCodeAt(2)) - ); - default: - return fromCharCode( - ((0x1f & cccc.charCodeAt(0)) << 6) - | (0x3f & cccc.charCodeAt(1)) - ); - } - }; - - var btou = function (b) { - return b.replace(re_btou, cb_btou); - }; - - var _decode = buffer ? function (a) { - return (a.constructor === buffer.constructor - ? a : new buffer(a, 'base64')).toString(); - } - : function (a) { - return btou(atob(a)); - }; - - return _decode( - String(str).replace(/[-_]/g, function (m0) { - return m0 === '-' ? '+' : '/'; - }) - .replace(/[^A-Za-z0-9\+\/]/g, '') - ); -} - -function parseCookies(str) { - if (str.length === 0) { return {}; } - var parsed = {}; - var pattern = new RegExp('\\s*;\\s*'); - str.split(pattern).forEach(function (i) { - var ref = i.split('='); - var encodedKey = ref[0]; - var encodedValue = ref[1]; - var key = decodeURIComponent(encodedKey); - var value = decodeURIComponent(encodedValue); - parsed[key] = value; - }); - return parsed; -} - -function formatOptions(options) { - var path = options.path; - var domain = options.domain; - var expires = options.expires; - var secure = options.secure; - return [ - typeof path === 'undefined' || path === null - ? '' : ';path=' + path, - typeof domain === 'undefined' || domain === null - ? '' : ';domain=' + domain, - typeof expires === 'undefined' || expires === null - ? '' : ';expires=' + expires.toUTCString(), - typeof secure === 'undefined' || secure === null || secure === false - ? '' : ';secure' - ].join(''); -} - -function formatCookie(key, value, options) { - return [ - encodeURIComponent(key), - '=', - encodeURIComponent(value), - formatOptions(options) - ].join(''); -} - -// Store setTimeout reference so promise-polyfill will be unaffected by -// other code modifying setTimeout (like sinon.useFakeTimers()) -var setTimeoutFunc = setTimeout; - -function noop() {} - -// Polyfill for Function.prototype.bind -function bind(fn, thisArg) { - return function () { - fn.apply(thisArg, arguments); - }; -} - -function Promise$1(fn) { - if (typeof this !== 'object') { throw new TypeError('Promises must be constructed via new'); } - if (typeof fn !== 'function') { throw new TypeError('not a function'); } - this._state = 0; - this._handled = false; - this._value = undefined; - this._deferreds = []; - - doResolve(fn, this); -} - -function handle(self, deferred) { - while (self._state === 3) { - self = self._value; - } - if (self._state === 0) { - self._deferreds.push(deferred); - return; - } - self._handled = true; - Promise$1._immediateFn(function () { - var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; - if (cb === null) { - (self._state === 1 ? resolve : reject)(deferred.promise, self._value); - return; - } - var ret; - try { - ret = cb(self._value); - } catch (e) { - reject(deferred.promise, e); - return; - } - resolve(deferred.promise, ret); - }); -} - -function resolve(self, newValue) { - try { - // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure - if (newValue === self) { throw new TypeError('A promise cannot be resolved with itself.'); } - if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { - var then = newValue.then; - if (newValue instanceof Promise$1) { - self._state = 3; - self._value = newValue; - finale(self); - return; - } else if (typeof then === 'function') { - doResolve(bind(then, newValue), self); - return; - } - } - self._state = 1; - self._value = newValue; - finale(self); - } catch (e) { - reject(self, e); - } -} - -function reject(self, newValue) { - self._state = 2; - self._value = newValue; - finale(self); -} - -function finale(self) { - if (self._state === 2 && self._deferreds.length === 0) { - Promise$1._immediateFn(function() { - if (!self._handled) { - Promise$1._unhandledRejectionFn(self._value); - } - }); - } - - for (var i = 0, len = self._deferreds.length; i < len; i++) { - handle(self, self._deferreds[i]); - } - self._deferreds = null; -} - -function Handler(onFulfilled, onRejected, promise) { - this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; - this.onRejected = typeof onRejected === 'function' ? onRejected : null; - this.promise = promise; -} - -/** - * Take a potentially misbehaving resolver function and make sure - * onFulfilled and onRejected are only called once. - * - * Makes no guarantees about asynchrony. - */ -function doResolve(fn, self) { - var done = false; - try { - fn(function (value) { - if (done) { return; } - done = true; - resolve(self, value); - }, function (reason) { - if (done) { return; } - done = true; - reject(self, reason); - }); - } catch (ex) { - if (done) { return; } - done = true; - reject(self, ex); - } -} - -Promise$1.prototype['catch'] = function (onRejected) { - return this.then(null, onRejected); -}; - -Promise$1.prototype.then = function (onFulfilled, onRejected) { - var prom = new (this.constructor)(noop); - - handle(this, new Handler(onFulfilled, onRejected, prom)); - return prom; -}; - -Promise$1.all = function (arr) { - var args = Array.prototype.slice.call(arr); - - return new Promise$1(function (resolve, reject) { - if (args.length === 0) { return resolve([]); } - var remaining = args.length; - - function res(i, val) { - try { - if (val && (typeof val === 'object' || typeof val === 'function')) { - var then = val.then; - if (typeof then === 'function') { - then.call(val, function (val) { - res(i, val); - }, reject); - return; - } - } - args[i] = val; - if (--remaining === 0) { - resolve(args); - } - } catch (ex) { - reject(ex); - } - } - - for (var i = 0; i < args.length; i++) { - res(i, args[i]); - } - }); -}; - -Promise$1.resolve = function (value) { - if (value && typeof value === 'object' && value.constructor === Promise$1) { - return value; - } - - return new Promise$1(function (resolve) { - resolve(value); - }); -}; - -Promise$1.reject = function (value) { - return new Promise$1(function (resolve, reject) { - reject(value); - }); -}; - -Promise$1.race = function (values) { - return new Promise$1(function (resolve, reject) { - for (var i = 0, len = values.length; i < len; i++) { - values[i].then(resolve, reject); - } - }); -}; - -// Use polyfill for setImmediate for performance gains -Promise$1._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) || - function (fn) { - setTimeoutFunc(fn, 0); - }; - -Promise$1._unhandledRejectionFn = function _unhandledRejectionFn(err) { - if (typeof console !== 'undefined' && console) { - console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console - } -}; - -/** - * Set the immediate function to execute callbacks - * @param fn {function} Function to execute - * @deprecated - */ -Promise$1._setImmediateFn = function _setImmediateFn(fn) { - Promise$1._immediateFn = fn; -}; - -/** - * Change the function to execute on unhandled rejection - * @param {function} fn Function to execute on unhandled rejection - * @deprecated - */ -Promise$1._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { - Promise$1._unhandledRejectionFn = fn; -}; - -function getCookieDomainUrl() { - try { - return window.location.hostname - } catch (e) {} - - return ''; -} - -function getRedirectUri(uri) { - try { - return (!isUndefined(uri)) - ? ("" + (window.location.origin) + uri) - : window.location.origin - } catch (e) {} - - return uri || null; -} - -/** - * Default configuration - */ -var defaultOptions = { - baseUrl: null, - tokenName: 'token', - tokenPrefix: 'vueauth', - tokenHeader: 'Authorization', - tokenType: 'Bearer', - loginUrl: '/auth/login', - registerUrl: '/auth/register', - logoutUrl: null, - storageType: 'localStorage', - storageNamespace: 'vue-authenticate', - cookieStorage: { - domain: getCookieDomainUrl(), - path: '/', - secure: false - }, - requestDataKey: 'data', - responseDataKey: 'data', - - /** - * Default request interceptor for Axios library - * @context {VueAuthenticate} - */ - bindRequestInterceptor: function ($auth) { - var tokenHeader = $auth.options.tokenHeader; - - $auth.$http.interceptors.request.use(function (config) { - if ($auth.isAuthenticated()) { - config.headers[tokenHeader] = [ - $auth.options.tokenType, $auth.getToken() - ].join(' '); - } else { - delete config.headers[tokenHeader]; - } - return config - }); - }, - - providers: { - facebook: { - name: 'facebook', - url: '/auth/facebook', - authorizationEndpoint: 'https://www.facebook.com/v2.5/dialog/oauth', - redirectUri: getRedirectUri('/'), - requiredUrlParams: ['display', 'scope'], - scope: ['email'], - scopeDelimiter: ',', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 580, height: 400 } - }, - - google: { - name: 'google', - url: '/auth/google', - authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth', - redirectUri: getRedirectUri(), - requiredUrlParams: ['scope'], - optionalUrlParams: ['display'], - scope: ['profile', 'email'], - scopePrefix: 'openid', - scopeDelimiter: ' ', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 452, height: 633 } - }, - - github: { - name: 'github', - url: '/auth/github', - authorizationEndpoint: 'https://github.com/login/oauth/authorize', - redirectUri: getRedirectUri(), - optionalUrlParams: ['scope'], - scope: ['user:email'], - scopeDelimiter: ' ', - oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } - }, - - instagram: { - name: 'instagram', - url: '/auth/instagram', - authorizationEndpoint: 'https://api.instagram.com/oauth/authorize', - redirectUri: getRedirectUri(), - requiredUrlParams: ['scope'], - scope: ['basic'], - scopeDelimiter: '+', - oauthType: '2.0', - popupOptions: { width: null, height: null } - }, - - twitter: { - name: 'twitter', - url: '/auth/twitter', - authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate', - redirectUri: getRedirectUri(), - oauthType: '1.0', - popupOptions: { width: 495, height: 645 } - }, - - bitbucket: { - name: 'bitbucket', - url: '/auth/bitbucket', - authorizationEndpoint: 'https://bitbucket.org/site/oauth2/authorize', - redirectUri: getRedirectUri('/'), - optionalUrlParams: ['scope'], - scope: ['email'], - scopeDelimiter: ' ', - oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } - }, - - linkedin: { - name: 'linkedin', - url: '/auth/linkedin', - authorizationEndpoint: 'https://www.linkedin.com/oauth/v2/authorization', - redirectUri: getRedirectUri(), - requiredUrlParams: ['state'], - scope: ['r_emailaddress'], - scopeDelimiter: ' ', - state: 'STATE', - oauthType: '2.0', - popupOptions: { width: 527, height: 582 } - }, - - live: { - name: 'live', - url: '/auth/live', - authorizationEndpoint: 'https://login.live.com/oauth20_authorize.srf', - redirectUri: getRedirectUri(), - requiredUrlParams: ['display', 'scope'], - scope: ['wl.emails'], - scopeDelimiter: ' ', - display: 'popup', - oauthType: '2.0', - popupOptions: { width: 500, height: 560 } - }, - - oauth1: { - name: null, - url: '/auth/oauth1', - authorizationEndpoint: null, - redirectUri: getRedirectUri(), - oauthType: '1.0', - popupOptions: null - }, - - oauth2: { - name: null, - url: '/auth/oauth2', - clientId: null, - redirectUri: getRedirectUri(), - authorizationEndpoint: null, - defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], - requiredUrlParams: null, - optionalUrlParams: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - state: null, - oauthType: '2.0', - popupOptions: null, - responseType: 'code', - responseParams: { - code: 'code', - clientId: 'clientId', - redirectUri: 'redirectUri' - } - } - } -}; - -var CookieStorage = function CookieStorage(defaultOptions) { - this._defaultOptions = objectExtend({ - domain: getCookieDomainUrl(), - expires: null, - path: '/', - secure: false - }, defaultOptions); -}; - -CookieStorage.prototype.setItem = function setItem (key, value) { - var options = objectExtend({}, this._defaultOptions); - var cookie = formatCookie(key, value, options); - this._setCookie(cookie); -}; - -CookieStorage.prototype.getItem = function getItem (key) { - var cookies = parseCookies(this._getCookie()); - return cookies.hasOwnProperty(key) ? cookies[key] : null; -}; - -CookieStorage.prototype.removeItem = function removeItem (key) { - var value = ''; - var defaultOptions = objectExtend({}, this._defaultOptions); - var options = objectExtend(defaultOptions, { - expires: new Date(0) - }); - var cookie = formatCookie(key, value, options); - this._setCookie(cookie); -}; - -CookieStorage.prototype._getCookie = function _getCookie () { - try { - return typeof document === 'undefined' - ? '' : typeof document.cookie === 'undefined' - ? '' : document.cookie; - } catch (e) {} - - return ''; -}; - -CookieStorage.prototype._setCookie = function _setCookie (cookie) { - try { - document.cookie = cookie; - } catch (e) {} -}; - -var LocalStorage = function LocalStorage(namespace) { - this.namespace = namespace || null; -}; - -LocalStorage.prototype.setItem = function setItem (key, value) { - window.localStorage.setItem(this._getStorageKey(key), value); -}; - -LocalStorage.prototype.getItem = function getItem (key) { - return window.localStorage.getItem(this._getStorageKey(key)) -}; - -LocalStorage.prototype.removeItem = function removeItem (key) { - window.localStorage.removeItem(this._getStorageKey(key)); -}; - -LocalStorage.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; - -var MemoryStorage = function MemoryStorage(namespace) { - this.namespace = namespace || null; - this._storage = {}; -}; - -MemoryStorage.prototype.setItem = function setItem (key, value) { - this._storage[this._getStorageKey(key)] = value; -}; - -MemoryStorage.prototype.getItem = function getItem (key) { - return this._storage[this._getStorageKey(key)] -}; - -MemoryStorage.prototype.removeItem = function removeItem (key) { - delete this._storage[this._getStorageKey(key)]; -}; - -MemoryStorage.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; - -var LocalStorage$2 = function LocalStorage(namespace) { - this.namespace = namespace || null; -}; - -LocalStorage$2.prototype.setItem = function setItem (key, value) { - window.sessionStorage.setItem(this._getStorageKey(key), value); -}; - -LocalStorage$2.prototype.getItem = function getItem (key) { - return window.sessionStorage.getItem(this._getStorageKey(key)) -}; - -LocalStorage$2.prototype.removeItem = function removeItem (key) { - window.sessionStorage.removeItem(this._getStorageKey(key)); -}; - -LocalStorage$2.prototype._getStorageKey = function _getStorageKey (key) { - if (this.namespace) { - return [this.namespace, key].join('.') - } - return key; -}; - -function StorageFactory(options) { - switch (options.storageType) { - case 'localStorage': - try { - window.localStorage.setItem('testKey', 'test'); - window.localStorage.removeItem('testKey'); - return new LocalStorage(options.storageNamespace) - } catch(e) {} - - case 'sessionStorage': - try { - window.sessionStorage.setItem('testKey', 'test'); - window.sessionStorage.removeItem('testKey'); - return new LocalStorage$2(options.storageNamespace) - } catch (e) {} - - case 'cookieStorage': - return new CookieStorage(options.cookieStorage); - - case 'memoryStorage': - default: - return new MemoryStorage(options.storageNamespace) - break; - } -} - -/** - * OAuth2 popup management class - * - * @author Sahat Yalkabov - * @copyright Class mostly taken from https://github.com/sahat/satellizer - * and adjusted to fit vue-authenticate library - */ -var OAuthPopup = function OAuthPopup(url, name, popupOptions) { - this.popup = null; - this.url = url; - this.name = name; - this.popupOptions = popupOptions; -}; - -OAuthPopup.prototype.open = function open (redirectUri, skipPooling) { - try { - this.popup = window.open(this.url, this.name, this._stringifyOptions()); - if (this.popup && this.popup.focus) { - this.popup.focus(); - } - - if (skipPooling) { - return Promise$1.resolve() - } else { - return this.pooling(redirectUri) - } - } catch(e) { - return Promise$1.reject(new Error('OAuth popup error occurred')) - } -}; - -OAuthPopup.prototype.pooling = function pooling (redirectUri) { - var this$1 = this; - - return new Promise$1(function (resolve, reject) { - var redirectUriParser = document.createElement('a'); - redirectUriParser.href = redirectUri; - var redirectUriPath = getFullUrlPath(redirectUriParser); - - var poolingInterval = setInterval(function () { - if (!this$1.popup || this$1.popup.closed || this$1.popup.closed === undefined) { - clearInterval(poolingInterval); - poolingInterval = null; - reject(new Error('Auth popup window closed')); - } - - try { - var popupWindowPath = getFullUrlPath(this$1.popup.location); - - if (popupWindowPath === redirectUriPath) { - if (this$1.popup.location.search || this$1.popup.location.hash) { - var query = parseQueryString(this$1.popup.location.search.substring(1).replace(/\/$/, '')); - var hash = parseQueryString(this$1.popup.location.hash.substring(1).replace(/[\/$]/, '')); - var params = objectExtend({}, query); - params = objectExtend(params, hash); - - if (params.error) { - reject(new Error(params.error)); - } else { - resolve(params); - } - } else { - reject(new Error('OAuth redirect has occurred but no query or hash parameters were found.')); - } - - clearInterval(poolingInterval); - poolingInterval = null; - this$1.popup.close(); - } - } catch(e) { - // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame. - } - }, 250); - }) -}; - -OAuthPopup.prototype._stringifyOptions = function _stringifyOptions () { - var this$1 = this; - - var options = []; - for (var optionKey in this$1.popupOptions) { - if (!isUndefined(this$1.popupOptions[optionKey])) { - options.push((optionKey + "=" + (this$1.popupOptions[optionKey]))); - } - } - return options.join(',') -}; - -var defaultProviderConfig = { - name: null, - url: null, - authorizationEndpoint: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - redirectUri: null, - requiredUrlParams: null, - defaultUrlParams: null, - oauthType: '1.0', - popupOptions: {} -}; - -var OAuth = function OAuth($http, storage, providerConfig, options) { - this.$http = $http; - this.storage = storage; - this.providerConfig = objectExtend({}, defaultProviderConfig); - this.providerConfig = objectExtend(this.providerConfig, providerConfig); - this.options = options; -}; - -/** - * Initialize OAuth1 process - * @param{Object} userData User data - * @return {Promise} - */ -OAuth.prototype.init = function init (userData) { - var this$1 = this; - - this.oauthPopup = new OAuthPopup('about:blank', this.providerConfig.name, this.providerConfig.popupOptions); - - if (window && !window['cordova']) { - this.oauthPopup.open(this.providerConfig.redirectUri, true); - } - - return this.getRequestToken().then(function (response) { - return this$1.openPopup(response).then(function (popupResponse) { - return this$1.exchangeForToken(popupResponse, userData) - }) - }) -}; - -/** - * Get OAuth1 request token - * @return {Promise} - */ -OAuth.prototype.getRequestToken = function getRequestToken () { - var requestOptions = {}; - requestOptions.method = 'POST'; - requestOptions[this.options.requestDataKey] = objectExtend({}, this.providerConfig); - requestOptions.withCredentials = this.options.withCredentials; - if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - requestOptions.url = this.providerConfig.url; - } - - return this.$http(requestOptions) -}; - -/** - * Open OAuth1 popup - * @param{Object} response Response object containing request token - * @return {Promise} - */ -OAuth.prototype.openPopup = function openPopup (response) { - var url = [this.providerConfig.authorizationEndpoint, this.buildQueryString(response[this.options.responseDataKey])].join('?'); - - this.oauthPopup.popup.location = url; - if (window && window['cordova']) { - return this.oauthPopup.open(this.providerConfig.redirectUri) - } else { - return this.oauthPopup.pooling(this.providerConfig.redirectUri) - } -}; - -/** - * Exchange token and token verifier for access token - * @param{Object} oauth OAuth data containing token and token verifier - * @param{Object} userData User data - * @return {Promise} - */ -OAuth.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { - var payload = objectExtend({}, userData); - payload = objectExtend(payload, oauth); - var requestOptions = {}; - requestOptions.method = 'POST'; - requestOptions[this.options.requestDataKey] = payload; - requestOptions.withCredentials = this.options.withCredentials; - if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - requestOptions.url = this.providerConfig.url; - } - return this.$http(requestOptions) -}; - -OAuth.prototype.buildQueryString = function buildQueryString (params) { - var parsedParams = []; - for (var key in params) { - var value = params[key]; - parsedParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); - } - return parsedParams.join('&'); -}; - -/** - * Default provider configuration - * @type {Object} - */ -var defaultProviderConfig$1 = { - name: null, - url: null, - clientId: null, - authorizationEndpoint: null, - redirectUri: null, - scope: null, - scopePrefix: null, - scopeDelimiter: null, - state: null, - requiredUrlParams: null, - defaultUrlParams: ['response_type', 'client_id', 'redirect_uri'], - responseType: 'code', - responseParams: { - code: 'code', - clientId: 'clientId', - redirectUri: 'redirectUri' - }, - oauthType: '2.0', - popupOptions: {} -}; - -var OAuth2 = function OAuth2($http, storage, providerConfig, options) { - this.$http = $http; - this.storage = storage; - this.providerConfig = objectExtend({}, defaultProviderConfig$1); - this.providerConfig = objectExtend(this.providerConfig, providerConfig); - this.options = options; -}; - -OAuth2.prototype.init = function init (userData) { - var this$1 = this; - - var stateName = this.providerConfig.name + '_state'; - if (isFunction(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state()); - } else if (isString(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state); - } - - var url = [this.providerConfig.authorizationEndpoint, this._stringifyRequestParams()].join('?'); - - this.oauthPopup = new OAuthPopup(url, this.providerConfig.name, this.providerConfig.popupOptions); - - return new Promise(function (resolve, reject) { - this$1.oauthPopup.open(this$1.providerConfig.redirectUri).then(function (response) { - if (this$1.providerConfig.responseType === 'token' || !this$1.providerConfig.url) { - return resolve(response) - } - - if (response.state && response.state !== this$1.storage.getItem(stateName)) { - return reject(new Error('State parameter value does not match original OAuth request state value')) - } - - resolve(this$1.exchangeForToken(response, userData)); - }).catch(function (err) { - reject(err); - }); - }) -}; - -/** - * Exchange temporary oauth data for access token - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @param{[type]} oauth [description] - * @param{[type]} userData [description] - * @return {[type]} [description] - */ -OAuth2.prototype.exchangeForToken = function exchangeForToken (oauth, userData) { - var this$1 = this; - - var payload = objectExtend({}, userData); - - for (var key in defaultProviderConfig$1.responseParams) { - var value = defaultProviderConfig$1[key]; - - switch(key) { - case 'code': - payload[key] = oauth.code; - break - case 'clientId': - payload[key] = this$1.providerConfig.clientId; - break - case 'redirectUri': - payload[key] = this$1.providerConfig.redirectUri; - break - default: - payload[key] = oauth[key]; - } - } - - if (oauth.state) { - payload.state = oauth.state; - } - - var exchangeTokenUrl; - if (this.options.baseUrl) { - exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url); - } else { - exchangeTokenUrl = this.providerConfig.url; - } - - return this.$http.post(exchangeTokenUrl, payload, { - withCredentials: this.options.withCredentials - }) -}; - -/** - * Stringify oauth params - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * - * @return {String} - */ -OAuth2.prototype._stringifyRequestParams = function _stringifyRequestParams () { - var this$1 = this; - - var keyValuePairs = []; - var paramCategories = ['defaultUrlParams', 'requiredUrlParams', 'optionalUrlParams']; - - paramCategories.forEach(function (categoryName) { - if (!this$1.providerConfig[categoryName]) { return } - if (!Array.isArray(this$1.providerConfig[categoryName])) { return } - - this$1.providerConfig[categoryName].forEach(function (paramName) { - var camelCaseParamName = camelCase(paramName); - var paramValue = isFunction(this$1.providerConfig[paramName]) ? this$1.providerConfig[paramName]() : this$1.providerConfig[camelCaseParamName]; - - if (paramName === 'redirect_uri' && !paramValue) { return } - - if (paramName === 'state') { - var stateName = this$1.providerConfig.name + '_state'; - paramValue = encodeURIComponent(this$1.storage.getItem(stateName)); - } - if (paramName === 'scope' && Array.isArray(paramValue)) { - paramValue = paramValue.join(this$1.providerConfig.scopeDelimiter); - if (this$1.providerConfig.scopePrefix) { - paramValue = [this$1.providerConfig.scopePrefix, paramValue].join(this$1.providerConfig.scopeDelimiter); - } - } - - keyValuePairs.push([paramName, paramValue]); - }); - }); - - return keyValuePairs.map(function (param) { - return param.join('=') - }).join('&') -}; - -var VueAuthenticate = function VueAuthenticate($http, overrideOptions) { - var options = objectExtend({}, defaultOptions); - options = objectExtend(options, overrideOptions); - var storage = StorageFactory(options); - - Object.defineProperties(this, { - $http: { - get: function get() { - return $http - } - }, - - options: { - get: function get() { - return options - } - }, - - storage: { - get: function get() { - return storage - } - }, - - tokenName: { - get: function get() { - if (this.options.tokenPrefix) { - return [this.options.tokenPrefix, this.options.tokenName].join('_') - } else { - return this.options.tokenName - } - } - } - }); - - // Setup request interceptors - if (this.options.bindRequestInterceptor && isFunction(this.options.bindRequestInterceptor)) { - this.options.bindRequestInterceptor.call(this, this); - } else { - throw new Error('Request interceptor must be functions') - } -}; - -/** - * Check if user is authenticated - * @author Sahat Yalkabov - * @copyright Method taken from https://github.com/sahat/satellizer - * @return {Boolean} - */ -VueAuthenticate.prototype.isAuthenticated = function isAuthenticated () { - var token = this.storage.getItem(this.tokenName); - - if (token) {// Token is present - if (token.split('.').length === 3) {// Token with a valid JWT format XXX.YYY.ZZZ - try { // Could be a valid JWT or an access token with the same format - var base64Url = token.split('.')[1]; - var base64 = base64Url.replace('-', '+').replace('_', '/'); - var exp = JSON.parse(window.atob(base64)).exp; - if (typeof exp === 'number') {// JWT with an optonal expiration claims - return Math.round(new Date().getTime() / 1000) < exp; - } - } catch (e) { - return true;// Pass: Non-JWT token that looks like JWT - } - } - return true;// Pass: All other tokens - } - return false -}; - -/** - * Get token if user is authenticated - * @return {String} Authentication token - */ -VueAuthenticate.prototype.getToken = function getToken () { - return this.storage.getItem(this.tokenName) -}; - -/** - * Set new authentication token - * @param {String|Object} token - */ -VueAuthenticate.prototype.setToken = function setToken (response) { - if (response[this.options.responseDataKey]) { - response = response[this.options.responseDataKey]; - } - - var token; - if (response.access_token) { - if (isObject(response.access_token) && isObject(response.access_token[this.options.responseDataKey])) { - response = response.access_token; - } else if (isString(response.access_token)) { - token = response.access_token; - } - } - - if (!token && response) { - token = response[this.options.tokenName]; - } - - if (token) { - this.storage.setItem(this.tokenName, token); - } -}; - -VueAuthenticate.prototype.getPayload = function getPayload () { - var token = this.storage.getItem(this.tokenName); - - if (token && token.split('.').length === 3) { - try { - var base64Url = token.split('.')[1]; - var base64 = base64Url.replace('-', '+').replace('_', '/'); - return JSON.parse(decodeBase64(base64)); - } catch (e) {} - } -}; - -/** - * Login user using email and password - * @param{Object} user User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.login = function login (user, requestOptions) { - var this$1 = this; - - requestOptions = requestOptions || {}; - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.loginUrl); - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey]; - requestOptions.method = requestOptions.method || 'POST'; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.setToken(response); - return response - }) -}; - -/** - * Register new user - * @param{Object} user User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.register = function register (user, requestOptions) { - var this$1 = this; - - requestOptions = requestOptions || {}; - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.registerUrl); - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey]; - requestOptions.method = requestOptions.method || 'POST'; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.setToken(response); - return response - }) -}; - -/** - * Logout current user - * @param{Object} requestOptionsLogout request options object - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.logout = function logout (requestOptions) { - var this$1 = this; - - if (!this.isAuthenticated()) { - return Promise$1.reject(new Error('There is no currently authenticated user')) - } - - requestOptions = requestOptions || {}; - - if (requestOptions.url) { - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.logoutUrl); - requestOptions.method = requestOptions.method || 'POST'; - requestOptions[this.options.requestDataKey] = requestOptions[this.options.requestDataKey] || undefined; - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials; - - return this.$http(requestOptions).then(function (response) { - this$1.storage.removeItem(this$1.tokenName); - }) - } else { - this.storage.removeItem(this.tokenName); - return Promise$1.resolve(); - } -}; - -/** - * Authenticate user using authentication provider - * - * @param{String} provider Provider name - * @param{Object} userData User data - * @param{Object} requestOptions Request options - * @return {Promise} Request promise - */ -VueAuthenticate.prototype.authenticate = function authenticate (provider, userData, requestOptions) { - var this$1 = this; - - return new Promise$1(function (resolve, reject) { - var providerConfig = this$1.options.providers[provider]; - if (!providerConfig) { - return reject(new Error('Unknown provider')) - } - - var providerInstance; - switch (providerConfig.oauthType) { - case '1.0': - providerInstance = new OAuth(this$1.$http, this$1.storage, providerConfig, this$1.options); - break - case '2.0': - providerInstance = new OAuth2(this$1.$http, this$1.storage, providerConfig, this$1.options); - break - default: - return reject(new Error('Invalid OAuth type')) - break - } - - return providerInstance.init(userData).then(function (response) { - this$1.setToken(response); - - if (this$1.isAuthenticated()) { - return resolve(response) - } else { - return reject(new Error('Authentication failed')) - } - }).catch(function (err) { return reject(err); }) - }) -}; - -/** - * VueAuthenticate plugin - * @param {Object} Vue - * @param {Object} options - */ -function plugin(Vue, options) { - if (plugin.installed) { - return - } - plugin.installed = true; - - var vueAuthInstance = null; - Object.defineProperties(Vue.prototype, { - $auth: { - get: function get() { - if (!vueAuthInstance) { - // Request handler library not found, throw error - if (!this.$http) { - throw new Error('Request handler instance not found') - } - - vueAuthInstance = new VueAuthenticate(this.$http, options); - } - return vueAuthInstance - } - } - }); -} - -/** - * External factory helper for ES5 and CommonJS - * @param {Object} $http Instance of request handling library - * @param {Object} options Configuration object - * @return {VueAuthenticate} VueAuthenticate instance - */ -plugin.factory = function ($http, options) { - return new VueAuthenticate($http, options) -}; - -return plugin; - -}))); diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index ea29b20..0000000 --- a/gulpfile.js +++ /dev/null @@ -1,33 +0,0 @@ -var gulp = require('gulp'), - connect = require('gulp-connect'), - webpack = require('webpack'), - gulpWebpack = require('gulp-webpack'), - history = require('connect-history-api-fallback') - -gulp.task('compile', function () { - var webpackConfig = require('./example/webpack.config.js') - return gulp.src('./example/index.js') - .pipe(gulpWebpack(webpackConfig, webpack)) - .pipe(gulp.dest('./example')) - .pipe(connect.reload()) -}) - -gulp.task('server', function () { - connect.server({ - name: 'VueAuthentication', - root: './example', - base: 'example', - port: 8080, - livereload: true, - verbose: true, - middleware: function () { - return [history()] - } - }); -}) - -gulp.task('watch', function () { - gulp.watch(['./example/index.js', './src/**/*.js'], ['compile']) -}) - -gulp.task('dev', ['server']) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7189a62 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,849 @@ +{ + "name": "vue-authenticate", + "version": "1.4.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/compat-data": { + "version": "7.13.11", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.11.tgz", + "integrity": "sha512-BwKEkO+2a67DcFeS3RLl0Z3Gs2OvdXewuWjc1Hfokhb5eQWP9YRYH1/+VrVZvql2CfjOiNGqSAFOYt4lsqTHzg==", + "dev": true + }, + "@babel/core": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.10.tgz", + "integrity": "sha512-bfIYcT0BdKeAZrovpMqX2Mx5NrgAckGbwT982AkdS5GNfn3KMGiprlBAtmBcFZRUmpaufS6WZFP8trvx8ptFDw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-compilation-targets": "^7.13.10", + "@babel/helper-module-transforms": "^7.13.0", + "@babel/helpers": "^7.13.10", + "@babel/parser": "^7.13.10", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "semver": "^6.3.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.10.tgz", + "integrity": "sha512-/Xju7Qg1GQO4mHZ/Kcs6Au7gfafgZnwm+a7sy/ow/tV1sHeraRUHbjdat8/UvDor4Tez+siGKDk6zIKtCPKVJA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.8", + "@babel/helper-validator-option": "^7.12.17", + "browserslist": "^4.14.5", + "semver": "^6.3.0" + } + }, + "@babel/helper-function-name": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz", + "integrity": "sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz", + "integrity": "sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-module-transforms": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz", + "integrity": "sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-replace-supers": "^7.13.0", + "@babel/helper-simple-access": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/helper-validator-identifier": "^7.12.11", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", + "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-replace-supers": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz", + "integrity": "sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.13.0", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" + } + }, + "@babel/helper-simple-access": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz", + "integrity": "sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", + "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz", + "integrity": "sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ==", + "dev": true, + "requires": { + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" + } + }, + "@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.13.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.11.tgz", + "integrity": "sha512-PhuoqeHoO9fc4ffMEVk4qb/w/s2iOSWohvbHxLtxui0eBg3Lg5gN1U8wp1V1u61hOWkPQJJyJzGH6Y+grwkq8Q==", + "dev": true + }, + "@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/traverse": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz", + "integrity": "sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.0", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.0", + "@babel/types": "^7.13.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.0.tgz", + "integrity": "sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@rollup/plugin-buble": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-buble/-/plugin-buble-0.21.3.tgz", + "integrity": "sha512-Iv8cCuFPnMdqV4pcyU+OrfjOfagPArRQ1PyQjx5KgHk3dARedI+8PNTLSMpJts0lQJr8yF2pAU4GxpxCBJ9HYw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.0.8", + "@types/buble": "^0.19.2", + "buble": "^0.20.0" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "@types/buble": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@types/buble/-/buble-0.19.2.tgz", + "integrity": "sha512-uUD8zIfXMKThmFkahTXDGI3CthFH1kMg2dOm3KLi4GlC5cbARA64bEcUMbbWdWdE73eoc/iBB9PiTMqH0dNS2Q==", + "dev": true, + "requires": { + "magic-string": "^0.25.0" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, + "browserslist": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", + "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001181", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.649", + "escalade": "^3.1.1", + "node-releases": "^1.1.70" + } + }, + "buble": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/buble/-/buble-0.20.0.tgz", + "integrity": "sha512-/1gnaMQE8xvd5qsNBl+iTuyjJ9XxeaVxAMF86dQ4EyxFJOZtsgOS8Ra+7WHgZTam5IFDtt4BguN0sH0tVTKrOw==", + "dev": true, + "requires": { + "acorn": "^6.4.1", + "acorn-dynamic-import": "^4.0.0", + "acorn-jsx": "^5.2.0", + "chalk": "^2.4.2", + "magic-string": "^0.25.7", + "minimist": "^1.2.5", + "regexpu-core": "4.5.4" + } + }, + "caniuse-lite": { + "version": "1.0.30001203", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001203.tgz", + "integrity": "sha512-/I9tvnzU/PHMH7wBPrfDMSuecDeUKerjCPX7D0xBbaJZPxoT9m+yYxt0zCTkcijCkjTdim3H56Zm0i5Adxch4w==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "electron-to-chromium": { + "version": "1.3.693", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.693.tgz", + "integrity": "sha512-vUdsE8yyeu30RecppQtI+XTz2++LWLVEIYmzeCaCRLSdtKZ2eXqdJcrs85KwLiPOPVc6PELgWyXBsfqIvzGZag==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node-releases": { + "version": "1.1.71", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", + "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regexpu-core": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.0.2", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.7.tgz", + "integrity": "sha512-ib77G0uxsA2ovgiYbCVGx4Pv3PSttAx2vIwidqQzbL2U5S4Q+j00HdSAneSBuyVcMvEnTXMjiGgB+DlXozVhpQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "rollup": { + "version": "2.42.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.42.1.tgz", + "integrity": "sha512-/y7M2ULg06JOXmMpPzhTeQroJSchy8lX8q6qrjqil0jmLz6ejCWbQzVnWTsdmMQRhfU0QcwtiW8iZlmrGXWV4g==", + "dev": true, + "requires": { + "fsevents": "~2.3.1" + } + }, + "rollup-plugin-babel": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz", + "integrity": "sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-banner": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-banner/-/rollup-plugin-banner-0.2.1.tgz", + "integrity": "sha512-Bs1uIPCsGpKIkNOwmBsCqn+dJ/xaojWk9PNlvd+1MEScddr1yUQlO6McAXi72wJyNWYL+9u9EI2JAZMpLRH92w==", + "dev": true, + "requires": { + "lodash.template": "^4.4.0" + } + }, + "rollup-plugin-uglify": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/rollup-plugin-uglify/-/rollup-plugin-uglify-6.0.4.tgz", + "integrity": "sha512-ddgqkH02klveu34TF0JqygPwZnsbhHVI6t8+hGTcYHngPkQb5MIHI0XiztXIN/d6V9j+efwHAqEL7LspSxQXGw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "jest-worker": "^24.0.0", + "serialize-javascript": "^2.1.2", + "uglify-js": "^3.4.9" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "uglify-js": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.1.tgz", + "integrity": "sha512-EWhx3fHy3M9JbaeTnO+rEqzCe1wtyQClv6q3YWq0voOj4E+bMZBErVS1GAHPDiRGONYq34M1/d8KuQMgvi6Gjw==", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "vue": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz", + "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==" + }, + "vue-axios": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vue-axios/-/vue-axios-2.1.5.tgz", + "integrity": "sha512-th5xVbInVoyIoe+qY+9GCflEVezxAvztD4xpFF39SRQYqpoKD2qkmX8yv08jJG9a2SgNOCjirjJGSwg/wTrbmA==" + } + } +} diff --git a/package.json b/package.json index bb767fe..c727176 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,25 @@ { "name": "vue-authenticate", - "version": "1.3.5-beta.1", + "version": "1.5.0", "description": "Authentication library for Vue.js", - "main": "dist/vue-authenticate.js", - "module": "dist/vue-authenticate.es2015.js", + "main": "dist/vue-authenticate.common.js", + "module": "dist/vue-authenticate.esm.js", "unpkg": "dist/vue-authenticate.js", "scripts": { - "dev": "parallelshell \"node-dev ./example/server.js\" \"gulp dev\"", - "build": "node build/build.js && cp ./dist/vue-authenticate.js ./example/" + "build": "node build/build.rollup.js" }, "keywords": [ "vue", + "vue.js", "vuejs", - "auth" + "json", + "jwt", + "token", + "auth", + "authentication", + "oauth", + "oauth1", + "oauth2" ], "author": { "name": "Davor Grubelic", @@ -23,42 +30,22 @@ "type": "git", "url": "https://github.com/dgrubelic/vue-authenticate.git" }, + "files": [ + "dist" + ], "license": "MIT", "devDependencies": { - "axios": "^0.17.1", - "babel-core": "^6.24.0", - "babel-loader": "^6.4.1", - "babel-plugin-external-helpers": "^6.22.0", - "babel-preset-es2015": "^6.24.1", - "babel-preset-es2015-rollup": "^3.0.0", - "body-parser": "^1.17.1", - "connect-history-api-fallback": "^1.3.0", - "cors": "^2.8.1", - "express": "^4.15.2", - "gulp": "^3.9.1", - "gulp-connect": "^5.0.0", - "gulp-webpack": "^1.5.0", - "node-dev": "^3.1.3", - "oauth": "^0.9.15", - "oauth-signature": "^1.3.1", - "parallelshell": "^2.0.0", - "request": "^2.81.0", - "rollup": "^0.41.6", - "rollup-plugin-babel": "^2.7.1", - "rollup-plugin-buble": "^0.15.0", - "rollup-plugin-commonjs": "^8.0.2", - "rollup-plugin-node-resolve": "^3.0.0", - "rollup-plugin-uglify": "^1.0.1", - "rollup-stream": "^1.19.0", - "uglify-js": "^2.8.22", - "unix-timestamp": "^0.2.0", - "vinyl-source-stream": "^1.1.0", - "vue-axios": "^2.0.2", - "vue-router": "^2.3.0", - "vuex": "^2.2.1", - "webpack": "^2.3.2", - "webpack-dev-server": "^2.4.2" + "@babel/core": "^7.9.0", + "@rollup/plugin-buble": "^0.21.3", + "acorn": "^6.1.1", + "ajv": "^6.10.0", + "rollup": "^2.6.1", + "rollup-plugin-babel": "^4.4.0", + "rollup-plugin-banner": "^0.2.1", + "rollup-plugin-uglify": "^6.0.4", + "uglify-js": "^3.9.1" }, + "peerDependencies": {}, "tags": [ "auth", "authentication", @@ -75,5 +62,10 @@ "oauth", "oauth 1.0", "oauth 2.0" - ] + ], + "dependencies": { + "axios": "^0.18.0", + "vue": "^2.6.10", + "vue-axios": "^2.1.4" + } } diff --git a/src/authenticate.js b/src/authenticate.js index ba079aa..1482688 100644 --- a/src/authenticate.js +++ b/src/authenticate.js @@ -1,51 +1,63 @@ -import Promise from './promise.js' -import { objectExtend, isString, isObject, isFunction, joinUrl, decodeBase64 } from './utils.js' -import defaultOptions from './options.js' -import StorageFactory from './storage.js' -import OAuth1 from './oauth/oauth1.js' -import OAuth2 from './oauth/oauth2.js' +import Promise from './promise.js'; +import { $window } from './globals.js'; +import { + objectExtend, + isString, + isObject, + isFunction, + joinUrl, + decodeBase64, + getObjectProperty, +} from './utils.js'; +import defaultOptions from './options.js'; +import StorageFactory from './storage.js'; +import OAuth1 from './oauth/oauth1.js'; +import OAuth2 from './oauth/oauth2.js'; export default class VueAuthenticate { constructor($http, overrideOptions) { - let options = objectExtend({}, defaultOptions) - options = objectExtend(options, overrideOptions) - let storage = StorageFactory(options) + let options = objectExtend({}, defaultOptions); + options = objectExtend(options, overrideOptions); + let storage = StorageFactory(options); Object.defineProperties(this, { $http: { get() { - return $http - } + return $http; + }, }, options: { get() { - return options - } + return options; + }, }, storage: { get() { - return storage - } + return storage; + }, }, tokenName: { get() { if (this.options.tokenPrefix) { - return [this.options.tokenPrefix, this.options.tokenName].join('_') + return [this.options.tokenPrefix, this.options.tokenName].join('_'); } else { - return this.options.tokenName + return this.options.tokenName; } - } - } - }) + }, + }, + }); // Setup request interceptors - if (this.options.bindRequestInterceptor && isFunction(this.options.bindRequestInterceptor)) { - this.options.bindRequestInterceptor.call(this, this) + if ( + this.options.bindRequestInterceptor && + isFunction(this.options.bindRequestInterceptor) + ) { + this.options.bindRequestInterceptor.call(this, this); } else { - throw new Error('Request interceptor must be functions') + throw new Error('Request interceptor must be functions'); } } @@ -56,24 +68,28 @@ export default class VueAuthenticate { * @return {Boolean} */ isAuthenticated() { - let token = this.storage.getItem(this.tokenName) + let token = this.storage.getItem(this.tokenName); - if (token) { // Token is present - if (token.split('.').length === 3) { // Token with a valid JWT format XXX.YYY.ZZZ - try { // Could be a valid JWT or an access token with the same format + if (token) { + // Token is present + if (token.split('.').length === 3) { + // Token with a valid JWT format XXX.YYY.ZZZ + try { + // Could be a valid JWT or an access token with the same format const base64Url = token.split('.')[1]; const base64 = base64Url.replace('-', '+').replace('_', '/'); - const exp = JSON.parse(window.atob(base64)).exp; - if (typeof exp === 'number') { // JWT with an optonal expiration claims + const exp = JSON.parse($window.atob(base64)).exp; + if (typeof exp === 'number') { + // JWT with an optonal expiration claims return Math.round(new Date().getTime() / 1000) < exp; } } catch (e) { - return true; // Pass: Non-JWT token that looks like JWT + return true; // Pass: Non-JWT token that looks like JWT } } - return true; // Pass: All other tokens + return true; // Pass: All other tokens } - return false + return false; } /** @@ -81,33 +97,23 @@ export default class VueAuthenticate { * @return {String} Authentication token */ getToken() { - return this.storage.getItem(this.tokenName) + return this.storage.getItem(this.tokenName); } /** * Set new authentication token * @param {String|Object} token */ - setToken(response) { + setToken(response, tokenPath) { if (response[this.options.responseDataKey]) { response = response[this.options.responseDataKey]; } - - let token; - if (response.access_token) { - if (isObject(response.access_token) && isObject(response.access_token[this.options.responseDataKey])) { - response = response.access_token - } else if (isString(response.access_token)) { - token = response.access_token - } - } - if (!token && response) { - token = response[this.options.tokenName] - } + const responseTokenPath = tokenPath || this.options.tokenPath; + const token = getObjectProperty(response, responseTokenPath); if (token) { - this.storage.setItem(this.tokenName, token) + this.storage.setItem(this.tokenName, token); } } @@ -122,7 +128,7 @@ export default class VueAuthenticate { } catch (e) {} } } - + /** * Login user using email and password * @param {Object} user User data @@ -130,16 +136,20 @@ export default class VueAuthenticate { * @return {Promise} Request promise */ login(user, requestOptions) { - requestOptions = requestOptions || {} - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.loginUrl) - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey] - requestOptions.method = requestOptions.method || 'POST' - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials - - return this.$http(requestOptions).then((response) => { - this.setToken(response) - return response - }) + requestOptions = requestOptions || {}; + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.loginUrl); + requestOptions[this.options.requestDataKey] = + user || requestOptions[this.options.requestDataKey]; + requestOptions.method = requestOptions.method || 'POST'; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; + + return this.$http(requestOptions).then(response => { + this.setToken(response); + return response; + }); } /** @@ -149,16 +159,20 @@ export default class VueAuthenticate { * @return {Promise} Request promise */ register(user, requestOptions) { - requestOptions = requestOptions || {} - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.registerUrl) - requestOptions[this.options.requestDataKey] = user || requestOptions[this.options.requestDataKey] - requestOptions.method = requestOptions.method || 'POST' - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials - - return this.$http(requestOptions).then((response) => { - this.setToken(response) - return response - }) + requestOptions = requestOptions || {}; + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.registerUrl); + requestOptions[this.options.requestDataKey] = + user || requestOptions[this.options.requestDataKey]; + requestOptions.method = requestOptions.method || 'POST'; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; + + return this.$http(requestOptions).then(response => { + this.setToken(response); + return response; + }); } /** @@ -168,63 +182,130 @@ export default class VueAuthenticate { */ logout(requestOptions) { if (!this.isAuthenticated()) { - return Promise.reject(new Error('There is no currently authenticated user')) + return Promise.reject( + new Error('There is no currently authenticated user') + ); } - requestOptions = requestOptions || {} + requestOptions = requestOptions || {}; - if (requestOptions.url) { - requestOptions.url = requestOptions.url ? requestOptions.url : joinUrl(this.options.baseUrl, this.options.logoutUrl) - requestOptions.method = requestOptions.method || 'POST' - requestOptions[this.options.requestDataKey] = requestOptions[this.options.requestDataKey] || undefined - requestOptions.withCredentials = requestOptions.withCredentials || this.options.withCredentials + if (requestOptions.url || this.options.logoutUrl) { + requestOptions.url = requestOptions.url + ? requestOptions.url + : joinUrl(this.options.baseUrl, this.options.logoutUrl); + requestOptions.method = requestOptions.method || 'POST'; + requestOptions[this.options.requestDataKey] = + requestOptions[this.options.requestDataKey] || undefined; + requestOptions.withCredentials = + requestOptions.withCredentials || this.options.withCredentials; - return this.$http(requestOptions).then((response) => { - this.storage.removeItem(this.tokenName) - }) + return this.$http(requestOptions).then(response => { + this.storage.removeItem(this.tokenName); + return response; + }); } else { - this.storage.removeItem(this.tokenName) + this.storage.removeItem(this.tokenName); return Promise.resolve(); } } /** * Authenticate user using authentication provider - * + * * @param {String} provider Provider name * @param {Object} userData User data - * @param {Object} requestOptions Request options * @return {Promise} Request promise */ - authenticate(provider, userData, requestOptions) { + authenticate(provider, userData) { return new Promise((resolve, reject) => { - var providerConfig = this.options.providers[provider] + var providerConfig = this.options.providers[provider]; if (!providerConfig) { - return reject(new Error('Unknown provider')) + return reject(new Error('Unknown provider')); } let providerInstance; switch (providerConfig.oauthType) { case '1.0': - providerInstance = new OAuth1(this.$http, this.storage, providerConfig, this.options) - break + providerInstance = new OAuth1( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; case '2.0': - providerInstance = new OAuth2(this.$http, this.storage, providerConfig, this.options) - break + providerInstance = new OAuth2( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; default: - return reject(new Error('Invalid OAuth type')) - break + return reject(new Error('Invalid OAuth type')); } - return providerInstance.init(userData).then((response) => { - this.setToken(response) + return providerInstance + .init(userData) + .then(response => { + this.setToken(response, providerConfig.tokenPath); - if (this.isAuthenticated()) { - return resolve(response) - } else { - return reject(new Error('Authentication failed')) - } - }).catch(err => reject(err)) - }) + if (this.isAuthenticated()) { + return resolve(response); + } else { + return reject(new Error('Authentication failed')); + } + }) + .catch(err => reject(err)); + }); + } + + /** + * Link user using authentication provider without login + * + * @param {String} provider Provider name + * @param {Object} userData User data + * @return {Promise} Request promise + */ + link(provider, userData) { + return new Promise((resolve, reject) => { + var providerConfig = this.options.providers[provider]; + if (!providerConfig) { + return reject(new Error('Unknown provider')); + } + + let providerInstance; + switch (providerConfig.oauthType) { + case '1.0': + providerInstance = new OAuth1( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + case '2.0': + providerInstance = new OAuth2( + this.$http, + this.storage, + providerConfig, + this.options + ); + break; + default: + return reject(new Error('Invalid OAuth type')); + } + + return providerInstance + .init(userData) + .then(response => { + if (response[this.options.responseDataKey]) { + response = response[this.options.responseDataKey]; + } + + resolve(response); + }) + .catch(reject); + }); } } diff --git a/src/globals.js b/src/globals.js new file mode 100644 index 0000000..00891fd --- /dev/null +++ b/src/globals.js @@ -0,0 +1,27 @@ +const fakeDocument = { + createElement() { }, +}; + +const fakeWindow = { + atob() { }, + open() { }, + location: {}, + localStorage: { + setItem() { }, + getItem() { }, + removeItem() { }, + }, + sessionStorage: { + setItem() { }, + getItem() { }, + removeItem() { }, + }, +}; + +export const $document = (typeof document !== undefined) + ? document + : fakeDocument; + +export const $window = (typeof window !== undefined) + ? window + : fakeWindow; diff --git a/src/index.js b/src/index.js index ba6bca6..2775c6b 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,5 @@ -import './utils.js' -import Promise from './promise.js' -import VueAuthenticate from './authenticate.js' +import './utils.js'; +import VueAuthenticate from './authenticate.js'; /** * VueAuthenticate plugin @@ -9,9 +8,10 @@ import VueAuthenticate from './authenticate.js' */ function plugin(Vue, options) { if (plugin.installed) { - return + return; } - plugin.installed = true + + plugin.installed = true; let vueAuthInstance = null; Object.defineProperties(Vue.prototype, { @@ -20,15 +20,15 @@ function plugin(Vue, options) { if (!vueAuthInstance) { // Request handler library not found, throw error if (!this.$http) { - throw new Error('Request handler instance not found') + throw new Error('Request handler instance not found'); } - vueAuthInstance = new VueAuthenticate(this.$http, options) + vueAuthInstance = new VueAuthenticate(this.$http, options); } - return vueAuthInstance - } - } - }) + return vueAuthInstance; + }, + }, + }); } /** @@ -38,7 +38,7 @@ function plugin(Vue, options) { * @return {VueAuthenticate} VueAuthenticate instance */ plugin.factory = function ($http, options) { - return new VueAuthenticate($http, options) -} + return new VueAuthenticate($http, options); +}; -export default plugin +export default plugin; diff --git a/src/oauth/oauth1.js b/src/oauth/oauth1.js index 3014b86..dfd5fff 100644 --- a/src/oauth/oauth1.js +++ b/src/oauth/oauth1.js @@ -1,5 +1,12 @@ -import OAuthPopup from './popup.js' -import { objectExtend, isString, isObject, isFunction, joinUrl } from '../utils.js' +import OAuthPopup from './popup.js'; +import { $window } from '../globals.js'; +import { + objectExtend, + isString, + isObject, + isFunction, + joinUrl, +} from '../utils.js'; const defaultProviderConfig = { name: null, @@ -12,35 +19,39 @@ const defaultProviderConfig = { requiredUrlParams: null, defaultUrlParams: null, oauthType: '1.0', - popupOptions: {} -} + popupOptions: {}, +}; export default class OAuth { constructor($http, storage, providerConfig, options) { - this.$http = $http - this.storage = storage - this.providerConfig = objectExtend({}, defaultProviderConfig) - this.providerConfig = objectExtend(this.providerConfig, providerConfig) - this.options = options + this.$http = $http; + this.storage = storage; + this.providerConfig = objectExtend({}, defaultProviderConfig); + this.providerConfig = objectExtend(this.providerConfig, providerConfig); + this.options = options; } /** - * Initialize OAuth1 process + * Initialize OAuth1 process * @param {Object} userData User data * @return {Promise} */ init(userData) { - this.oauthPopup = new OAuthPopup('about:blank', this.providerConfig.name, this.providerConfig.popupOptions) + this.oauthPopup = new OAuthPopup( + 'about:blank', + this.providerConfig.name, + this.providerConfig.popupOptions + ); - if (window && !window['cordova']) { - this.oauthPopup.open(this.providerConfig.redirectUri, true) + if (!$window['cordova']) { + this.oauthPopup.open(this.providerConfig.redirectUri, true); } - return this.getRequestToken().then((response) => { - return this.openPopup(response).then((popupResponse) => { - return this.exchangeForToken(popupResponse, userData) - }) - }) + return this.getRequestToken().then(response => { + return this.openPopup(response).then(popupResponse => { + return this.exchangeForToken(popupResponse, userData); + }); + }); } /** @@ -48,17 +59,23 @@ export default class OAuth { * @return {Promise} */ getRequestToken() { - let requestOptions = {} - requestOptions.method = 'POST' - requestOptions[this.options.requestDataKey] = objectExtend({}, this.providerConfig) - requestOptions.withCredentials = this.options.withCredentials + let requestOptions = {}; + requestOptions.method = 'POST'; + requestOptions[this.options.requestDataKey] = objectExtend( + {}, + this.providerConfig + ); + requestOptions.withCredentials = this.options.withCredentials; if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url) + requestOptions.url = joinUrl( + this.options.baseUrl, + this.providerConfig.url + ); } else { - requestOptions.url = this.providerConfig.url + requestOptions.url = this.providerConfig.url; } - return this.$http(requestOptions) + return this.$http(requestOptions); } /** @@ -67,13 +84,16 @@ export default class OAuth { * @return {Promise} */ openPopup(response) { - const url = [this.providerConfig.authorizationEndpoint, this.buildQueryString(response[this.options.responseDataKey])].join('?'); + const url = [ + this.providerConfig.authorizationEndpoint, + this.buildQueryString(response[this.options.responseDataKey]), + ].join('?'); - this.oauthPopup.popup.location = url - if (window && window['cordova']) { - return this.oauthPopup.open(this.providerConfig.redirectUri) + this.oauthPopup.popup.location = url; + if ($window['cordova']) { + return this.oauthPopup.open(this.providerConfig.redirectUri); } else { - return this.oauthPopup.pooling(this.providerConfig.redirectUri) + return this.oauthPopup.pooling(this.providerConfig.redirectUri); } } @@ -84,26 +104,31 @@ export default class OAuth { * @return {Promise} */ exchangeForToken(oauth, userData) { - let payload = objectExtend({}, userData) - payload = objectExtend(payload, oauth) - let requestOptions = {} - requestOptions.method = 'POST' - requestOptions[this.options.requestDataKey] = payload - requestOptions.withCredentials = this.options.withCredentials + let payload = objectExtend({}, userData); + payload = objectExtend(payload, oauth); + let requestOptions = {}; + requestOptions.method = 'POST'; + requestOptions[this.options.requestDataKey] = payload; + requestOptions.withCredentials = this.options.withCredentials; if (this.options.baseUrl) { - requestOptions.url = joinUrl(this.options.baseUrl, this.providerConfig.url) + requestOptions.url = joinUrl( + this.options.baseUrl, + this.providerConfig.url + ); } else { - requestOptions.url = this.providerConfig.url + requestOptions.url = this.providerConfig.url; } - return this.$http(requestOptions) + return this.$http(requestOptions); } buildQueryString(params) { const parsedParams = []; for (var key in params) { - let value = params[key] - parsedParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); + let value = params[key]; + parsedParams.push( + encodeURIComponent(key) + '=' + encodeURIComponent(value) + ); } return parsedParams.join('&'); } -} \ No newline at end of file +} diff --git a/src/oauth/oauth2.js b/src/oauth/oauth2.js index f527ad1..294c958 100644 --- a/src/oauth/oauth2.js +++ b/src/oauth/oauth2.js @@ -1,5 +1,11 @@ -import OAuthPopup from './popup.js' -import { camelCase, isFunction, isString, objectExtend, joinUrl } from '../utils.js' +import OAuthPopup from './popup.js'; +import { + camelCase, + isFunction, + isString, + objectExtend, + joinUrl, +} from '../utils.js'; /** * Default provider configuration @@ -21,116 +27,142 @@ const defaultProviderConfig = { responseParams: { code: 'code', clientId: 'clientId', - redirectUri: 'redirectUri' + redirectUri: 'redirectUri', }, oauthType: '2.0', - popupOptions: {} -} + popupOptions: {}, +}; export default class OAuth2 { constructor($http, storage, providerConfig, options) { - this.$http = $http - this.storage = storage - this.providerConfig = objectExtend({}, defaultProviderConfig) - this.providerConfig = objectExtend(this.providerConfig, providerConfig) - this.options = options + this.$http = $http; + this.storage = storage; + this.providerConfig = objectExtend({}, defaultProviderConfig); + this.providerConfig = objectExtend(this.providerConfig, providerConfig); + this.options = options; } init(userData) { let stateName = this.providerConfig.name + '_state'; if (isFunction(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state()) + this.storage.setItem(stateName, this.providerConfig.state()); } else if (isString(this.providerConfig.state)) { - this.storage.setItem(stateName, this.providerConfig.state) + this.storage.setItem(stateName, this.providerConfig.state); } - let url = [this.providerConfig.authorizationEndpoint, this._stringifyRequestParams()].join('?') + let url = [ + this.providerConfig.authorizationEndpoint, + this._stringifyRequestParams(), + ].join('?'); + + this.oauthPopup = new OAuthPopup( + url, + this.providerConfig.name, + this.providerConfig.popupOptions + ); - this.oauthPopup = new OAuthPopup(url, this.providerConfig.name, this.providerConfig.popupOptions) - return new Promise((resolve, reject) => { - this.oauthPopup.open(this.providerConfig.redirectUri).then((response) => { - if (this.providerConfig.responseType === 'token' || !this.providerConfig.url) { - return resolve(response) - } + this.oauthPopup + .open(this.providerConfig.redirectUri) + .then(response => { + if ( + this.providerConfig.responseType === 'token' || + !this.providerConfig.url + ) { + return resolve(response); + } - if (response.state && response.state !== this.storage.getItem(stateName)) { - return reject(new Error('State parameter value does not match original OAuth request state value')) - } + if ( + response.state && + response.state !== this.storage.getItem(stateName) + ) { + return reject( + new Error( + 'State parameter value does not match original OAuth request state value' + ) + ); + } - resolve(this.exchangeForToken(response, userData)) - }).catch((err) => { - reject(err) - }) - }) + resolve(this.exchangeForToken(response, userData)); + }) + .catch(err => { + reject(err); + }); + }); } /** * Exchange temporary oauth data for access token * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {[type]} oauth [description] * @param {[type]} userData [description] * @return {[type]} [description] */ exchangeForToken(oauth, userData) { - let payload = objectExtend({}, userData) + let payload = objectExtend({}, userData); - for (let key in defaultProviderConfig.responseParams) { - let value = defaultProviderConfig[key] + for (let key in this.providerConfig.responseParams) { + let value = this.providerConfig.responseParams[key]; - switch(key) { + switch (key) { case 'code': - payload[key] = oauth.code - break + payload[key] = oauth.code; + break; case 'clientId': - payload[key] = this.providerConfig.clientId - break + payload[key] = this.providerConfig.clientId; + break; case 'redirectUri': - payload[key] = this.providerConfig.redirectUri - break + payload[key] = this.providerConfig.redirectUri; + break; default: - payload[key] = oauth[key] + payload[key] = oauth[key]; } } if (oauth.state) { - payload.state = oauth.state + payload.state = oauth.state; } - let exchangeTokenUrl + let exchangeTokenUrl; if (this.options.baseUrl) { - exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url) + exchangeTokenUrl = joinUrl(this.options.baseUrl, this.providerConfig.url); } else { - exchangeTokenUrl = this.providerConfig.url + exchangeTokenUrl = this.providerConfig.url; } return this.$http.post(exchangeTokenUrl, payload, { - withCredentials: this.options.withCredentials - }) + withCredentials: this.options.withCredentials, + }); } /** * Stringify oauth params * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @return {String} */ _stringifyRequestParams() { - let keyValuePairs = [] - let paramCategories = ['defaultUrlParams', 'requiredUrlParams', 'optionalUrlParams'] + let keyValuePairs = []; + let paramCategories = [ + 'defaultUrlParams', + 'requiredUrlParams', + 'optionalUrlParams', + ]; - paramCategories.forEach((categoryName) => { - if (!this.providerConfig[categoryName]) return - if (!Array.isArray(this.providerConfig[categoryName])) return + paramCategories.forEach(categoryName => { + if (!this.providerConfig[categoryName]) return; + if (!Array.isArray(this.providerConfig[categoryName])) return; - this.providerConfig[categoryName].forEach((paramName) => { - let camelCaseParamName = camelCase(paramName) - let paramValue = isFunction(this.providerConfig[paramName]) ? this.providerConfig[paramName]() : this.providerConfig[camelCaseParamName] + this.providerConfig[categoryName].forEach(paramName => { + let camelCaseParamName = camelCase(paramName); + let paramValue = isFunction(this.providerConfig[paramName]) + ? this.providerConfig[paramName]() + : this.providerConfig[camelCaseParamName]; - if (paramName === 'redirect_uri' && !paramValue) return + if (paramName === 'redirect_uri' && !paramValue) return; if (paramName === 'state') { let stateName = this.providerConfig.name + '_state'; @@ -139,16 +171,20 @@ export default class OAuth2 { if (paramName === 'scope' && Array.isArray(paramValue)) { paramValue = paramValue.join(this.providerConfig.scopeDelimiter); if (this.providerConfig.scopePrefix) { - paramValue = [this.providerConfig.scopePrefix, paramValue].join(this.providerConfig.scopeDelimiter); + paramValue = [this.providerConfig.scopePrefix, paramValue].join( + this.providerConfig.scopeDelimiter + ); } } - keyValuePairs.push([paramName, paramValue]) - }) - }) + keyValuePairs.push([paramName, paramValue]); + }); + }); - return keyValuePairs.map((param) => { - return param.join('=') - }).join('&') + return keyValuePairs + .map(param => { + return param.join('='); + }) + .join('&'); } -} \ No newline at end of file +} diff --git a/src/oauth/popup.js b/src/oauth/popup.js index e75fcf4..1c48bdd 100644 --- a/src/oauth/popup.js +++ b/src/oauth/popup.js @@ -1,60 +1,74 @@ -import Promise from '../promise.js' -import { objectExtend, parseQueryString, getFullUrlPath, isUndefined } from '../utils.js' +import Promise from '../promise.js'; +import { $document, $window } from '../globals.js'; +import { + objectExtend, + parseQueryString, + getFullUrlPath, + isUndefined, +} from '../utils.js'; /** * OAuth2 popup management class - * + * * @author Sahat Yalkabov - * @copyright Class mostly taken from https://github.com/sahat/satellizer + * @copyright Class mostly taken from https://github.com/sahat/satellizer * and adjusted to fit vue-authenticate library */ export default class OAuthPopup { constructor(url, name, popupOptions) { - this.popup = null - this.url = url - this.name = name - this.popupOptions = popupOptions + this.popup = null; + this.url = url; + this.name = name; + this.popupOptions = popupOptions; } open(redirectUri, skipPooling) { try { - this.popup = window.open(this.url, this.name, this._stringifyOptions()) + this.popup = $window.open(this.url, this.name, this._stringifyOptions()); if (this.popup && this.popup.focus) { - this.popup.focus() + this.popup.focus(); } if (skipPooling) { - return Promise.resolve() + return Promise.resolve(); } else { - return this.pooling(redirectUri) + return this.pooling(redirectUri); } - } catch(e) { - return Promise.reject(new Error('OAuth popup error occurred')) + } catch (e) { + return Promise.reject(new Error('OAuth popup error occurred')); } } pooling(redirectUri) { return new Promise((resolve, reject) => { - const redirectUriParser = document.createElement('a') - redirectUriParser.href = redirectUri - const redirectUriPath = getFullUrlPath(redirectUriParser) + const redirectUriParser = $document.createElement('a'); + redirectUriParser.href = redirectUri; + const redirectUriPath = getFullUrlPath(redirectUriParser); let poolingInterval = setInterval(() => { - if (!this.popup || this.popup.closed || this.popup.closed === undefined) { - clearInterval(poolingInterval) - poolingInterval = null - reject(new Error('Auth popup window closed')) + if ( + !this.popup || + this.popup.closed || + this.popup.closed === undefined + ) { + clearInterval(poolingInterval); + poolingInterval = null; + reject(new Error('Auth popup window closed')); } try { - const popupWindowPath = getFullUrlPath(this.popup.location) + const popupWindowPath = getFullUrlPath(this.popup.location); if (popupWindowPath === redirectUriPath) { if (this.popup.location.search || this.popup.location.hash) { - const query = parseQueryString(this.popup.location.search.substring(1).replace(/\/$/, '')); - const hash = parseQueryString(this.popup.location.hash.substring(1).replace(/[\/$]/, '')); + const query = parseQueryString( + this.popup.location.search.substring(1).replace(/\/$/, '') + ); + const hash = parseQueryString( + this.popup.location.hash.substring(1).replace(/[\/$]/, '') + ); let params = objectExtend({}, query); - params = objectExtend(params, hash) + params = objectExtend(params, hash); if (params.error) { reject(new Error(params.error)); @@ -62,27 +76,31 @@ export default class OAuthPopup { resolve(params); } } else { - reject(new Error('OAuth redirect has occurred but no query or hash parameters were found.')) + reject( + new Error( + 'OAuth redirect has occurred but no query or hash parameters were found.' + ) + ); } - clearInterval(poolingInterval) - poolingInterval = null - this.popup.close() + clearInterval(poolingInterval); + poolingInterval = null; + this.popup.close(); } - } catch(e) { + } catch (e) { // Ignore DOMException: Blocked a frame with origin from accessing a cross-origin frame. } - }, 250) - }) + }, 250); + }); } _stringifyOptions() { - let options = [] + let options = []; for (var optionKey in this.popupOptions) { if (!isUndefined(this.popupOptions[optionKey])) { - options.push(`${optionKey}=${this.popupOptions[optionKey]}`) + options.push(`${optionKey}=${this.popupOptions[optionKey]}`); } } - return options.join(',') + return options.join(','); } -} \ No newline at end of file +} diff --git a/src/options.js b/src/options.js index a5d34bb..f2ecd78 100644 --- a/src/options.js +++ b/src/options.js @@ -1,8 +1,9 @@ import { isUndefined } from './utils'; +import { $window } from './globals'; export function getCookieDomainUrl() { try { - return window.location.hostname + return $window.location.hostname; } catch (e) {} return ''; @@ -10,9 +11,9 @@ export function getCookieDomainUrl() { export function getRedirectUri(uri) { try { - return (!isUndefined(uri)) - ? `${window.location.origin}${uri}` - : window.location.origin + return !isUndefined(uri) + ? `${$window.location.origin}${uri}` + : $window.location.origin; } catch (e) {} return uri || null; @@ -23,6 +24,7 @@ export function getRedirectUri(uri) { */ export default { baseUrl: null, + tokenPath: 'access_token', tokenName: 'token', tokenPrefix: 'vueauth', tokenHeader: 'Authorization', @@ -35,7 +37,7 @@ export default { cookieStorage: { domain: getCookieDomainUrl(), path: '/', - secure: false + secure: false, }, requestDataKey: 'data', responseDataKey: 'data', @@ -47,30 +49,31 @@ export default { bindRequestInterceptor: function ($auth) { const tokenHeader = $auth.options.tokenHeader; - $auth.$http.interceptors.request.use((config) => { + $auth.$http.interceptors.request.use(config => { if ($auth.isAuthenticated()) { config.headers[tokenHeader] = [ - $auth.options.tokenType, $auth.getToken() - ].join(' ') + $auth.options.tokenType, + $auth.getToken(), + ].join(' '); } else { - delete config.headers[tokenHeader] + delete config.headers[tokenHeader]; } - return config - }) + return config; + }); }, providers: { facebook: { name: 'facebook', url: '/auth/facebook', - authorizationEndpoint: 'https://www.facebook.com/v2.5/dialog/oauth', + authorizationEndpoint: 'https://www.facebook.com/v10.0/dialog/oauth', redirectUri: getRedirectUri('/'), requiredUrlParams: ['display', 'scope'], scope: ['email'], scopeDelimiter: ',', display: 'popup', oauthType: '2.0', - popupOptions: { width: 580, height: 400 } + popupOptions: { width: 580, height: 400 }, }, google: { @@ -85,7 +88,7 @@ export default { scopeDelimiter: ' ', display: 'popup', oauthType: '2.0', - popupOptions: { width: 452, height: 633 } + popupOptions: { width: 452, height: 633 }, }, github: { @@ -97,7 +100,7 @@ export default { scope: ['user:email'], scopeDelimiter: ' ', oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } + popupOptions: { width: 1020, height: 618 }, }, instagram: { @@ -109,7 +112,7 @@ export default { scope: ['basic'], scopeDelimiter: '+', oauthType: '2.0', - popupOptions: { width: null, height: null } + popupOptions: { width: null, height: null }, }, twitter: { @@ -118,7 +121,7 @@ export default { authorizationEndpoint: 'https://api.twitter.com/oauth/authenticate', redirectUri: getRedirectUri(), oauthType: '1.0', - popupOptions: { width: 495, height: 645 } + popupOptions: { width: 495, height: 645 }, }, bitbucket: { @@ -130,7 +133,7 @@ export default { scope: ['email'], scopeDelimiter: ' ', oauthType: '2.0', - popupOptions: { width: 1020, height: 618 } + popupOptions: { width: 1020, height: 618 }, }, linkedin: { @@ -143,7 +146,7 @@ export default { scopeDelimiter: ' ', state: 'STATE', oauthType: '2.0', - popupOptions: { width: 527, height: 582 } + popupOptions: { width: 527, height: 582 }, }, live: { @@ -156,7 +159,7 @@ export default { scopeDelimiter: ' ', display: 'popup', oauthType: '2.0', - popupOptions: { width: 500, height: 560 } + popupOptions: { width: 500, height: 560 }, }, oauth1: { @@ -165,7 +168,7 @@ export default { authorizationEndpoint: null, redirectUri: getRedirectUri(), oauthType: '1.0', - popupOptions: null + popupOptions: null, }, oauth2: { @@ -187,8 +190,8 @@ export default { responseParams: { code: 'code', clientId: 'clientId', - redirectUri: 'redirectUri' - } - } - } -} + redirectUri: 'redirectUri', + }, + }, + }, +}; diff --git a/src/promise.js b/src/promise.js index 573452c..9b16e22 100644 --- a/src/promise.js +++ b/src/promise.js @@ -12,7 +12,8 @@ function bind(fn, thisArg) { } function Promise(fn) { - if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new'); + if (typeof this !== 'object') + throw new TypeError('Promises must be constructed via new'); if (typeof fn !== 'function') throw new TypeError('not a function'); this._state = 0; this._handled = false; @@ -51,8 +52,12 @@ function handle(self, deferred) { function resolve(self, newValue) { try { // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure - if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); - if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { + if (newValue === self) + throw new TypeError('A promise cannot be resolved with itself.'); + if ( + newValue && + (typeof newValue === 'object' || typeof newValue === 'function') + ) { var then = newValue.then; if (newValue instanceof Promise) { self._state = 3; @@ -80,7 +85,7 @@ function reject(self, newValue) { function finale(self) { if (self._state === 2 && self._deferreds.length === 0) { - Promise._immediateFn(function() { + Promise._immediateFn(function () { if (!self._handled) { Promise._unhandledRejectionFn(self._value); } @@ -108,15 +113,18 @@ function Handler(onFulfilled, onRejected, promise) { function doResolve(fn, self) { var done = false; try { - fn(function (value) { - if (done) return; - done = true; - resolve(self, value); - }, function (reason) { - if (done) return; - done = true; - reject(self, reason); - }); + fn( + function (value) { + if (done) return; + done = true; + resolve(self, value); + }, + function (reason) { + if (done) return; + done = true; + reject(self, reason); + } + ); } catch (ex) { if (done) return; done = true; @@ -129,7 +137,7 @@ Promise.prototype['catch'] = function (onRejected) { }; Promise.prototype.then = function (onFulfilled, onRejected) { - var prom = new (this.constructor)(noop); + var prom = new this.constructor(noop); handle(this, new Handler(onFulfilled, onRejected, prom)); return prom; @@ -147,9 +155,13 @@ Promise.all = function (arr) { if (val && (typeof val === 'object' || typeof val === 'function')) { var then = val.then; if (typeof then === 'function') { - then.call(val, function (val) { - res(i, val); - }, reject); + then.call( + val, + function (val) { + res(i, val); + }, + reject + ); return; } } @@ -193,7 +205,11 @@ Promise.race = function (values) { }; // Use polyfill for setImmediate for performance gains -Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) || +Promise._immediateFn = + (typeof setImmediate === 'function' && + function (fn) { + setImmediate(fn); + }) || function (fn) { setTimeoutFunc(fn, 0); }; @@ -222,4 +238,4 @@ Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { Promise._unhandledRejectionFn = fn; }; -export default Promise; \ No newline at end of file +export default Promise; diff --git a/src/storage.js b/src/storage.js index 7d873ec..b114e3f 100644 --- a/src/storage.js +++ b/src/storage.js @@ -1,30 +1,31 @@ +import { $window } from './globals'; import CookieStorage from './storage/cookie-storage.js'; -import LocalStorage from './storage/local-storage.js' -import MemoryStorage from './storage/memory-storage.js' -import SessionStorage from './storage/session-storage.js' +import LocalStorage from './storage/local-storage.js'; +import MemoryStorage from './storage/memory-storage.js'; +import SessionStorage from './storage/session-storage.js'; export default function StorageFactory(options) { switch (options.storageType) { case 'localStorage': try { - window.localStorage.setItem('testKey', 'test') - window.localStorage.removeItem('testKey') - return new LocalStorage(options.storageNamespace) - } catch(e) {} + $window.localStorage.setItem('testKey', 'test'); + $window.localStorage.removeItem('testKey'); + return new LocalStorage(options.storageNamespace); + } catch (e) {} case 'sessionStorage': try { - window.sessionStorage.setItem('testKey', 'test') - window.sessionStorage.removeItem('testKey') - return new SessionStorage(options.storageNamespace) + $window.sessionStorage.setItem('testKey', 'test'); + $window.sessionStorage.removeItem('testKey'); + return new SessionStorage(options.storageNamespace); } catch (e) {} - + case 'cookieStorage': return new CookieStorage(options.cookieStorage); - case 'memoryStorage': + case 'memoryStorage': default: - return new MemoryStorage(options.storageNamespace) + return new MemoryStorage(options.storageNamespace); break; } -} \ No newline at end of file +} diff --git a/src/storage/cookie-storage.js b/src/storage/cookie-storage.js index ca8257a..522c858 100644 --- a/src/storage/cookie-storage.js +++ b/src/storage/cookie-storage.js @@ -1,21 +1,18 @@ -import { - objectExtend, - formatCookie, - parseCookies -} from '../utils.js'; - -import { - getCookieDomainUrl -} from '../options.js'; +import { $document } from '../globals.js'; +import { objectExtend, formatCookie, parseCookies } from '../utils.js'; +import { getCookieDomainUrl } from '../options.js'; class CookieStorage { constructor(defaultOptions) { - this._defaultOptions = objectExtend({ - domain: getCookieDomainUrl(), - expires: null, - path: '/', - secure: false - }, defaultOptions); + this._defaultOptions = objectExtend( + { + domain: getCookieDomainUrl(), + expires: null, + path: '/', + secure: false, + }, + defaultOptions + ); } setItem(key, value) { @@ -33,7 +30,7 @@ class CookieStorage { const value = ''; const defaultOptions = objectExtend({}, this._defaultOptions); const options = objectExtend(defaultOptions, { - expires: new Date(0) + expires: new Date(0), }); const cookie = formatCookie(key, value, options); this._setCookie(cookie); @@ -41,19 +38,17 @@ class CookieStorage { _getCookie() { try { - return typeof document === 'undefined' - ? '' : typeof document.cookie === 'undefined' - ? '' : document.cookie; + return $document.cookie === 'undefined' ? '' : $document.cookie; } catch (e) {} - + return ''; } _setCookie(cookie) { try { - document.cookie = cookie; + $document.cookie = cookie; } catch (e) {} } } -export default CookieStorage \ No newline at end of file +export default CookieStorage; diff --git a/src/storage/local-storage.js b/src/storage/local-storage.js index efec8d6..82ffb9b 100644 --- a/src/storage/local-storage.js +++ b/src/storage/local-storage.js @@ -1,26 +1,28 @@ +import { $window } from '../globals.js'; + class LocalStorage { constructor(namespace) { - this.namespace = namespace || null + this.namespace = namespace || null; } setItem(key, value) { - window.localStorage.setItem(this._getStorageKey(key), value) + $window.localStorage.setItem(this._getStorageKey(key), value); } getItem(key) { - return window.localStorage.getItem(this._getStorageKey(key)) + return $window.localStorage.getItem(this._getStorageKey(key)); } removeItem(key) { - window.localStorage.removeItem(this._getStorageKey(key)) + $window.localStorage.removeItem(this._getStorageKey(key)); } _getStorageKey(key) { if (this.namespace) { - return [this.namespace, key].join('.') + return [this.namespace, key].join('.'); } return key; } } -export default LocalStorage \ No newline at end of file +export default LocalStorage; diff --git a/src/storage/memory-storage.js b/src/storage/memory-storage.js index 6b35600..e3d432b 100644 --- a/src/storage/memory-storage.js +++ b/src/storage/memory-storage.js @@ -1,27 +1,27 @@ class MemoryStorage { constructor(namespace) { - this.namespace = namespace || null - this._storage = {} + this.namespace = namespace || null; + this._storage = {}; } setItem(key, value) { - this._storage[this._getStorageKey(key)] = value + this._storage[this._getStorageKey(key)] = value; } getItem(key) { - return this._storage[this._getStorageKey(key)] + return this._storage[this._getStorageKey(key)]; } removeItem(key) { - delete this._storage[this._getStorageKey(key)] + delete this._storage[this._getStorageKey(key)]; } _getStorageKey(key) { if (this.namespace) { - return [this.namespace, key].join('.') + return [this.namespace, key].join('.'); } return key; } } -export default MemoryStorage \ No newline at end of file +export default MemoryStorage; diff --git a/src/storage/session-storage.js b/src/storage/session-storage.js index 71725ef..4836ef6 100644 --- a/src/storage/session-storage.js +++ b/src/storage/session-storage.js @@ -1,26 +1,28 @@ -class LocalStorage { +import { $window } from '../globals.js'; + +class SessionStorage { constructor(namespace) { - this.namespace = namespace || null + this.namespace = namespace || null; } setItem(key, value) { - window.sessionStorage.setItem(this._getStorageKey(key), value) + $window.sessionStorage.setItem(this._getStorageKey(key), value); } getItem(key) { - return window.sessionStorage.getItem(this._getStorageKey(key)) + return $window.sessionStorage.getItem(this._getStorageKey(key)); } removeItem(key) { - window.sessionStorage.removeItem(this._getStorageKey(key)) + $window.sessionStorage.removeItem(this._getStorageKey(key)); } _getStorageKey(key) { if (this.namespace) { - return [this.namespace, key].join('.') + return [this.namespace, key].join('.'); } return key; } } -export default LocalStorage \ No newline at end of file +export default SessionStorage; diff --git a/src/utils.js b/src/utils.js index 883999d..2732da8 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,5 @@ if (typeof Object.assign != 'function') { - Object.assign = function(target, varArgs) { + Object.assign = function (target, varArgs) { 'use strict'; if (target == null) { throw new TypeError('Cannot convert undefined or null to object'); @@ -10,7 +10,8 @@ if (typeof Object.assign != 'function') { for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; - if (nextSource != null) { // Skip over if undefined or null + if (nextSource != null) { + // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { @@ -24,37 +25,41 @@ if (typeof Object.assign != 'function') { } export function camelCase(name) { - return name.replace(/([\:\-\_]+(.))/g, function (_, separator, letter, offset) { + return name.replace(/([\:\-\_]+(.))/g, function ( + _, + separator, + letter, + offset + ) { return offset ? letter.toUpperCase() : letter; }); } export function isUndefined(value) { - return typeof value === 'undefined' + return typeof value === 'undefined'; } export function isDefined(value) { - return typeof value !== 'undefined' + return typeof value !== 'undefined'; } export function isObject(value) { - return value !== null && typeof value === 'object' + return value !== null && typeof value === 'object'; } export function isString(value) { - return typeof value === 'string' + return typeof value === 'string'; } export function isNumber(value) { - return typeof value === 'number' + return typeof value === 'number'; } export function isFunction(value) { - return typeof value === 'function' + return typeof value === 'function'; } export function objectExtend(a, b) { - // Don't touch 'null' or 'undefined' objects. if (a == null || b == null) { return a; @@ -73,14 +78,14 @@ export function objectExtend(a, b) { }); return a; -}; +} /** * Assemble url from two segments - * + * * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {String} baseUrl Base url * @param {String} url URI * @return {String} @@ -102,26 +107,33 @@ export function joinUrl(baseUrl, url) { /** * Get full path based on current location - * + * * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {Location} location * @return {String} */ export function getFullUrlPath(location) { const isHttps = location.protocol === 'https:'; - return location.protocol + '//' + location.hostname + - ':' + (location.port || (isHttps ? '443' : '80')) + - (/^\//.test(location.pathname) ? location.pathname : '/' + location.pathname); + return ( + location.protocol + + '//' + + location.hostname + + ':' + + (location.port || (isHttps ? '443' : '80')) + + (/^\//.test(location.pathname) + ? location.pathname + : '/' + location.pathname) + ); } /** * Parse query string variables - * + * * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {String} Query string * @return {String} */ @@ -129,11 +141,11 @@ export function parseQueryString(str) { let obj = {}; let key; let value; - (str || '').split('&').forEach((keyValue) => { + (str || '').split('&').forEach(keyValue => { if (keyValue) { value = keyValue.split('='); key = decodeURIComponent(value[0]); - obj[key] = (!!value[1]) ? decodeURIComponent(value[1]) : true; + obj[key] = !!value[1] ? decodeURIComponent(value[1]) : true; } }); return obj; @@ -143,7 +155,7 @@ export function parseQueryString(str) { * Decode base64 string * @author Sahat Yalkabov * @copyright Method taken from https://github.com/sahat/satellizer - * + * * @param {String} str base64 encoded string * @return {Object} */ @@ -159,32 +171,37 @@ export function decodeBase64(str) { let fromCharCode = String.fromCharCode; - let re_btou = new RegExp([ - '[\xC0-\xDF][\x80-\xBF]', - '[\xE0-\xEF][\x80-\xBF]{2}', - '[\xF0-\xF7][\x80-\xBF]{3}' - ].join('|'), 'g'); + let re_btou = new RegExp( + [ + '[\xC0-\xDF][\x80-\xBF]', + '[\xE0-\xEF][\x80-\xBF]{2}', + '[\xF0-\xF7][\x80-\xBF]{3}', + ].join('|'), + 'g' + ); let cb_btou = function (cccc) { switch (cccc.length) { case 4: - let cp = ((0x07 & cccc.charCodeAt(0)) << 18) - | ((0x3f & cccc.charCodeAt(1)) << 12) - | ((0x3f & cccc.charCodeAt(2)) << 6) - | (0x3f & cccc.charCodeAt(3)); + let cp = + ((0x07 & cccc.charCodeAt(0)) << 18) | + ((0x3f & cccc.charCodeAt(1)) << 12) | + ((0x3f & cccc.charCodeAt(2)) << 6) | + (0x3f & cccc.charCodeAt(3)); let offset = cp - 0x10000; - return (fromCharCode((offset >>> 10) + 0xD800) - + fromCharCode((offset & 0x3FF) + 0xDC00)); + return ( + fromCharCode((offset >>> 10) + 0xd800) + + fromCharCode((offset & 0x3ff) + 0xdc00) + ); case 3: return fromCharCode( - ((0x0f & cccc.charCodeAt(0)) << 12) - | ((0x3f & cccc.charCodeAt(1)) << 6) - | (0x3f & cccc.charCodeAt(2)) + ((0x0f & cccc.charCodeAt(0)) << 12) | + ((0x3f & cccc.charCodeAt(1)) << 6) | + (0x3f & cccc.charCodeAt(2)) ); default: return fromCharCode( - ((0x1f & cccc.charCodeAt(0)) << 6) - | (0x3f & cccc.charCodeAt(1)) + ((0x1f & cccc.charCodeAt(0)) << 6) | (0x3f & cccc.charCodeAt(1)) ); } }; @@ -193,54 +210,77 @@ export function decodeBase64(str) { return b.replace(re_btou, cb_btou); }; - let _decode = buffer ? function (a) { - return (a.constructor === buffer.constructor - ? a : new buffer(a, 'base64')).toString(); - } + let _decode = buffer + ? function (a) { + return (a.constructor === buffer.constructor + ? a + : new buffer(a, 'base64') + ).toString(); + } : function (a) { - return btou(atob(a)); - }; + return btou(atob(a)); + }; return _decode( - String(str).replace(/[-_]/g, function (m0) { - return m0 === '-' ? '+' : '/'; - }) + String(str) + .replace(/[-_]/g, function (m0) { + return m0 === '-' ? '+' : '/'; + }) .replace(/[^A-Za-z0-9\+\/]/g, '') ); } -export function parseCookies(str) { +export function parseCookies(str = '') { if (str.length === 0) return {}; const parsed = {}; const pattern = new RegExp('\\s*;\\s*'); - str.split(pattern).forEach((i) => { + str.split(pattern).forEach(i => { const [encodedKey, encodedValue] = i.split('='); const key = decodeURIComponent(encodedKey); const value = decodeURIComponent(encodedValue); parsed[key] = value; }); return parsed; -}; +} export function formatOptions(options) { const { path, domain, expires, secure } = options; return [ - typeof path === 'undefined' || path === null - ? '' : ';path=' + path, - typeof domain === 'undefined' || domain === null - ? '' : ';domain=' + domain, + typeof path === 'undefined' || path === null ? '' : ';path=' + path, + typeof domain === 'undefined' || domain === null ? '' : ';domain=' + domain, typeof expires === 'undefined' || expires === null - ? '' : ';expires=' + expires.toUTCString(), + ? '' + : ';expires=' + expires.toUTCString(), typeof secure === 'undefined' || secure === null || secure === false - ? '' : ';secure' + ? '' + : ';secure', ].join(''); -}; +} export function formatCookie(key, value, options) { return [ encodeURIComponent(key), '=', encodeURIComponent(value), - formatOptions(options) + formatOptions(options), ].join(''); -}; +} + +export function getObjectProperty(objectRef, propertyName) { + let value = undefined; + let valueRef = objectRef; + const propNames = propertyName.split('.'); + + for (var i = 0; i < propNames.length; i++) { + const key = propNames[i]; + value = valueRef[key]; + + if (isObject(value)) { + valueRef = valueRef[key]; + } else { + break; + } + } + + return value; +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..9266453 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,674 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + +"@babel/core@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" + integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helpers" "^7.9.0" + "@babel/parser" "^7.9.0" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.9.0", "@babel/generator@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" + integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== + dependencies: + "@babel/types" "^7.9.5" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-function-name@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" + integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.9.5" + +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" + integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-transforms@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" + integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.6" + "@babel/types" "^7.9.0" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-replace-supers@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" + integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/helper-simple-access@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" + integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" + integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== + +"@babel/helpers@^7.9.0": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" + integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + +"@babel/highlight@^7.8.3": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" + integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== + dependencies: + "@babel/helper-validator-identifier" "^7.9.0" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.8.6", "@babel/parser@^7.9.0": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" + integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== + +"@babel/template@^7.8.3", "@babel/template@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" + integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" + integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.5" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.9.0" + "@babel/types" "^7.9.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" + integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@rollup/plugin-buble@^0.21.3": + version "0.21.3" + resolved "https://registry.yarnpkg.com/@rollup/plugin-buble/-/plugin-buble-0.21.3.tgz#1649a915b1d051a4f430d40e7734a7f67a69b33e" + integrity sha512-Iv8cCuFPnMdqV4pcyU+OrfjOfagPArRQ1PyQjx5KgHk3dARedI+8PNTLSMpJts0lQJr8yF2pAU4GxpxCBJ9HYw== + dependencies: + "@rollup/pluginutils" "^3.0.8" + "@types/buble" "^0.19.2" + buble "^0.20.0" + +"@rollup/pluginutils@^3.0.8": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.0.9.tgz#aa6adca2c45e5a1b950103a999e3cddfe49fd775" + integrity sha512-TLZavlfPAZYI7v33wQh4mTP6zojne14yok3DNSLcjoG/Hirxfkonn6icP5rrNWRn8nZsirJBFFpijVOJzkUHDg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + micromatch "^4.0.2" + +"@types/buble@^0.19.2": + version "0.19.2" + resolved "https://registry.yarnpkg.com/@types/buble/-/buble-0.19.2.tgz#a4289d20b175b3c206aaad80caabdabe3ecdfdd1" + integrity sha512-uUD8zIfXMKThmFkahTXDGI3CthFH1kMg2dOm3KLi4GlC5cbARA64bEcUMbbWdWdE73eoc/iBB9PiTMqH0dNS2Q== + dependencies: + magic-string "^0.25.0" + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + +acorn-dynamic-import@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" + integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== + +acorn-jsx@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" + integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== + +acorn@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" + integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== + +acorn@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" + integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + +ajv@^6.10.0: + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +axios@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102" + integrity sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI= + dependencies: + follow-redirects "^1.3.0" + is-buffer "^1.1.5" + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +buble@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/buble/-/buble-0.20.0.tgz#a143979a8d968b7f76b57f38f2e7ce7cfe938d1f" + integrity sha512-/1gnaMQE8xvd5qsNBl+iTuyjJ9XxeaVxAMF86dQ4EyxFJOZtsgOS8Ra+7WHgZTam5IFDtt4BguN0sH0tVTKrOw== + dependencies: + acorn "^6.4.1" + acorn-dynamic-import "^4.0.0" + acorn-jsx "^5.2.0" + chalk "^2.4.2" + magic-string "^0.25.7" + minimist "^1.2.5" + regexpu-core "4.5.4" + +chalk@^2.0.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +estree-walker@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" + integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== + +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +follow-redirects@^1.3.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76" + integrity sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ== + dependencies: + debug "^3.2.6" + +fsevents@~2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +jest-worker@^24.0.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" + integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== + dependencies: + merge-stream "^2.0.0" + supports-color "^6.1.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash.template@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash@^4.17.13: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +magic-string@^0.25.0, magic-string@^0.25.7: + version "0.25.7" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" + integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== + dependencies: + sourcemap-codec "^1.4.4" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +picomatch@^2.0.5: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +regenerate-unicode-properties@^8.0.2: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regexpu-core@4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" + integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.0.2" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +regjsgen@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + +regjsparser@^0.6.0: + version "0.6.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" + integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== + dependencies: + jsesc "~0.5.0" + +resolve@^1.3.2: + version "1.16.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.16.1.tgz#49fac5d8bacf1fd53f200fa51247ae736175832c" + integrity sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig== + dependencies: + path-parse "^1.0.6" + +rollup-plugin-babel@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb" + integrity sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + rollup-pluginutils "^2.8.1" + +rollup-plugin-banner@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-banner/-/rollup-plugin-banner-0.2.1.tgz#f62f26c468530ecea16263da83175079625f9c6f" + integrity sha512-Bs1uIPCsGpKIkNOwmBsCqn+dJ/xaojWk9PNlvd+1MEScddr1yUQlO6McAXi72wJyNWYL+9u9EI2JAZMpLRH92w== + dependencies: + lodash.template "^4.4.0" + +rollup-plugin-uglify@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-6.0.4.tgz#65a0959d91586627f1e46a7db966fd504ec6c4e6" + integrity sha512-ddgqkH02klveu34TF0JqygPwZnsbhHVI6t8+hGTcYHngPkQb5MIHI0XiztXIN/d6V9j+efwHAqEL7LspSxQXGw== + dependencies: + "@babel/code-frame" "^7.0.0" + jest-worker "^24.0.0" + serialize-javascript "^2.1.2" + uglify-js "^3.4.9" + +rollup-pluginutils@^2.8.1: + version "2.8.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" + integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== + dependencies: + estree-walker "^0.6.1" + +rollup@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.6.1.tgz#8354e67caa7b8bf24c2488d9e2f64da2be62eebe" + integrity sha512-1RhFDRJeg027YjBO6+JxmVWkEZY0ASztHhoEUEWxOwkh4mjO58TFD6Uo7T7Y3FbmDpRTfKhM5NVxJyimCn0Elg== + optionalDependencies: + fsevents "~2.1.2" + +safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +semver@^5.4.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== + +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +sourcemap-codec@^1.4.4: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +uglify-js@^3.4.9, uglify-js@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.1.tgz#a56a71c8caa2d36b5556cc1fd57df01ae3491539" + integrity sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA== + dependencies: + commander "~2.20.3" + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +vue-axios@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/vue-axios/-/vue-axios-2.1.4.tgz#a9d298f7e876f9a87feb336b37adcbce34ff9f9f" + integrity sha512-DS8Q+WFT3i7nS0aZ/NMmTPf2yhbtlXhj4QEZmY69au/BshsGzGjC6dXaniZaPQlErP3J3Sv1HtQ4RVrXaUTkxA== + +vue@^2.6.10: + version "2.6.10" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637" + integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==