angular-aap-auth
Advanced tools
Comparing version 1.0.0-alpha.10 to 1.0.0-alpha.11
@@ -1,315 +0,698 @@ | ||
/** | ||
* Copyright 2017 EMBL - European Bioinformatics Institute | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
* this file except in compliance with the License. You may obtain a copy of the | ||
* License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed | ||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@auth0/angular-jwt'), require('rxjs'), require('rxjs/operators')) : | ||
typeof define === 'function' && define.amd ? define('angular-aap-auth', ['exports', '@angular/core', '@auth0/angular-jwt', 'rxjs', 'rxjs/operators'], factory) : | ||
(factory((global['angular-aap-auth'] = {}),global.ng.core,global.angularJwt,global.RxJS,global.Rx.Observable.prototype)); | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@auth0/angular-jwt'), require('rxjs'), require('rxjs/operators')) : | ||
typeof define === 'function' && define.amd ? define('angular-aap-auth', ['exports', '@angular/core', '@auth0/angular-jwt', 'rxjs', 'rxjs/operators'], factory) : | ||
(factory((global['angular-aap-auth'] = {}),global.ng.core,global.angularJwt,global.RxJS,global.rxjs.operators)); | ||
}(this, (function (exports,core,angularJwt,rxjs,operators) { 'use strict'; | ||
var TokenService = /** @class */ (function () { | ||
function TokenService(_jwt) { | ||
this._jwt = _jwt; | ||
} | ||
TokenService.prototype.getToken = function () { | ||
return this._jwt.tokenGetter(); | ||
}; | ||
TokenService.prototype.getTokenExpirationDate = function () { | ||
try { | ||
return this._jwt.getTokenExpirationDate(); | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
/** | ||
* The purpose of this very simple service is to interface between the | ||
* AuthService and the specific token manipulation routing of JwtHelperService. | ||
* In this way, if in the future we want to replace JwtHelperService by | ||
* another service, AuthService doesn't need to be modified, only this service. | ||
*/ | ||
var TokenService = (function () { | ||
function TokenService(_jwt) { | ||
this._jwt = _jwt; | ||
} | ||
catch (e) { | ||
return null; | ||
} | ||
}; | ||
TokenService.prototype.isTokenValid = function () { | ||
try { | ||
return !this._jwt.isTokenExpired(); | ||
} | ||
catch (error) { | ||
return false; | ||
} | ||
}; | ||
TokenService.prototype.getClaim = function (claim, defaultValue) { | ||
try { | ||
var value = (this._jwt.decodeToken()[claim]); | ||
if (value === undefined) { | ||
return defaultValue; | ||
} | ||
return value; | ||
} | ||
catch (e) { | ||
return defaultValue; | ||
} | ||
}; | ||
return TokenService; | ||
}()); | ||
TokenService.decorators = [ | ||
{ type: core.Injectable }, | ||
]; | ||
TokenService.ctorParameters = function () { return [ | ||
{ type: angularJwt.JwtHelperService, }, | ||
]; }; | ||
var AAP_CONFIG = new core.InjectionToken('AAP_CONFIG'); | ||
function getToken() { | ||
return localStorage.getItem('id_token') || ''; | ||
} | ||
function removeToken() { | ||
return localStorage.removeItem('id_token'); | ||
} | ||
function updateToken(newToken) { | ||
return localStorage.setItem('id_token', newToken); | ||
} | ||
var DEFAULT_CONF = { | ||
aapURL: 'https://api.aai.ebi.ac.uk', | ||
tokenGetter: getToken, | ||
tokenRemover: removeToken, | ||
tokenUpdater: updateToken | ||
}; | ||
var AuthService = /** @class */ (function () { | ||
function AuthService(_rendererFactory, _tokenService, config) { | ||
var _this = this; | ||
this._rendererFactory = _rendererFactory; | ||
this._tokenService = _tokenService; | ||
this.config = config; | ||
this._credentials = new rxjs.BehaviorSubject(null); | ||
this._loginCallbacks = []; | ||
this._logoutCallbacks = []; | ||
this._timeoutID = null; | ||
this._commKeyName = 'AngularAapAuthUpdated'; | ||
this._commKeyUpdater = function () { return localStorage.setItem(_this._commKeyName, '' + new Date().getTime()); }; | ||
this._domain = encodeURIComponent(window.location.origin); | ||
this._appURL = config.aapURL.replace(/\/$/, ''); | ||
this._storageUpdater = config.tokenUpdater; | ||
if (config.tokenRemover) { | ||
this._storageRemover = config.tokenRemover; | ||
} | ||
else { | ||
this._storageRemover = function () { return config.tokenUpdater(null); }; | ||
} | ||
var renderer = this._rendererFactory.createRenderer(null, null); | ||
this._listenLoginMessage(renderer); | ||
this._listenChangesFromOtherWindows(renderer); | ||
this._updateCredentials(); | ||
/** | ||
* @return {?} | ||
*/ | ||
TokenService.prototype.getToken = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._jwt.tokenGetter(); | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
TokenService.prototype.getTokenExpirationDate = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
try { | ||
return this._jwt.getTokenExpirationDate(); | ||
} | ||
catch (e) { | ||
return null; | ||
} | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
TokenService.prototype.isTokenValid = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
try { | ||
return !this._jwt.isTokenExpired(); | ||
} | ||
catch (error) { | ||
return false; | ||
} | ||
}; | ||
/** | ||
* Get claims from the token. | ||
* | ||
* @template T, C | ||
* @param {?} claim The name of the claim | ||
* @param {?} defaultValue The default value returned in case of error | ||
* | ||
* @return {?} claim or default value | ||
*/ | ||
TokenService.prototype.getClaim = /** | ||
* Get claims from the token. | ||
* | ||
* @template T, C | ||
* @param {?} claim The name of the claim | ||
* @param {?} defaultValue The default value returned in case of error | ||
* | ||
* @return {?} claim or default value | ||
*/ | ||
function (claim, defaultValue) { | ||
try { | ||
var /** @type {?} */ value = (this._jwt.decodeToken()[claim]); | ||
if (value === undefined) { | ||
return defaultValue; | ||
} | ||
return value; | ||
} | ||
catch (e) { | ||
return defaultValue; | ||
} | ||
}; | ||
TokenService.decorators = [ | ||
{ type: core.Injectable }, | ||
]; | ||
/** @nocollapse */ | ||
TokenService.ctorParameters = function () { | ||
return [ | ||
{ type: angularJwt.JwtHelperService } | ||
]; | ||
}; | ||
return TokenService; | ||
}()); | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
var /** @type {?} */ AAP_CONFIG = new core.InjectionToken('AAP_CONFIG'); | ||
/** | ||
* @return {?} | ||
*/ | ||
function getToken() { | ||
return localStorage.getItem('id_token') || ''; | ||
} | ||
AuthService.prototype.isAuthenticated = function () { | ||
return this._credentials.asObservable().pipe(operators.map(function (credentials) { return credentials ? true : false; })); | ||
/** | ||
* @return {?} | ||
*/ | ||
function removeToken() { | ||
return localStorage.removeItem('id_token'); | ||
} | ||
/** | ||
* @param {?} newToken | ||
* @return {?} | ||
*/ | ||
function updateToken(newToken) { | ||
return localStorage.setItem('id_token', newToken); | ||
} | ||
var /** @type {?} */ DEFAULT_CONF = { | ||
aapURL: 'https://api.aai.ebi.ac.uk', | ||
tokenGetter: getToken, | ||
tokenRemover: removeToken, | ||
tokenUpdater: updateToken | ||
}; | ||
AuthService.prototype.credentials = function () { | ||
return this._credentials.asObservable(); | ||
}; | ||
AuthService.prototype.realname = function () { | ||
return this._credentials.asObservable().pipe(operators.map(function (credentials) { return credentials ? credentials.realname : null; })); | ||
}; | ||
AuthService.prototype.username = function () { | ||
return this._credentials.asObservable().pipe(operators.map(function (credentials) { return credentials ? credentials.username : null; })); | ||
}; | ||
AuthService.prototype.token = function () { | ||
return this._credentials.asObservable().pipe(operators.map(function (credentials) { return credentials ? credentials.token : null; })); | ||
}; | ||
AuthService.prototype.windowOpen = function (loginOptions, width, height, top, left) { | ||
if (width === void 0) { width = 650; } | ||
if (height === void 0) { height = 1000; } | ||
if (top === void 0) { top = -1; } | ||
if (left === void 0) { left = -1; } | ||
if (left < 0) { | ||
var screenWidth = screen.width; | ||
if (screenWidth > width) { | ||
left = Math.round(screenWidth / 2 - width / 2); | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
var AuthService = (function () { | ||
function AuthService(_rendererFactory, _tokenService, config) { | ||
var _this = this; | ||
this._rendererFactory = _rendererFactory; | ||
this._tokenService = _tokenService; | ||
this.config = config; | ||
this._credentials = new rxjs.BehaviorSubject(null); | ||
this._loginCallbacks = []; | ||
this._logoutCallbacks = []; | ||
this._timeoutID = null; | ||
this._commKeyName = 'AngularAapAuthUpdated'; | ||
this._commKeyUpdater = function () { return localStorage.setItem(_this._commKeyName, '' + new Date().getTime()); }; | ||
this._domain = encodeURIComponent(window.location.origin); | ||
this._appURL = config.aapURL.replace(/\/$/, ''); | ||
this._storageUpdater = config.tokenUpdater; | ||
if (config.tokenRemover) { | ||
this._storageRemover = config.tokenRemover; | ||
} | ||
} | ||
if (top < 0) { | ||
var screenHeight = screen.height; | ||
if (screenHeight > height) { | ||
top = Math.round(screenHeight / 2 - height / 2); | ||
else { | ||
this._storageRemover = function () { return config.tokenUpdater(null); }; | ||
} | ||
var /** @type {?} */ renderer = this._rendererFactory.createRenderer(null, null); | ||
this._listenLoginMessage(renderer); | ||
this._listenChangesFromOtherWindows(renderer); | ||
this._updateCredentials(); // TODO: experiment with setTimeOut | ||
} | ||
var windowOptions = [ | ||
"width=" + width, | ||
"height=" + height, | ||
"left=" + left, | ||
"top=" + top, | ||
'personalbar=no', | ||
'toolbar=no', | ||
'scrollbars=yes', | ||
'resizable=yes', | ||
'directories=no', | ||
'location=no', | ||
'menubar=no', | ||
'titlebar=no', | ||
'toolbar=no' | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.isAuthenticated = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._credentials.asObservable().pipe(operators.map(function (credentials) { return credentials ? true : false; })); | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.credentials = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._credentials.asObservable(); | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.realname = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._credentials.asObservable().pipe(operators.map(function (credentials) { return credentials ? credentials.realname : null; })); | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.username = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._credentials.asObservable().pipe(operators.map(function (credentials) { return credentials ? credentials.username : null; })); | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.token = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._credentials.asObservable().pipe(operators.map(function (credentials) { return credentials ? credentials.token : null; })); | ||
}; | ||
/** | ||
* Functions that opens a window instead of a tab. | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} loginOptions Options passed as URL parameters to the SSO. | ||
* @param {?=} width Pixel width of the login window. | ||
* @param {?=} height Pixel height of the login window. | ||
* @param {?=} top Position of the top corners. If it is a negative | ||
* number it centres the login window on the screen. | ||
* @param {?=} left Position of the left corners. If it is a negative | ||
* number it centres the login window on the screen. | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.windowOpen = /** | ||
* Functions that opens a window instead of a tab. | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} loginOptions Options passed as URL parameters to the SSO. | ||
* @param {?=} width Pixel width of the login window. | ||
* @param {?=} height Pixel height of the login window. | ||
* @param {?=} top Position of the top corners. If it is a negative | ||
* number it centres the login window on the screen. | ||
* @param {?=} left Position of the left corners. If it is a negative | ||
* number it centres the login window on the screen. | ||
* @return {?} | ||
*/ | ||
function (loginOptions, width, height, top, left) { | ||
if (width === void 0) { | ||
width = 650; | ||
} | ||
if (height === void 0) { | ||
height = 1000; | ||
} | ||
if (top === void 0) { | ||
top = -1; | ||
} | ||
if (left === void 0) { | ||
left = -1; | ||
} | ||
if (left < 0) { | ||
var /** @type {?} */ screenWidth = screen.width; | ||
if (screenWidth > width) { | ||
left = Math.round(screenWidth / 2 - width / 2); | ||
} | ||
} | ||
if (top < 0) { | ||
var /** @type {?} */ screenHeight = screen.height; | ||
if (screenHeight > height) { | ||
top = Math.round(screenHeight / 2 - height / 2); | ||
} | ||
} | ||
var /** @type {?} */ windowOptions = [ | ||
"width=" + width, | ||
"height=" + height, | ||
"left=" + left, | ||
"top=" + top, | ||
'personalbar=no', | ||
'toolbar=no', | ||
'scrollbars=yes', | ||
'resizable=yes', | ||
'directories=no', | ||
'location=no', | ||
'menubar=no', | ||
'titlebar=no', | ||
'toolbar=no' | ||
]; | ||
var /** @type {?} */ loginWindow = window.open(this.getSSOURL(loginOptions), 'Sign in to Elixir', windowOptions.join(',')); | ||
if (loginWindow) { | ||
loginWindow.focus(); | ||
} | ||
}; | ||
/** | ||
* Functions that opens a tab (in modern browser). | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} loginOptions Options passed as URL parameters to the SSO. | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.tabOpen = /** | ||
* Functions that opens a tab (in modern browser). | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} loginOptions Options passed as URL parameters to the SSO. | ||
* @return {?} | ||
*/ | ||
function (loginOptions) { | ||
var /** @type {?} */ loginWindow = window.open(this.getSSOURL(loginOptions), 'Sign in to Elixir'); | ||
if (loginWindow) { | ||
loginWindow.focus(); | ||
} | ||
}; | ||
/** | ||
* Produces a URL that allows logging into the single sign on (SSO) page. | ||
* The URL cans be opened in a new tab using target="_blank", | ||
* or in a new window using window.open(). | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} options | ||
* @return {?} The SSO URL. | ||
* | ||
*/ | ||
AuthService.prototype.getSSOURL = /** | ||
* Produces a URL that allows logging into the single sign on (SSO) page. | ||
* The URL cans be opened in a new tab using target="_blank", | ||
* or in a new window using window.open(). | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} options | ||
* @return {?} The SSO URL. | ||
* | ||
*/ | ||
function (options) { | ||
var /** @type {?} */ extra = ''; | ||
if (options) { | ||
this._filterLoginOptions(options); | ||
extra = Object.keys(options) | ||
.map(function (key) { return [key, options[key]]; }) | ||
.reduce(function (accumulator, keyvalue) { return accumulator + "&" + keyvalue[0] + "=" + keyvalue[1]; }, ''); | ||
} | ||
return this._appURL + "/sso?from=" + this._domain + extra; | ||
}; | ||
/** | ||
* Filters options that are unsecure. | ||
* | ||
* See the advance options that can be requested through the options parameter: | ||
* https://api.aai.ebi.ac.uk/docs/authentication/authentication.index.html#_common_attributes | ||
* | ||
* The time to live paramenter (ttl) default value is 60 minutes. It is a | ||
* big security risk to request longer ttl. If a third party gets hold of | ||
* such token, means that they could use it for a day, week, year | ||
* (essentially, like having the username/password). | ||
* | ||
* @param {?} options | ||
* @return {?} | ||
*/ | ||
AuthService.prototype._filterLoginOptions = /** | ||
* Filters options that are unsecure. | ||
* | ||
* See the advance options that can be requested through the options parameter: | ||
* https://api.aai.ebi.ac.uk/docs/authentication/authentication.index.html#_common_attributes | ||
* | ||
* The time to live paramenter (ttl) default value is 60 minutes. It is a | ||
* big security risk to request longer ttl. If a third party gets hold of | ||
* such token, means that they could use it for a day, week, year | ||
* (essentially, like having the username/password). | ||
* | ||
* @param {?} options | ||
* @return {?} | ||
*/ | ||
function (options) { | ||
if (Object.keys(options).indexOf('ttl') > -1) { | ||
var /** @type {?} */ ttl = +options['ttl']; | ||
var /** @type {?} */ softLimit = 60; | ||
var /** @type {?} */ hardLimit = 60 * 24; | ||
if (ttl > hardLimit) { | ||
window.console.error("Login requested with an expiration longer than " + hardLimit + " minutes! This is not allowed."); | ||
window.console.error("Expiration request reset to " + hardLimit + " minutes."); | ||
options['ttl'] = '' + hardLimit; | ||
} | ||
else if (ttl > softLimit) { | ||
window.console.warn("Login requested with an expiration longer than " + softLimit + " minutes!"); | ||
} | ||
} | ||
}; | ||
/** | ||
* Functions that logs out the user. | ||
* It triggers the logout callbacks. | ||
* It is an arrow function (lambda) because in that way it has a reference | ||
* to 'this' when used in setTimeout call. | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.logOut = /** | ||
* Functions that logs out the user. | ||
* It triggers the logout callbacks. | ||
* It is an arrow function (lambda) because in that way it has a reference | ||
* to 'this' when used in setTimeout call. | ||
* @return {?} | ||
*/ | ||
function () { | ||
this._storageRemover(); | ||
this._updateCredentials(); | ||
// Triggers updating other windows | ||
this._commKeyUpdater(); | ||
}; | ||
/** | ||
* Add a callback to the LogIn event. | ||
* | ||
* @param {?} callback The Function called when the login event is triggered and the | ||
* JWT token is received and accepted. | ||
* | ||
* @return {?} The event registration id (necessary to unregister the event). | ||
*/ | ||
AuthService.prototype.addLogInEventListener = /** | ||
* Add a callback to the LogIn event. | ||
* | ||
* @param {?} callback The Function called when the login event is triggered and the | ||
* JWT token is received and accepted. | ||
* | ||
* @return {?} The event registration id (necessary to unregister the event). | ||
*/ | ||
function (callback) { | ||
return this._loginCallbacks.push(callback); | ||
}; | ||
/** | ||
* Remove a callback from the LogIn event. | ||
* | ||
* @param {?} id The id given when event listener was added. | ||
* | ||
* @return {?} true when remove successfully, false otherwise. | ||
*/ | ||
AuthService.prototype.removeLogInEventListener = /** | ||
* Remove a callback from the LogIn event. | ||
* | ||
* @param {?} id The id given when event listener was added. | ||
* | ||
* @return {?} true when remove successfully, false otherwise. | ||
*/ | ||
function (id) { | ||
return delete this._loginCallbacks[id - 1]; | ||
}; | ||
/** | ||
* Add a callback to the LogOut event. | ||
* | ||
* @param {?} callback The Function called when the logout event is triggered and the | ||
* JWT token is received and accepted. | ||
* | ||
* @return {?} The registration id (necessary to unregister the event). | ||
*/ | ||
AuthService.prototype.addLogOutEventListener = /** | ||
* Add a callback to the LogOut event. | ||
* | ||
* @param {?} callback The Function called when the logout event is triggered and the | ||
* JWT token is received and accepted. | ||
* | ||
* @return {?} The registration id (necessary to unregister the event). | ||
*/ | ||
function (callback) { | ||
return this._logoutCallbacks.push(callback); | ||
}; | ||
/** | ||
* Remove a callback from the LogOut event. | ||
* | ||
* @param {?} id The id given when event listener was added. | ||
* | ||
* @return {?} true when remove successfully, false otherwise. | ||
*/ | ||
AuthService.prototype.removeLogOutEventListener = /** | ||
* Remove a callback from the LogOut event. | ||
* | ||
* @param {?} id The id given when event listener was added. | ||
* | ||
* @return {?} true when remove successfully, false otherwise. | ||
*/ | ||
function (id) { | ||
return delete this._logoutCallbacks[id - 1]; | ||
}; | ||
/** | ||
* Listen for login messages from other windows. | ||
* These messages contain the tokens from the AAP. | ||
* If a token is received then the callbacks are triggered. | ||
* @param {?} renderer | ||
* @return {?} | ||
*/ | ||
AuthService.prototype._listenLoginMessage = /** | ||
* Listen for login messages from other windows. | ||
* These messages contain the tokens from the AAP. | ||
* If a token is received then the callbacks are triggered. | ||
* @param {?} renderer | ||
* @return {?} | ||
*/ | ||
function (renderer) { | ||
var _this = this; | ||
renderer.listen('window', 'message', function (event) { | ||
if (!_this.messageIsAcceptable(event)) { | ||
return; | ||
} | ||
_this._storageUpdater(event.data); | ||
event.source.close(); | ||
_this._updateCredentials(); | ||
// Triggers updating other windows | ||
// Triggers updating other windows | ||
_this._commKeyUpdater(); | ||
}); | ||
}; | ||
/** | ||
* Listen to changes in the token from *other* windows. | ||
* | ||
* For inter-window communication messages are transmitted trough changes | ||
* on a dummy storage key property: '_commKeyName'. | ||
* | ||
* Notice that changes in the '_commKeyName' produced by this class doesn't | ||
* trigger this event. | ||
* @param {?} renderer | ||
* @return {?} | ||
*/ | ||
AuthService.prototype._listenChangesFromOtherWindows = /** | ||
* Listen to changes in the token from *other* windows. | ||
* | ||
* For inter-window communication messages are transmitted trough changes | ||
* on a dummy storage key property: '_commKeyName'. | ||
* | ||
* Notice that changes in the '_commKeyName' produced by this class doesn't | ||
* trigger this event. | ||
* @param {?} renderer | ||
* @return {?} | ||
*/ | ||
function (renderer) { | ||
var _this = this; | ||
renderer.listen('window', 'storage', function (event) { | ||
if (event.key === _this._commKeyName) { | ||
_this._updateCredentials(); | ||
} | ||
}); | ||
}; | ||
/** | ||
* Check if the message is coming from the same domain we use to generate | ||
* the SSO URL, otherwise it's iffy and shouldn't trust it. | ||
* @param {?} event | ||
* @return {?} | ||
*/ | ||
AuthService.prototype.messageIsAcceptable = /** | ||
* Check if the message is coming from the same domain we use to generate | ||
* the SSO URL, otherwise it's iffy and shouldn't trust it. | ||
* @param {?} event | ||
* @return {?} | ||
*/ | ||
function (event) { | ||
return event.origin === this._appURL; | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype._updateCredentials = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
var _this = this; | ||
var /** @type {?} */ isAuthenticated = this._loggedIn(); | ||
if (this._timeoutID) { | ||
window.clearTimeout(this._timeoutID); | ||
} | ||
if (isAuthenticated) { | ||
this._credentials.next({ | ||
realname: /** @type {?} */ (this._getRealName()), | ||
username: /** @type {?} */ (this._getUserName()), | ||
token: /** @type {?} */ (this._getToken()) | ||
}); | ||
this._loginCallbacks.map(function (callback) { return callback && callback(); }); | ||
// Schedule future logout event base on token expiration | ||
var /** @type {?} */ expireDate = (this._tokenService.getTokenExpirationDate()); | ||
// Coercing dates to numbers with the unary operator '+' | ||
var /** @type {?} */ delay = +expireDate - +new Date(); | ||
this._timeoutID = window.setTimeout(function () { return _this.logOut(); }, delay); | ||
} | ||
else { | ||
this._storageRemover(); // Cleanup possible left behind token | ||
this._credentials.next(null); | ||
this._logoutCallbacks.map(function (callback) { return callback && callback(); }); | ||
} | ||
}; | ||
/** | ||
* Check if there's a user logging on and whether the token is still valid. | ||
* | ||
* @return {?} Whether the user user is authenticated or not. | ||
*/ | ||
AuthService.prototype._loggedIn = /** | ||
* Check if there's a user logging on and whether the token is still valid. | ||
* | ||
* @return {?} Whether the user user is authenticated or not. | ||
*/ | ||
function () { | ||
return this._tokenService.isTokenValid(); | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype._getToken = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._tokenService.getToken(); | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype._getUserName = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._tokenService.getClaim('email', null); | ||
}; | ||
/** | ||
* @return {?} | ||
*/ | ||
AuthService.prototype._getRealName = /** | ||
* @return {?} | ||
*/ | ||
function () { | ||
return this._tokenService.getClaim('name', null); | ||
}; | ||
AuthService.decorators = [ | ||
{ type: core.Injectable }, | ||
]; | ||
var loginWindow = window.open(this.getSSOURL(loginOptions), 'Sign in to Elixir', windowOptions.join(',')); | ||
if (loginWindow) { | ||
loginWindow.focus(); | ||
} | ||
}; | ||
AuthService.prototype.tabOpen = function (loginOptions) { | ||
var loginWindow = window.open(this.getSSOURL(loginOptions), 'Sign in to Elixir'); | ||
if (loginWindow) { | ||
loginWindow.focus(); | ||
} | ||
}; | ||
AuthService.prototype.getSSOURL = function (options) { | ||
var extra = ''; | ||
if (options) { | ||
this._filterLoginOptions(options); | ||
extra = Object.keys(options) | ||
.map(function (key) { return [key, options[key]]; }) | ||
.reduce(function (accumulator, keyvalue) { return accumulator + "&" + keyvalue[0] + "=" + keyvalue[1]; }, ''); | ||
} | ||
return this._appURL + "/sso?from=" + this._domain + extra; | ||
}; | ||
AuthService.prototype._filterLoginOptions = function (options) { | ||
if (Object.keys(options).indexOf('ttl') > -1) { | ||
var ttl = +options['ttl']; | ||
var softLimit = 60; | ||
var hardLimit = 60 * 24; | ||
if (ttl > hardLimit) { | ||
window.console.error("Login requested with an expiration longer than " + hardLimit + " minutes! This is not allowed."); | ||
window.console.error("Expiration request reset to " + hardLimit + " minutes."); | ||
options['ttl'] = '' + hardLimit; | ||
/** @nocollapse */ | ||
AuthService.ctorParameters = function () { | ||
return [ | ||
{ type: core.RendererFactory2 }, | ||
{ type: TokenService }, | ||
{ type: undefined, decorators: [{ type: core.Inject, args: [AAP_CONFIG,] }] } | ||
]; | ||
}; | ||
return AuthService; | ||
}()); | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
var AuthModule = (function () { | ||
function AuthModule(parentModule) { | ||
if (parentModule) { | ||
throw new Error('AuthModule is already loaded. It should only be imported in your application\'s main module.'); | ||
} | ||
else if (ttl > softLimit) { | ||
window.console.warn("Login requested with an expiration longer than " + softLimit + " minutes!"); | ||
} | ||
} | ||
}; | ||
AuthService.prototype.logOut = function () { | ||
this._storageRemover(); | ||
this._updateCredentials(); | ||
this._commKeyUpdater(); | ||
}; | ||
AuthService.prototype.addLogInEventListener = function (callback) { | ||
return this._loginCallbacks.push(callback); | ||
}; | ||
AuthService.prototype.removeLogInEventListener = function (id) { | ||
return delete this._loginCallbacks[id - 1]; | ||
}; | ||
AuthService.prototype.addLogOutEventListener = function (callback) { | ||
return this._logoutCallbacks.push(callback); | ||
}; | ||
AuthService.prototype.removeLogOutEventListener = function (id) { | ||
return delete this._logoutCallbacks[id - 1]; | ||
}; | ||
AuthService.prototype._listenLoginMessage = function (renderer) { | ||
var _this = this; | ||
renderer.listen('window', 'message', function (event) { | ||
if (!_this.messageIsAcceptable(event)) { | ||
return; | ||
} | ||
_this._storageUpdater(event.data); | ||
event.source.close(); | ||
_this._updateCredentials(); | ||
_this._commKeyUpdater(); | ||
}); | ||
}; | ||
AuthService.prototype._listenChangesFromOtherWindows = function (renderer) { | ||
var _this = this; | ||
renderer.listen('window', 'storage', function (event) { | ||
if (event.key === _this._commKeyName) { | ||
_this._updateCredentials(); | ||
} | ||
}); | ||
}; | ||
AuthService.prototype.messageIsAcceptable = function (event) { | ||
return event.origin === this._appURL; | ||
}; | ||
AuthService.prototype._updateCredentials = function () { | ||
var _this = this; | ||
var isAuthenticated = this._loggedIn(); | ||
if (this._timeoutID) { | ||
window.clearTimeout(this._timeoutID); | ||
} | ||
if (isAuthenticated) { | ||
this._credentials.next({ | ||
realname: (this._getRealName()), | ||
username: (this._getUserName()), | ||
token: (this._getToken()) | ||
}); | ||
this._loginCallbacks.map(function (callback) { return callback && callback(); }); | ||
var expireDate = (this._tokenService.getTokenExpirationDate()); | ||
var delay = +expireDate - +new Date(); | ||
this._timeoutID = window.setTimeout(function () { return _this.logOut(); }, delay); | ||
} | ||
else { | ||
this._storageRemover(); | ||
this._credentials.next(null); | ||
this._logoutCallbacks.map(function (callback) { return callback && callback(); }); | ||
} | ||
}; | ||
AuthService.prototype._loggedIn = function () { | ||
return this._tokenService.isTokenValid(); | ||
}; | ||
AuthService.prototype._getToken = function () { | ||
return this._tokenService.getToken(); | ||
}; | ||
AuthService.prototype._getUserName = function () { | ||
return this._tokenService.getClaim('email', null); | ||
}; | ||
AuthService.prototype._getRealName = function () { | ||
return this._tokenService.getClaim('name', null); | ||
}; | ||
return AuthService; | ||
}()); | ||
AuthService.decorators = [ | ||
{ type: core.Injectable }, | ||
]; | ||
AuthService.ctorParameters = function () { return [ | ||
{ type: core.RendererFactory2, }, | ||
{ type: TokenService, }, | ||
{ type: undefined, decorators: [{ type: core.Inject, args: [AAP_CONFIG,] },] }, | ||
]; }; | ||
var AuthModule = /** @class */ (function () { | ||
function AuthModule(parentModule) { | ||
if (parentModule) { | ||
throw new Error('AuthModule is already loaded. It should only be imported in your application\'s main module.'); | ||
} | ||
} | ||
AuthModule.forRoot = function (options) { | ||
return { | ||
ngModule: AuthModule, | ||
providers: [ | ||
TokenService, | ||
{ | ||
provide: AAP_CONFIG, | ||
useValue: options ? options : DEFAULT_CONF | ||
}, | ||
AuthService | ||
] | ||
/** | ||
* @param {?=} options | ||
* @return {?} | ||
*/ | ||
AuthModule.forRoot = /** | ||
* @param {?=} options | ||
* @return {?} | ||
*/ | ||
function (options) { | ||
return { | ||
ngModule: AuthModule, | ||
providers: [ | ||
TokenService, | ||
{ | ||
provide: AAP_CONFIG, | ||
useValue: options ? options : DEFAULT_CONF | ||
}, | ||
AuthService | ||
] | ||
}; | ||
}; | ||
AuthModule.decorators = [ | ||
{ type: core.NgModule, args: [{},] }, | ||
]; | ||
/** @nocollapse */ | ||
AuthModule.ctorParameters = function () { | ||
return [ | ||
{ type: AuthModule, decorators: [{ type: core.Optional }, { type: core.SkipSelf }] } | ||
]; | ||
}; | ||
}; | ||
return AuthModule; | ||
}()); | ||
AuthModule.decorators = [ | ||
{ type: core.NgModule, args: [{},] }, | ||
]; | ||
AuthModule.ctorParameters = function () { return [ | ||
{ type: AuthModule, decorators: [{ type: core.Optional }, { type: core.SkipSelf },] }, | ||
]; }; | ||
return AuthModule; | ||
}()); | ||
exports.AuthModule = AuthModule; | ||
exports.AuthService = AuthService; | ||
exports.TokenService = TokenService; | ||
exports.ɵb = AAP_CONFIG; | ||
exports.ɵf = DEFAULT_CONF; | ||
exports.ɵc = getToken; | ||
exports.ɵd = removeToken; | ||
exports.ɵe = updateToken; | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
exports.AuthModule = AuthModule; | ||
exports.AuthService = AuthService; | ||
exports.TokenService = TokenService; | ||
exports.ɵb = AAP_CONFIG; | ||
exports.ɵf = DEFAULT_CONF; | ||
exports.ɵc = getToken; | ||
exports.ɵd = removeToken; | ||
exports.ɵe = updateToken; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}))); | ||
//# sourceMappingURL=angular-aap-auth.umd.js.map | ||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1hYXAtYXV0aC51bWQuanMubWFwIiwic291cmNlcyI6WyJuZzovL2FuZ3VsYXItYWFwLWF1dGgvYXBwL21vZHVsZXMvYXV0aC90b2tlbi5zZXJ2aWNlLnRzIiwibmc6Ly9hbmd1bGFyLWFhcC1hdXRoL2FwcC9tb2R1bGVzL2F1dGgvYXV0aC5jb25maWcudHMiLCJuZzovL2FuZ3VsYXItYWFwLWF1dGgvYXBwL21vZHVsZXMvYXV0aC9hdXRoLnNlcnZpY2UudHMiLCJuZzovL2FuZ3VsYXItYWFwLWF1dGgvYXBwL21vZHVsZXMvYXV0aC9hdXRoLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIEluamVjdGFibGVcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7XG4gICAgSnd0SGVscGVyU2VydmljZVxufSBmcm9tICdAYXV0aDAvYW5ndWxhci1qd3QnO1xuXG4vKipcbiAqIFRoZSBwdXJwb3NlIG9mIHRoaXMgdmVyeSBzaW1wbGUgc2VydmljZSBpcyB0byBpbnRlcmZhY2UgYmV0d2VlbiB0aGVcbiAqIEF1dGhTZXJ2aWNlIGFuZCB0aGUgc3BlY2lmaWMgdG9rZW4gbWFuaXB1bGF0aW9uIHJvdXRpbmcgb2YgSnd0SGVscGVyU2VydmljZS5cbiAqIEluIHRoaXMgd2F5LCBpZiBpbiB0aGUgZnV0dXJlIHdlIHdhbnQgdG8gcmVwbGFjZSBKd3RIZWxwZXJTZXJ2aWNlIGJ5XG4gKiBhbm90aGVyIHNlcnZpY2UsIEF1dGhTZXJ2aWNlIGRvZXNuJ3QgbmVlZCB0byBiZSBtb2RpZmllZCwgb25seSB0aGlzIHNlcnZpY2UuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBUb2tlblNlcnZpY2Uge1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgX2p3dDogSnd0SGVscGVyU2VydmljZVxuICAgICkge31cblxuICAgIHB1YmxpYyBnZXRUb2tlbigpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2p3dC50b2tlbkdldHRlcigpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRUb2tlbkV4cGlyYXRpb25EYXRlKCk6IERhdGUgfCBudWxsIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9qd3QuZ2V0VG9rZW5FeHBpcmF0aW9uRGF0ZSgpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBpc1Rva2VuVmFsaWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gIXRoaXMuX2p3dC5pc1Rva2VuRXhwaXJlZCgpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGNsYWltcyBmcm9tIHRoZSB0b2tlbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBjbGFpbSBUaGUgbmFtZSBvZiB0aGUgY2xhaW1cbiAgICAgKiBAcGFyYW0gZGVmYXVsdFZhbHVlIFRoZSBkZWZhdWx0IHZhbHVlIHJldHVybmVkIGluIGNhc2Ugb2YgZXJyb3JcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIGNsYWltIG9yIGRlZmF1bHQgdmFsdWVcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Q2xhaW0gPCBULCBDID4gKGNsYWltOiBzdHJpbmcsIGRlZmF1bHRWYWx1ZTogQyk6IFQgfCBDIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gPCBUID4gdGhpcy5fand0LmRlY29kZVRva2VuKClbY2xhaW1dO1xuICAgICAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IHtcbiAgICBJbmplY3Rpb25Ub2tlblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuZXhwb3J0IGludGVyZmFjZSBBdXRoQ29uZmlnIHtcbiAgICBhYXBVUkw6IHN0cmluZztcbiAgICB0b2tlbkdldHRlcjogKCkgPT4gc3RyaW5nO1xuICAgIHRva2VuUmVtb3Zlcj86ICgpID0+IHZvaWQ7XG4gICAgdG9rZW5VcGRhdGVyOiAobmV3VG9rZW46IGFueSkgPT4gdm9pZDtcbn1cblxuZXhwb3J0IGNvbnN0IEFBUF9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW4gPCBBdXRoQ29uZmlnID4gKCdBQVBfQ09ORklHJyk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUb2tlbigpOiBzdHJpbmcge1xuICAgIHJldHVybiBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnaWRfdG9rZW4nKSB8fCAnJztcbn1cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVUb2tlbigpOiB2b2lkIHtcbiAgICByZXR1cm4gbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oJ2lkX3Rva2VuJyk7XG59XG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlVG9rZW4obmV3VG9rZW46IHN0cmluZyk6IHZvaWQge1xuICAgIHJldHVybiBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnaWRfdG9rZW4nLCBuZXdUb2tlbik7XG59XG5leHBvcnQgY29uc3QgREVGQVVMVF9DT05GOiBBdXRoQ29uZmlnID0ge1xuICAgIGFhcFVSTDogJ2h0dHBzOi8vYXBpLmFhaS5lYmkuYWMudWsnLFxuICAgIHRva2VuR2V0dGVyOiBnZXRUb2tlbixcbiAgICB0b2tlblJlbW92ZXI6IHJlbW92ZVRva2VuLFxuICAgIHRva2VuVXBkYXRlcjogdXBkYXRlVG9rZW5cbn07XG4iLCJpbXBvcnQge1xuICAgIEluamVjdGFibGUsXG4gICAgSW5qZWN0LFxuICAgIFJlbmRlcmVyRmFjdG9yeTIsXG4gICAgUmVuZGVyZXIyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgICBPYnNlcnZhYmxlXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtcbiAgICBCZWhhdmlvclN1YmplY3QsXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtcbiAgICBtYXBcbn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge1xuICAgIEFBUF9DT05GSUcsXG4gICAgQXV0aENvbmZpZ1xufSBmcm9tICcuL2F1dGguY29uZmlnJztcbmltcG9ydCB7XG4gICAgVG9rZW5TZXJ2aWNlXG59IGZyb20gJy4vdG9rZW4uc2VydmljZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9naW5PcHRpb25zIHtcbiAgICBba2V5OiBzdHJpbmddOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlZGVudGlhbHMge1xuICAgIHJlYWxuYW1lOiBzdHJpbmc7XG4gICAgdXNlcm5hbWU6IHN0cmluZztcbiAgICB0b2tlbjogc3RyaW5nO1xufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXV0aFNlcnZpY2Uge1xuXG4gICAgcHJpdmF0ZSBfY3JlZGVudGlhbHMgPSBuZXcgQmVoYXZpb3JTdWJqZWN0IDwgQ3JlZGVudGlhbHMgfCBudWxsID4gKG51bGwpO1xuXG4gICAgcHJpdmF0ZSBfbG9naW5DYWxsYmFja3M6IEZ1bmN0aW9uW10gPSBbXTtcbiAgICBwcml2YXRlIF9sb2dvdXRDYWxsYmFja3M6IEZ1bmN0aW9uW10gPSBbXTtcblxuICAgIHByaXZhdGUgX3RpbWVvdXRJRDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgICAvLyBDb25maWd1cmF0aW9uXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZG9tYWluOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfYXBwVVJMOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfc3RvcmFnZVVwZGF0ZXI6IChuZXdUb2tlbjogYW55KSA9PiB2b2lkO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX3N0b3JhZ2VSZW1vdmVyOiAoKSA9PiB2b2lkO1xuXG4gICAgLy8gVGhpcyB0d28gcHJvcGVydGllcyBhcmUgdXNlZCBmb3IgaW50ZXItd2luZG93IGNvbW11bmNhdGlvbi5cbiAgICAvLyBJdCBpcyBhY2hpZXZlIHRocm91Z2ggdGhlIHVwZGF0ZSBvZiB0aGUgZHVtbXkga2V5IHN0b3JhZ2UgJ19jb21tS2V5TmFtZSdcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jb21tS2V5TmFtZSA9ICdBbmd1bGFyQWFwQXV0aFVwZGF0ZWQnO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NvbW1LZXlVcGRhdGVyID0gKCkgPT4gbG9jYWxTdG9yYWdlLnNldEl0ZW0odGhpcy5fY29tbUtleU5hbWUsICcnICsgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgX3JlbmRlcmVyRmFjdG9yeTogUmVuZGVyZXJGYWN0b3J5MixcbiAgICAgICAgcHJpdmF0ZSBfdG9rZW5TZXJ2aWNlOiBUb2tlblNlcnZpY2UsXG4gICAgICAgIEBJbmplY3QoQUFQX0NPTkZJRykgcHJpdmF0ZSBjb25maWc6IEF1dGhDb25maWdcbiAgICApIHtcbiAgICAgICAgdGhpcy5fZG9tYWluID0gZW5jb2RlVVJJQ29tcG9uZW50KHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pO1xuICAgICAgICB0aGlzLl9hcHBVUkwgPSBjb25maWcuYWFwVVJMLnJlcGxhY2UoL1xcLyQvLCAnJyk7XG4gICAgICAgIHRoaXMuX3N0b3JhZ2VVcGRhdGVyID0gY29uZmlnLnRva2VuVXBkYXRlcjtcbiAgICAgICAgaWYgKGNvbmZpZy50b2tlblJlbW92ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0b3JhZ2VSZW1vdmVyID0gY29uZmlnLnRva2VuUmVtb3ZlcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3N0b3JhZ2VSZW1vdmVyID0gKCkgPT4gY29uZmlnLnRva2VuVXBkYXRlcihudWxsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlbmRlcmVyID0gdGhpcy5fcmVuZGVyZXJGYWN0b3J5LmNyZWF0ZVJlbmRlcmVyKG51bGwsIG51bGwpO1xuICAgICAgICB0aGlzLl9saXN0ZW5Mb2dpbk1lc3NhZ2UocmVuZGVyZXIpO1xuICAgICAgICB0aGlzLl9saXN0ZW5DaGFuZ2VzRnJvbU90aGVyV2luZG93cyhyZW5kZXJlcik7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlQ3JlZGVudGlhbHMoKTsgLy8gVE9ETzogZXhwZXJpbWVudCB3aXRoIHNldFRpbWVPdXRcbiAgICB9XG5cbiAgICBwdWJsaWMgaXNBdXRoZW50aWNhdGVkKCk6IE9ic2VydmFibGUgPCBib29sZWFuID4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fY3JlZGVudGlhbHMuYXNPYnNlcnZhYmxlKCkucGlwZShcbiAgICAgICAgICAgIG1hcChjcmVkZW50aWFscyA9PiBjcmVkZW50aWFscyA/IHRydWUgOiBmYWxzZSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlZGVudGlhbHMoKTogT2JzZXJ2YWJsZSA8IENyZWRlbnRpYWxzIHwgbnVsbCA+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NyZWRlbnRpYWxzLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWFsbmFtZSgpOiBPYnNlcnZhYmxlIDwgc3RyaW5nIHwgbnVsbCA+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NyZWRlbnRpYWxzLmFzT2JzZXJ2YWJsZSgpLnBpcGUoXG4gICAgICAgICAgICBtYXAoY3JlZGVudGlhbHMgPT4gY3JlZGVudGlhbHMgPyAgY3JlZGVudGlhbHMucmVhbG5hbWUgOiBudWxsKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyB1c2VybmFtZSgpOiBPYnNlcnZhYmxlIDwgc3RyaW5nIHwgbnVsbCA+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NyZWRlbnRpYWxzLmFzT2JzZXJ2YWJsZSgpLnBpcGUoXG4gICAgICAgICAgICBtYXAoY3JlZGVudGlhbHMgPT4gY3JlZGVudGlhbHMgPyAgY3JlZGVudGlhbHMudXNlcm5hbWUgOiBudWxsKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyB0b2tlbigpOiBPYnNlcnZhYmxlIDwgc3RyaW5nIHwgbnVsbCA+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NyZWRlbnRpYWxzLmFzT2JzZXJ2YWJsZSgpLnBpcGUoXG4gICAgICAgICAgICBtYXAoY3JlZGVudGlhbHMgPT4gY3JlZGVudGlhbHMgPyAgY3JlZGVudGlhbHMudG9rZW4gOiBudWxsKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9ucyB0aGF0IG9wZW5zIGEgd2luZG93IGluc3RlYWQgb2YgYSB0YWIuXG4gICAgICpcbiAgICAgKiBTZWUgbWV0aG9kIF9maWx0ZXJMb2dpbk9wdGlvbnMgcmVnYXJkaW5nIHNlY3VyaXR5IHJpc2tzIG9mIGNlcnRhaW5cbiAgICAgKiBMb2dpbk9wdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbG9naW5PcHRpb25zIE9wdGlvbnMgcGFzc2VkIGFzIFVSTCBwYXJhbWV0ZXJzIHRvIHRoZSBTU08uXG4gICAgICogQHBhcmFtIHdpZHRoIFBpeGVsIHdpZHRoIG9mIHRoZSBsb2dpbiB3aW5kb3cuXG4gICAgICogQHBhcmFtIGhlaWdodCBQaXhlbCBoZWlnaHQgb2YgdGhlIGxvZ2luIHdpbmRvdy5cbiAgICAgKiBAcGFyYW0gdG9wIFBvc2l0aW9uIG9mIHRoZSB0b3AgY29ybmVycy4gSWYgaXQgaXMgYSBuZWdhdGl2ZVxuICAgICAqICAgICAgICAgICAgIG51bWJlciBpdCBjZW50cmVzIHRoZSBsb2dpbiB3aW5kb3cgb24gdGhlIHNjcmVlbi5cbiAgICAgKiBAcGFyYW0gbGVmdCBQb3NpdGlvbiBvZiB0aGUgbGVmdCBjb3JuZXJzLiBJZiBpdCBpcyBhIG5lZ2F0aXZlXG4gICAgICogICAgICAgICAgICAgbnVtYmVyIGl0IGNlbnRyZXMgdGhlIGxvZ2luIHdpbmRvdyBvbiB0aGUgc2NyZWVuLlxuICAgICAqL1xuICAgIHB1YmxpYyB3aW5kb3dPcGVuKGxvZ2luT3B0aW9ucz86IExvZ2luT3B0aW9ucywgd2lkdGggPSA2NTAsIGhlaWdodCA9IDEwMDAsIHRvcCA9IC0xLCBsZWZ0ID0gLTEpIHtcbiAgICAgICAgaWYgKGxlZnQgPCAwKSB7XG4gICAgICAgICAgICBjb25zdCBzY3JlZW5XaWR0aCA9IHNjcmVlbi53aWR0aDtcbiAgICAgICAgICAgIGlmIChzY3JlZW5XaWR0aCA+IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IE1hdGgucm91bmQoc2NyZWVuV2lkdGggLyAyIC0gd2lkdGggLyAyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodG9wIDwgMCkge1xuICAgICAgICAgICAgY29uc3Qgc2NyZWVuSGVpZ2h0ID0gc2NyZWVuLmhlaWdodDtcbiAgICAgICAgICAgIGlmIChzY3JlZW5IZWlnaHQgPiBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICB0b3AgPSBNYXRoLnJvdW5kKHNjcmVlbkhlaWdodCAvIDIgLSBoZWlnaHQgLyAyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHdpbmRvd09wdGlvbnMgPSBbXG4gICAgICAgICAgICBgd2lkdGg9JHt3aWR0aH1gLFxuICAgICAgICAgICAgYGhlaWdodD0ke2hlaWdodH1gLFxuICAgICAgICAgICAgYGxlZnQ9JHtsZWZ0fWAsXG4gICAgICAgICAgICBgdG9wPSR7dG9wfWAsXG4gICAgICAgICAgICAncGVyc29uYWxiYXI9bm8nLFxuICAgICAgICAgICAgJ3Rvb2xiYXI9bm8nLFxuICAgICAgICAgICAgJ3Njcm9sbGJhcnM9eWVzJyxcbiAgICAgICAgICAgICdyZXNpemFibGU9eWVzJyxcbiAgICAgICAgICAgICdkaXJlY3Rvcmllcz1ubycsXG4gICAgICAgICAgICAnbG9jYXRpb249bm8nLFxuICAgICAgICAgICAgJ21lbnViYXI9bm8nLFxuICAgICAgICAgICAgJ3RpdGxlYmFyPW5vJyxcbiAgICAgICAgICAgICd0b29sYmFyPW5vJ1xuICAgICAgICBdO1xuXG4gICAgICAgIGNvbnN0IGxvZ2luV2luZG93ID0gd2luZG93Lm9wZW4odGhpcy5nZXRTU09VUkwobG9naW5PcHRpb25zKSwgJ1NpZ24gaW4gdG8gRWxpeGlyJywgd2luZG93T3B0aW9ucy5qb2luKCcsJykpO1xuICAgICAgICBpZiAobG9naW5XaW5kb3cpIHtcbiAgICAgICAgICAgIGxvZ2luV2luZG93LmZvY3VzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbnMgdGhhdCBvcGVucyBhIHRhYiAoaW4gbW9kZXJuIGJyb3dzZXIpLlxuICAgICAqXG4gICAgICogU2VlIG1ldGhvZCBfZmlsdGVyTG9naW5PcHRpb25zIHJlZ2FyZGluZyBzZWN1cml0eSByaXNrcyBvZiBjZXJ0YWluXG4gICAgICogTG9naW5PcHRpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIGxvZ2luT3B0aW9ucyBPcHRpb25zIHBhc3NlZCBhcyBVUkwgcGFyYW1ldGVycyB0byB0aGUgU1NPLlxuICAgICAqL1xuICAgIHB1YmxpYyB0YWJPcGVuKGxvZ2luT3B0aW9ucz86IExvZ2luT3B0aW9ucykge1xuICAgICAgICBjb25zdCBsb2dpbldpbmRvdyA9IHdpbmRvdy5vcGVuKHRoaXMuZ2V0U1NPVVJMKGxvZ2luT3B0aW9ucyksICdTaWduIGluIHRvIEVsaXhpcicpO1xuICAgICAgICBpZiAobG9naW5XaW5kb3cpIHtcbiAgICAgICAgICAgIGxvZ2luV2luZG93LmZvY3VzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9kdWNlcyBhIFVSTCB0aGF0IGFsbG93cyBsb2dnaW5nIGludG8gdGhlIHNpbmdsZSBzaWduIG9uIChTU08pIHBhZ2UuXG4gICAgICogVGhlIFVSTCBjYW5zIGJlIG9wZW5lZCBpbiBhIG5ldyB0YWIgdXNpbmcgdGFyZ2V0PVwiX2JsYW5rXCIsXG4gICAgICogb3IgaW4gYSBuZXcgd2luZG93IHVzaW5nIHdpbmRvdy5vcGVuKCkuXG4gICAgICpcbiAgICAgKiBTZWUgbWV0aG9kIF9maWx0ZXJMb2dpbk9wdGlvbnMgcmVnYXJkaW5nIHNlY3VyaXR5IHJpc2tzIG9mIGNlcnRhaW5cbiAgICAgKiBMb2dpbk9wdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gIGxvZ2luT3B0aW9ucyBPcHRpb25zIHBhc3NlZCBhcyBVUkwgcGFyYW1ldGVycyB0byB0aGUgU1NPLlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIFNTTyBVUkwuXG4gICAgICpcbiAgICAgKi9cbiAgICAgICAgcHVibGljIGdldFNTT1VSTChvcHRpb25zPzogTG9naW5PcHRpb25zKTogc3RyaW5nIHtcbiAgICAgICAgbGV0IGV4dHJhID0gJyc7XG4gICAgICAgIGlmIChvcHRpb25zKSB7XG4gICAgICAgICAgICB0aGlzLl9maWx0ZXJMb2dpbk9wdGlvbnMob3B0aW9ucyk7XG4gICAgICAgICAgICBleHRyYSA9IE9iamVjdC5rZXlzKG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgLm1hcChrZXkgPT4gW2tleSwgb3B0aW9uc1trZXldXSlcbiAgICAgICAgICAgICAgICAucmVkdWNlKChhY2N1bXVsYXRvciwga2V5dmFsdWUpID0+IGAke2FjY3VtdWxhdG9yfSYke2tleXZhbHVlWzBdfT0ke2tleXZhbHVlWzFdfWAsICcnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYCR7dGhpcy5fYXBwVVJMfS9zc28/ZnJvbT0ke3RoaXMuX2RvbWFpbn0ke2V4dHJhfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmlsdGVycyBvcHRpb25zIHRoYXQgYXJlIHVuc2VjdXJlLlxuICAgICAqXG4gICAgICogU2VlIHRoZSBhZHZhbmNlIG9wdGlvbnMgdGhhdCBjYW4gYmUgcmVxdWVzdGVkIHRocm91Z2ggdGhlIG9wdGlvbnMgcGFyYW1ldGVyOlxuICAgICAqIGh0dHBzOi8vYXBpLmFhaS5lYmkuYWMudWsvZG9jcy9hdXRoZW50aWNhdGlvbi9hdXRoZW50aWNhdGlvbi5pbmRleC5odG1sI19jb21tb25fYXR0cmlidXRlc1xuICAgICAqXG4gICAgICogVGhlIHRpbWUgdG8gbGl2ZSBwYXJhbWVudGVyICh0dGwpIGRlZmF1bHQgdmFsdWUgaXMgNjAgbWludXRlcy4gSXQgaXMgYVxuICAgICAqIGJpZyBzZWN1cml0eSByaXNrIHRvIHJlcXVlc3QgbG9uZ2VyIHR0bC4gSWYgYSB0aGlyZCBwYXJ0eSBnZXRzIGhvbGQgb2ZcbiAgICAgKiBzdWNoIHRva2VuLCBtZWFucyB0aGF0IHRoZXkgY291bGQgdXNlIGl0IGZvciBhIGRheSwgd2VlaywgeWVhclxuICAgICAqIChlc3NlbnRpYWxseSwgbGlrZSBoYXZpbmcgdGhlIHVzZXJuYW1lL3Bhc3N3b3JkKS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSAgbG9naW5PcHRpb25zIE9wdGlvbnMgcGFzc2VkIGFzIFVSTCBwYXJhbWV0ZXJzIHRvIHRoZSBTU08uXG4gICAgICpcbiAgICAgKlxuICAgICAqL1xuICAgIHB1YmxpYyBfZmlsdGVyTG9naW5PcHRpb25zKG9wdGlvbnM6IExvZ2luT3B0aW9ucykge1xuICAgICAgICBpZiAoT2JqZWN0LmtleXMob3B0aW9ucykuaW5kZXhPZigndHRsJykgPiAtMSkge1xuICAgICAgICAgICAgY29uc3QgdHRsOiBudW1iZXIgPSArb3B0aW9uc1sndHRsJ107XG4gICAgICAgICAgICBjb25zdCBzb2Z0TGltaXQgPSA2MDtcbiAgICAgICAgICAgIGNvbnN0IGhhcmRMaW1pdCA9IDYwICogMjQ7XG4gICAgICAgICAgICBpZiAodHRsID4gaGFyZExpbWl0KSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmNvbnNvbGUuZXJyb3IoYExvZ2luIHJlcXVlc3RlZCB3aXRoIGFuIGV4cGlyYXRpb24gbG9uZ2VyIHRoYW4gJHtoYXJkTGltaXR9IG1pbnV0ZXMhIFRoaXMgaXMgbm90IGFsbG93ZWQuYCk7XG4gICAgICAgICAgICAgICAgd2luZG93LmNvbnNvbGUuZXJyb3IoYEV4cGlyYXRpb24gcmVxdWVzdCByZXNldCB0byAke2hhcmRMaW1pdH0gbWludXRlcy5gKTtcbiAgICAgICAgICAgICAgICBvcHRpb25zWyd0dGwnXSA9ICcnICsgaGFyZExpbWl0O1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0dGwgPiBzb2Z0TGltaXQpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuY29uc29sZS53YXJuKGBMb2dpbiByZXF1ZXN0ZWQgd2l0aCBhbiBleHBpcmF0aW9uIGxvbmdlciB0aGFuICR7c29mdExpbWl0fSBtaW51dGVzIWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb25zIHRoYXQgbG9ncyBvdXQgdGhlIHVzZXIuXG4gICAgICogSXQgdHJpZ2dlcnMgdGhlIGxvZ291dCBjYWxsYmFja3MuXG4gICAgICogSXQgaXMgYW4gYXJyb3cgZnVuY3Rpb24gKGxhbWJkYSkgYmVjYXVzZSBpbiB0aGF0IHdheSBpdCBoYXMgYSByZWZlcmVuY2VcbiAgICAgKiB0byAndGhpcycgd2hlbiB1c2VkIGluIHNldFRpbWVvdXQgY2FsbC5cbiAgICAgKi9cbiAgICBwdWJsaWMgbG9nT3V0KCkge1xuICAgICAgICB0aGlzLl9zdG9yYWdlUmVtb3ZlcigpO1xuICAgICAgICB0aGlzLl91cGRhdGVDcmVkZW50aWFscygpO1xuXG4gICAgICAgIC8vIFRyaWdnZXJzIHVwZGF0aW5nIG90aGVyIHdpbmRvd3NcbiAgICAgICAgdGhpcy5fY29tbUtleVVwZGF0ZXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBjYWxsYmFjayB0byB0aGUgTG9nSW4gZXZlbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIEZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSBsb2dpbiBldmVudCBpcyB0cmlnZ2VyZWQgYW5kIHRoZVxuICAgICAqICAgIEpXVCB0b2tlbiBpcyByZWNlaXZlZCBhbmQgYWNjZXB0ZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgZXZlbnQgcmVnaXN0cmF0aW9uIGlkIChuZWNlc3NhcnkgdG8gdW5yZWdpc3RlciB0aGUgZXZlbnQpLlxuICAgICAqL1xuICAgIHB1YmxpYyBhZGRMb2dJbkV2ZW50TGlzdGVuZXIoY2FsbGJhY2s6IEZ1bmN0aW9uKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvZ2luQ2FsbGJhY2tzLnB1c2goY2FsbGJhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhIGNhbGxiYWNrIGZyb20gdGhlIExvZ0luIGV2ZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIGlkIFRoZSBpZCBnaXZlbiB3aGVuIGV2ZW50IGxpc3RlbmVyIHdhcyBhZGRlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHRydWUgd2hlbiByZW1vdmUgc3VjY2Vzc2Z1bGx5LCBmYWxzZSBvdGhlcndpc2UuXG4gICAgICovXG4gICAgcHVibGljIHJlbW92ZUxvZ0luRXZlbnRMaXN0ZW5lcihpZDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBkZWxldGUgdGhpcy5fbG9naW5DYWxsYmFja3NbaWQgLSAxXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBjYWxsYmFjayB0byB0aGUgTG9nT3V0IGV2ZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBGdW5jdGlvbiBjYWxsZWQgd2hlbiB0aGUgbG9nb3V0IGV2ZW50IGlzIHRyaWdnZXJlZCBhbmQgdGhlXG4gICAgICogICAgSldUIHRva2VuIGlzIHJlY2VpdmVkIGFuZCBhY2NlcHRlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSByZWdpc3RyYXRpb24gaWQgKG5lY2Vzc2FyeSB0byB1bnJlZ2lzdGVyIHRoZSBldmVudCkuXG4gICAgICovXG4gICAgcHVibGljIGFkZExvZ091dEV2ZW50TGlzdGVuZXIoY2FsbGJhY2s6IEZ1bmN0aW9uKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvZ291dENhbGxiYWNrcy5wdXNoKGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYSBjYWxsYmFjayBmcm9tIHRoZSBMb2dPdXQgZXZlbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gaWQgVGhlIGlkIGdpdmVuIHdoZW4gZXZlbnQgbGlzdGVuZXIgd2FzIGFkZGVkLlxuICAgICAqXG4gICAgICogQHJldHVybnMgdHJ1ZSB3aGVuIHJlbW92ZSBzdWNjZXNzZnVsbHksIGZhbHNlIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVtb3ZlTG9nT3V0RXZlbnRMaXN0ZW5lcihpZDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBkZWxldGUgdGhpcy5fbG9nb3V0Q2FsbGJhY2tzW2lkIC0gMV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGlzdGVuIGZvciBsb2dpbiBtZXNzYWdlcyBmcm9tIG90aGVyIHdpbmRvd3MuXG4gICAgICogVGhlc2UgbWVzc2FnZXMgY29udGFpbiB0aGUgdG9rZW5zIGZyb20gdGhlIEFBUC5cbiAgICAgKiBJZiBhIHRva2VuIGlzIHJlY2VpdmVkIHRoZW4gdGhlIGNhbGxiYWNrcyBhcmUgdHJpZ2dlcmVkLlxuICAgICAqL1xuICAgIHByaXZhdGUgX2xpc3RlbkxvZ2luTWVzc2FnZShyZW5kZXJlcjogUmVuZGVyZXIyKSB7XG4gICAgICAgIHJlbmRlcmVyLmxpc3Rlbignd2luZG93JywgJ21lc3NhZ2UnLCAoZXZlbnQ6IE1lc3NhZ2VFdmVudCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLm1lc3NhZ2VJc0FjY2VwdGFibGUoZXZlbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fc3RvcmFnZVVwZGF0ZXIoZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICBldmVudC5zb3VyY2UuY2xvc2UoKTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUNyZWRlbnRpYWxzKCk7XG5cbiAgICAgICAgICAgIC8vIFRyaWdnZXJzIHVwZGF0aW5nIG90aGVyIHdpbmRvd3NcbiAgICAgICAgICAgIHRoaXMuX2NvbW1LZXlVcGRhdGVyKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKiBMaXN0ZW4gdG8gY2hhbmdlcyBpbiB0aGUgdG9rZW4gZnJvbSAqb3RoZXIqIHdpbmRvd3MuXG4gICAgICpcbiAgICAgKiBGb3IgaW50ZXItd2luZG93IGNvbW11bmljYXRpb24gbWVzc2FnZXMgYXJlIHRyYW5zbWl0dGVkIHRyb3VnaCBjaGFuZ2VzXG4gICAgICogb24gYSBkdW1teSBzdG9yYWdlIGtleSBwcm9wZXJ0eTogJ19jb21tS2V5TmFtZScuXG4gICAgICpcbiAgICAgKiBOb3RpY2UgdGhhdCBjaGFuZ2VzIGluIHRoZSAnX2NvbW1LZXlOYW1lJyBwcm9kdWNlZCBieSB0aGlzIGNsYXNzIGRvZXNuJ3RcbiAgICAgKiB0cmlnZ2VyIHRoaXMgZXZlbnQuXG4gICAgICovXG4gICAgcHJpdmF0ZSBfbGlzdGVuQ2hhbmdlc0Zyb21PdGhlcldpbmRvd3MocmVuZGVyZXI6IFJlbmRlcmVyMikge1xuICAgICAgICByZW5kZXJlci5saXN0ZW4oJ3dpbmRvdycsICdzdG9yYWdlJywgKGV2ZW50OiBTdG9yYWdlRXZlbnQpID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudC5rZXkgPT09IHRoaXMuX2NvbW1LZXlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlQ3JlZGVudGlhbHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIG1lc3NhZ2UgaXMgY29taW5nIGZyb20gdGhlIHNhbWUgZG9tYWluIHdlIHVzZSB0byBnZW5lcmF0ZVxuICAgICAqIHRoZSBTU08gVVJMLCBvdGhlcndpc2UgaXQncyBpZmZ5IGFuZCBzaG91bGRuJ3QgdHJ1c3QgaXQuXG4gICAgICovXG4gICAgcHJpdmF0ZSBtZXNzYWdlSXNBY2NlcHRhYmxlKGV2ZW50OiBNZXNzYWdlRXZlbnQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50Lm9yaWdpbiA9PT0gdGhpcy5fYXBwVVJMO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3VwZGF0ZUNyZWRlbnRpYWxzKCkge1xuICAgICAgICBjb25zdCBpc0F1dGhlbnRpY2F0ZWQgPSB0aGlzLl9sb2dnZWRJbigpO1xuXG4gICAgICAgIGlmICh0aGlzLl90aW1lb3V0SUQpIHtcbiAgICAgICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5fdGltZW91dElEKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0F1dGhlbnRpY2F0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2NyZWRlbnRpYWxzLm5leHQoe1xuICAgICAgICAgICAgICAgIHJlYWxuYW1lOiA8IHN0cmluZyA+IHRoaXMuX2dldFJlYWxOYW1lKCksXG4gICAgICAgICAgICAgICAgdXNlcm5hbWU6IDwgc3RyaW5nID4gdGhpcy5fZ2V0VXNlck5hbWUoKSxcbiAgICAgICAgICAgICAgICB0b2tlbjogPCBzdHJpbmcgPiB0aGlzLl9nZXRUb2tlbigpXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy5fbG9naW5DYWxsYmFja3MubWFwKGNhbGxiYWNrID0+IGNhbGxiYWNrICYmIGNhbGxiYWNrKCkpO1xuXG4gICAgICAgICAgICAvLyBTY2hlZHVsZSBmdXR1cmUgbG9nb3V0IGV2ZW50IGJhc2Ugb24gdG9rZW4gZXhwaXJhdGlvblxuICAgICAgICAgICAgY29uc3QgZXhwaXJlRGF0ZSA9IDwgRGF0ZSA+IHRoaXMuX3Rva2VuU2VydmljZS5nZXRUb2tlbkV4cGlyYXRpb25EYXRlKCk7XG4gICAgICAgICAgICAvLyBDb2VyY2luZyBkYXRlcyB0byBudW1iZXJzIHdpdGggdGhlIHVuYXJ5IG9wZXJhdG9yICcrJ1xuICAgICAgICAgICAgY29uc3QgZGVsYXkgPSArZXhwaXJlRGF0ZSAtICtuZXcgRGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fdGltZW91dElEID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4gdGhpcy5sb2dPdXQoKSwgZGVsYXkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fc3RvcmFnZVJlbW92ZXIoKTsgLy8gQ2xlYW51cCBwb3NzaWJsZSBsZWZ0IGJlaGluZCB0b2tlblxuICAgICAgICAgICAgdGhpcy5fY3JlZGVudGlhbHMubmV4dChudWxsKTtcbiAgICAgICAgICAgIHRoaXMuX2xvZ291dENhbGxiYWNrcy5tYXAoY2FsbGJhY2sgPT4gY2FsbGJhY2sgJiYgY2FsbGJhY2soKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGVyZSdzIGEgdXNlciBsb2dnaW5nIG9uIGFuZCB3aGV0aGVyIHRoZSB0b2tlbiBpcyBzdGlsbCB2YWxpZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zICBXaGV0aGVyIHRoZSB1c2VyIHVzZXIgaXMgYXV0aGVudGljYXRlZCBvciBub3QuXG4gICAgICovXG4gICAgcHJpdmF0ZSBfbG9nZ2VkSW4oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl90b2tlblNlcnZpY2UuaXNUb2tlblZhbGlkKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZ2V0VG9rZW4oKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLl90b2tlblNlcnZpY2UuZ2V0VG9rZW4oKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9nZXRVc2VyTmFtZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Rva2VuU2VydmljZS5nZXRDbGFpbSA8IHN0cmluZywgbnVsbCA+ICgnZW1haWwnLCBudWxsKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9nZXRSZWFsTmFtZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Rva2VuU2VydmljZS5nZXRDbGFpbSA8IHN0cmluZywgbnVsbCA+ICgnbmFtZScsIG51bGwpO1xuICAgIH1cblxufVxuIiwiaW1wb3J0IHtcbiAgICBOZ01vZHVsZSxcbiAgICBPcHRpb25hbCxcbiAgICBTa2lwU2VsZixcbiAgICBNb2R1bGVXaXRoUHJvdmlkZXJzLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtcbiAgICBKV1RfT1BUSU9OUyxcbiAgICBKd3RIZWxwZXJTZXJ2aWNlXG59IGZyb20gJ0BhdXRoMC9hbmd1bGFyLWp3dCc7XG5pbXBvcnQge1xuICAgIFRva2VuU2VydmljZVxufSBmcm9tICcuL3Rva2VuLnNlcnZpY2UnO1xuaW1wb3J0IHtcbiAgICBBdXRoQ29uZmlnLFxuICAgIEFBUF9DT05GSUcsXG4gICAgREVGQVVMVF9DT05GXG59IGZyb20gJy4vYXV0aC5jb25maWcnO1xuaW1wb3J0IHtcbiAgICBBdXRoU2VydmljZVxufSBmcm9tICcuL2F1dGguc2VydmljZSc7XG5cbkBOZ01vZHVsZSh7fSlcbmV4cG9ydCBjbGFzcyBBdXRoTW9kdWxlIHtcblxuICAgIGNvbnN0cnVjdG9yKEBPcHRpb25hbCgpIEBTa2lwU2VsZigpIHBhcmVudE1vZHVsZTogQXV0aE1vZHVsZSkge1xuICAgICAgICBpZiAocGFyZW50TW9kdWxlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F1dGhNb2R1bGUgaXMgYWxyZWFkeSBsb2FkZWQuIEl0IHNob3VsZCBvbmx5IGJlIGltcG9ydGVkIGluIHlvdXIgYXBwbGljYXRpb25cXCdzIG1haW4gbW9kdWxlLicpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGZvclJvb3Qob3B0aW9ucz86IEF1dGhDb25maWcpOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5nTW9kdWxlOiBBdXRoTW9kdWxlLFxuICAgICAgICAgICAgcHJvdmlkZXJzOiBbXG4gICAgICAgICAgICAgICAgVG9rZW5TZXJ2aWNlLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZTogQUFQX0NPTkZJRyxcbiAgICAgICAgICAgICAgICAgICAgdXNlVmFsdWU6IG9wdGlvbnMgPyBvcHRpb25zIDogREVGQVVMVF9DT05GXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBBdXRoU2VydmljZVxuICAgICAgICAgICAgXVxuICAgICAgICB9O1xuICAgIH1cbn1cbiJdLCJuYW1lcyI6WyJJbmplY3RhYmxlIiwiSnd0SGVscGVyU2VydmljZSIsIkluamVjdGlvblRva2VuIiwiQmVoYXZpb3JTdWJqZWN0IiwibWFwIiwiUmVuZGVyZXJGYWN0b3J5MiIsIkluamVjdCIsIk5nTW9kdWxlIiwiT3B0aW9uYWwiLCJTa2lwU2VsZiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBOzs7Ozs7O1FBaUJJLHNCQUNZO1lBQUEsU0FBSSxHQUFKLElBQUk7U0FDWjs7OztRQUVHLCtCQUFROzs7O2dCQUNYLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQzs7Ozs7UUFHNUIsNkNBQXNCOzs7O2dCQUN6QixJQUFJO29CQUNBLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO2lCQUM3QztnQkFBQyxPQUFPLENBQUMsRUFBRTtvQkFDUixPQUFPLElBQUksQ0FBQztpQkFDZjs7Ozs7UUFHRSxtQ0FBWTs7OztnQkFDZixJQUFJO29CQUNBLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2lCQUN0QztnQkFBQyxPQUFPLEtBQUssRUFBRTtvQkFDWixPQUFPLEtBQUss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 |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core"),require("@auth0/angular-jwt"),require("rxjs"),require("rxjs/operators")):"function"==typeof define&&define.amd?define("angular-aap-auth",["exports","@angular/core","@auth0/angular-jwt","rxjs","rxjs/operators"],t):t(e["angular-aap-auth"]={},e.ng.core,e.angularJwt,e.RxJS,e.Rx.Observable.prototype)}(this,function(e,t,n,i,o){"use strict";var r=function(){function e(e){this._jwt=e}return e.prototype.getToken=function(){return this._jwt.tokenGetter()},e.prototype.getTokenExpirationDate=function(){try{return this._jwt.getTokenExpirationDate()}catch(e){return null}},e.prototype.isTokenValid=function(){try{return!this._jwt.isTokenExpired()}catch(e){return!1}},e.prototype.getClaim=function(e,t){try{var n=this._jwt.decodeToken()[e];return n===undefined?t:n}catch(o){return t}},e}();r.decorators=[{type:t.Injectable}],r.ctorParameters=function(){return[{type:n.JwtHelperService}]};var a=new t.InjectionToken("AAP_CONFIG");function s(){return localStorage.getItem("id_token")||""}function u(){return localStorage.removeItem("id_token")}function l(e){return localStorage.setItem("id_token",e)}var c={aapURL:"https://api.aai.ebi.ac.uk",tokenGetter:s,tokenRemover:u,tokenUpdater:l},p=function(){function e(e,t,n){var o=this;this._rendererFactory=e,this._tokenService=t,this.config=n,this._credentials=new i.BehaviorSubject(null),this._loginCallbacks=[],this._logoutCallbacks=[],this._timeoutID=null,this._commKeyName="AngularAapAuthUpdated",this._commKeyUpdater=function(){return localStorage.setItem(o._commKeyName,""+(new Date).getTime())},this._domain=encodeURIComponent(window.location.origin),this._appURL=n.aapURL.replace(/\/$/,""),this._storageUpdater=n.tokenUpdater,n.tokenRemover?this._storageRemover=n.tokenRemover:this._storageRemover=function(){return n.tokenUpdater(null)};var r=this._rendererFactory.createRenderer(null,null);this._listenLoginMessage(r),this._listenChangesFromOtherWindows(r),this._updateCredentials()}return e.prototype.isAuthenticated=function(){return this._credentials.asObservable().pipe(o.map(function(e){return!!e}))},e.prototype.credentials=function(){return this._credentials.asObservable()},e.prototype.realname=function(){return this._credentials.asObservable().pipe(o.map(function(e){return e?e.realname:null}))},e.prototype.username=function(){return this._credentials.asObservable().pipe(o.map(function(e){return e?e.username:null}))},e.prototype.token=function(){return this._credentials.asObservable().pipe(o.map(function(e){return e?e.token:null}))},e.prototype.windowOpen=function(e,t,n,o,r){if(void 0===t&&(t=650),void 0===n&&(n=1e3),void 0===o&&(o=-1),void 0===r&&(r=-1),r<0){var i=screen.width;t<i&&(r=Math.round(i/2-t/2))}if(o<0){var a=screen.height;n<a&&(o=Math.round(a/2-n/2))}var s=["width="+t,"height="+n,"left="+r,"top="+o,"personalbar=no","toolbar=no","scrollbars=yes","resizable=yes","directories=no","location=no","menubar=no","titlebar=no","toolbar=no"],u=window.open(this.getSSOURL(e),"Sign in to Elixir",s.join(","));u&&u.focus()},e.prototype.tabOpen=function(e){var t=window.open(this.getSSOURL(e),"Sign in to Elixir");t&&t.focus()},e.prototype.getSSOURL=function(t){var e="";return t&&(this._filterLoginOptions(t),e=Object.keys(t).map(function(e){return[e,t[e]]}).reduce(function(e,t){return e+"&"+t[0]+"="+t[1]},"")),this._appURL+"/sso?from="+this._domain+e},e.prototype._filterLoginOptions=function(e){if(-1<Object.keys(e).indexOf("ttl")){var t=+e.ttl;1440<t?(window.console.error("Login requested with an expiration longer than 1440 minutes! This is not allowed."),window.console.error("Expiration request reset to 1440 minutes."),e.ttl="1440"):60<t&&window.console.warn("Login requested with an expiration longer than 60 minutes!")}},e.prototype.logOut=function(){this._storageRemover(),this._updateCredentials(),this._commKeyUpdater()},e.prototype.addLogInEventListener=function(e){return this._loginCallbacks.push(e)},e.prototype.removeLogInEventListener=function(e){return delete this._loginCallbacks[e-1]},e.prototype.addLogOutEventListener=function(e){return this._logoutCallbacks.push(e)},e.prototype.removeLogOutEventListener=function(e){return delete this._logoutCallbacks[e-1]},e.prototype._listenLoginMessage=function(e){var t=this;e.listen("window","message",function(e){t.messageIsAcceptable(e)&&(t._storageUpdater(e.data),e.source.close(),t._updateCredentials(),t._commKeyUpdater())})},e.prototype._listenChangesFromOtherWindows=function(e){var t=this;e.listen("window","storage",function(e){e.key===t._commKeyName&&t._updateCredentials()})},e.prototype.messageIsAcceptable=function(e){return e.origin===this._appURL},e.prototype._updateCredentials=function(){var e=this,t=this._loggedIn();if(this._timeoutID&&window.clearTimeout(this._timeoutID),t){this._credentials.next({realname:this._getRealName(),username:this._getUserName(),token:this._getToken()}),this._loginCallbacks.map(function(e){return e&&e()});var n=+this._tokenService.getTokenExpirationDate()-+new Date;this._timeoutID=window.setTimeout(function(){return e.logOut()},n)}else this._storageRemover(),this._credentials.next(null),this._logoutCallbacks.map(function(e){return e&&e()})},e.prototype._loggedIn=function(){return this._tokenService.isTokenValid()},e.prototype._getToken=function(){return this._tokenService.getToken()},e.prototype._getUserName=function(){return this._tokenService.getClaim("email",null)},e.prototype._getRealName=function(){return this._tokenService.getClaim("name",null)},e}();p.decorators=[{type:t.Injectable}],p.ctorParameters=function(){return[{type:t.RendererFactory2},{type:r},{type:undefined,decorators:[{type:t.Inject,args:[a]}]}]};var d=function(){function t(e){if(e)throw new Error("AuthModule is already loaded. It should only be imported in your application's main module.")}return t.forRoot=function(e){return{ngModule:t,providers:[r,{provide:a,useValue:e||c},p]}},t}();d.decorators=[{type:t.NgModule,args:[{}]}],d.ctorParameters=function(){return[{type:d,decorators:[{type:t.Optional},{type:t.SkipSelf}]}]},e.AuthModule=d,e.AuthService=p,e.TokenService=r,e.ɵb=a,e.ɵf=c,e.ɵc=s,e.ɵd=u,e.ɵe=l,Object.defineProperty(e,"__esModule",{value:!0})}); | ||
//# sourceMappingURL=angular-aap-auth.umd.min.js.map | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core"),require("@auth0/angular-jwt"),require("rxjs"),require("rxjs/operators")):"function"==typeof define&&define.amd?define("angular-aap-auth",["exports","@angular/core","@auth0/angular-jwt","rxjs","rxjs/operators"],t):t(e["angular-aap-auth"]={},e.ng.core,e.angularJwt,e.RxJS,e.rxjs.operators)}(this,function(e,n,t,i,o){"use strict";var r=function(){function e(e){this._jwt=e}return e.prototype.getToken=function(){return this._jwt.tokenGetter()},e.prototype.getTokenExpirationDate=function(){try{return this._jwt.getTokenExpirationDate()}catch(e){return null}},e.prototype.isTokenValid=function(){try{return!this._jwt.isTokenExpired()}catch(e){return!1}},e.prototype.getClaim=function(e,t){try{var n=this._jwt.decodeToken()[e];return n===undefined?t:n}catch(o){return t}},e.decorators=[{type:n.Injectable}],e.ctorParameters=function(){return[{type:t.JwtHelperService}]},e}(),a=new n.InjectionToken("AAP_CONFIG");function s(){return localStorage.getItem("id_token")||""}function u(){return localStorage.removeItem("id_token")}function l(e){return localStorage.setItem("id_token",e)}var c={aapURL:"https://api.aai.ebi.ac.uk",tokenGetter:s,tokenRemover:u,tokenUpdater:l},p=function(){function e(e,t,n){var o=this;this._rendererFactory=e,this._tokenService=t,this.config=n,this._credentials=new i.BehaviorSubject(null),this._loginCallbacks=[],this._logoutCallbacks=[],this._timeoutID=null,this._commKeyName="AngularAapAuthUpdated",this._commKeyUpdater=function(){return localStorage.setItem(o._commKeyName,""+(new Date).getTime())},this._domain=encodeURIComponent(window.location.origin),this._appURL=n.aapURL.replace(/\/$/,""),this._storageUpdater=n.tokenUpdater,n.tokenRemover?this._storageRemover=n.tokenRemover:this._storageRemover=function(){return n.tokenUpdater(null)};var r=this._rendererFactory.createRenderer(null,null);this._listenLoginMessage(r),this._listenChangesFromOtherWindows(r),this._updateCredentials()}return e.prototype.isAuthenticated=function(){return this._credentials.asObservable().pipe(o.map(function(e){return!!e}))},e.prototype.credentials=function(){return this._credentials.asObservable()},e.prototype.realname=function(){return this._credentials.asObservable().pipe(o.map(function(e){return e?e.realname:null}))},e.prototype.username=function(){return this._credentials.asObservable().pipe(o.map(function(e){return e?e.username:null}))},e.prototype.token=function(){return this._credentials.asObservable().pipe(o.map(function(e){return e?e.token:null}))},e.prototype.windowOpen=function(e,t,n,o,r){if(void 0===t&&(t=650),void 0===n&&(n=1e3),void 0===o&&(o=-1),void 0===r&&(r=-1),r<0){var i=screen.width;t<i&&(r=Math.round(i/2-t/2))}if(o<0){var a=screen.height;n<a&&(o=Math.round(a/2-n/2))}var s=["width="+t,"height="+n,"left="+r,"top="+o,"personalbar=no","toolbar=no","scrollbars=yes","resizable=yes","directories=no","location=no","menubar=no","titlebar=no","toolbar=no"],u=window.open(this.getSSOURL(e),"Sign in to Elixir",s.join(","));u&&u.focus()},e.prototype.tabOpen=function(e){var t=window.open(this.getSSOURL(e),"Sign in to Elixir");t&&t.focus()},e.prototype.getSSOURL=function(t){var e="";return t&&(this._filterLoginOptions(t),e=Object.keys(t).map(function(e){return[e,t[e]]}).reduce(function(e,t){return e+"&"+t[0]+"="+t[1]},"")),this._appURL+"/sso?from="+this._domain+e},e.prototype._filterLoginOptions=function(e){if(-1<Object.keys(e).indexOf("ttl")){var t=+e.ttl;1440<t?(window.console.error("Login requested with an expiration longer than 1440 minutes! This is not allowed."),window.console.error("Expiration request reset to 1440 minutes."),e.ttl="1440"):60<t&&window.console.warn("Login requested with an expiration longer than 60 minutes!")}},e.prototype.logOut=function(){this._storageRemover(),this._updateCredentials(),this._commKeyUpdater()},e.prototype.addLogInEventListener=function(e){return this._loginCallbacks.push(e)},e.prototype.removeLogInEventListener=function(e){return delete this._loginCallbacks[e-1]},e.prototype.addLogOutEventListener=function(e){return this._logoutCallbacks.push(e)},e.prototype.removeLogOutEventListener=function(e){return delete this._logoutCallbacks[e-1]},e.prototype._listenLoginMessage=function(e){var t=this;e.listen("window","message",function(e){t.messageIsAcceptable(e)&&(t._storageUpdater(e.data),e.source.close(),t._updateCredentials(),t._commKeyUpdater())})},e.prototype._listenChangesFromOtherWindows=function(e){var t=this;e.listen("window","storage",function(e){e.key===t._commKeyName&&t._updateCredentials()})},e.prototype.messageIsAcceptable=function(e){return e.origin===this._appURL},e.prototype._updateCredentials=function(){var e=this,t=this._loggedIn();if(this._timeoutID&&window.clearTimeout(this._timeoutID),t){this._credentials.next({realname:this._getRealName(),username:this._getUserName(),token:this._getToken()}),this._loginCallbacks.map(function(e){return e&&e()});var n=+this._tokenService.getTokenExpirationDate()-+new Date;this._timeoutID=window.setTimeout(function(){return e.logOut()},n)}else this._storageRemover(),this._credentials.next(null),this._logoutCallbacks.map(function(e){return e&&e()})},e.prototype._loggedIn=function(){return this._tokenService.isTokenValid()},e.prototype._getToken=function(){return this._tokenService.getToken()},e.prototype._getUserName=function(){return this._tokenService.getClaim("email",null)},e.prototype._getRealName=function(){return this._tokenService.getClaim("name",null)},e.decorators=[{type:n.Injectable}],e.ctorParameters=function(){return[{type:n.RendererFactory2},{type:r},{type:undefined,decorators:[{type:n.Inject,args:[a]}]}]},e}(),d=function(){function t(e){if(e)throw new Error("AuthModule is already loaded. It should only be imported in your application's main module.")}return t.forRoot=function(e){return{ngModule:t,providers:[r,{provide:a,useValue:e||c},p]}},t.decorators=[{type:n.NgModule,args:[{}]}],t.ctorParameters=function(){return[{type:t,decorators:[{type:n.Optional},{type:n.SkipSelf}]}]},t}();e.AuthModule=d,e.AuthService=p,e.TokenService=r,e.ɵb=a,e.ɵf=c,e.ɵc=s,e.ɵd=u,e.ɵe=l,Object.defineProperty(e,"__esModule",{value:!0})}); | ||
//# sourceMappingURL=angular-aap-auth.umd.min.js.map |
/** | ||
* Copyright 2017 EMBL - European Bioinformatics Institute | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
* this file except in compliance with the License. You may obtain a copy of the | ||
* License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed | ||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
import { Injectable, InjectionToken, Inject, RendererFactory2, NgModule, Optional, SkipSelf } from '@angular/core'; | ||
import { JwtHelperService } from '@auth0/angular-jwt'; | ||
import { BehaviorSubject } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
/** | ||
* @fileoverview added by tsickle | ||
@@ -26,511 +6,7 @@ * @suppress {checkTypes} checked by tsc | ||
/** | ||
* The purpose of this very simple service is to interface between the | ||
* AuthService and the specific token manipulation routing of JwtHelperService. | ||
* In this way, if in the future we want to replace JwtHelperService by | ||
* another service, AuthService doesn't need to be modified, only this service. | ||
*/ | ||
class TokenService { | ||
/** | ||
* @param {?} _jwt | ||
*/ | ||
constructor(_jwt) { | ||
this._jwt = _jwt; | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
getToken() { | ||
return this._jwt.tokenGetter(); | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
getTokenExpirationDate() { | ||
try { | ||
return this._jwt.getTokenExpirationDate(); | ||
} | ||
catch (/** @type {?} */ e) { | ||
return null; | ||
} | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
isTokenValid() { | ||
try { | ||
return !this._jwt.isTokenExpired(); | ||
} | ||
catch (/** @type {?} */ error) { | ||
return false; | ||
} | ||
} | ||
/** | ||
* Get claims from the token. | ||
* | ||
* @template T, C | ||
* @param {?} claim The name of the claim | ||
* @param {?} defaultValue The default value returned in case of error | ||
* | ||
* @return {?} claim or default value | ||
*/ | ||
getClaim(claim, defaultValue) { | ||
try { | ||
const /** @type {?} */ value = /** @type {?} */ (this._jwt.decodeToken()[claim]); | ||
if (value === undefined) { | ||
return defaultValue; | ||
} | ||
return value; | ||
} | ||
catch (/** @type {?} */ e) { | ||
return defaultValue; | ||
} | ||
} | ||
} | ||
TokenService.decorators = [ | ||
{ type: Injectable }, | ||
]; | ||
/** @nocollapse */ | ||
TokenService.ctorParameters = () => [ | ||
{ type: JwtHelperService, }, | ||
]; | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
/** | ||
* @record | ||
*/ | ||
const AAP_CONFIG = new InjectionToken('AAP_CONFIG'); | ||
/** | ||
* @return {?} | ||
*/ | ||
function getToken() { | ||
return localStorage.getItem('id_token') || ''; | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
function removeToken() { | ||
return localStorage.removeItem('id_token'); | ||
} | ||
/** | ||
* @param {?} newToken | ||
* @return {?} | ||
*/ | ||
function updateToken(newToken) { | ||
return localStorage.setItem('id_token', newToken); | ||
} | ||
const DEFAULT_CONF = { | ||
aapURL: 'https://api.aai.ebi.ac.uk', | ||
tokenGetter: getToken, | ||
tokenRemover: removeToken, | ||
tokenUpdater: updateToken | ||
}; | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
/** | ||
* @record | ||
*/ | ||
/** | ||
* @record | ||
*/ | ||
class AuthService { | ||
/** | ||
* @param {?} _rendererFactory | ||
* @param {?} _tokenService | ||
* @param {?} config | ||
*/ | ||
constructor(_rendererFactory, _tokenService, config) { | ||
this._rendererFactory = _rendererFactory; | ||
this._tokenService = _tokenService; | ||
this.config = config; | ||
this._credentials = new BehaviorSubject(null); | ||
this._loginCallbacks = []; | ||
this._logoutCallbacks = []; | ||
this._timeoutID = null; | ||
this._commKeyName = 'AngularAapAuthUpdated'; | ||
this._commKeyUpdater = () => localStorage.setItem(this._commKeyName, '' + new Date().getTime()); | ||
this._domain = encodeURIComponent(window.location.origin); | ||
this._appURL = config.aapURL.replace(/\/$/, ''); | ||
this._storageUpdater = config.tokenUpdater; | ||
if (config.tokenRemover) { | ||
this._storageRemover = config.tokenRemover; | ||
} | ||
else { | ||
this._storageRemover = () => config.tokenUpdater(null); | ||
} | ||
const /** @type {?} */ renderer = this._rendererFactory.createRenderer(null, null); | ||
this._listenLoginMessage(renderer); | ||
this._listenChangesFromOtherWindows(renderer); | ||
this._updateCredentials(); // TODO: experiment with setTimeOut | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
isAuthenticated() { | ||
return this._credentials.asObservable().pipe(map(credentials => credentials ? true : false)); | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
credentials() { | ||
return this._credentials.asObservable(); | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
realname() { | ||
return this._credentials.asObservable().pipe(map(credentials => credentials ? credentials.realname : null)); | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
username() { | ||
return this._credentials.asObservable().pipe(map(credentials => credentials ? credentials.username : null)); | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
token() { | ||
return this._credentials.asObservable().pipe(map(credentials => credentials ? credentials.token : null)); | ||
} | ||
/** | ||
* Functions that opens a window instead of a tab. | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} loginOptions Options passed as URL parameters to the SSO. | ||
* @param {?=} width Pixel width of the login window. | ||
* @param {?=} height Pixel height of the login window. | ||
* @param {?=} top Position of the top corners. If it is a negative | ||
* number it centres the login window on the screen. | ||
* @param {?=} left Position of the left corners. If it is a negative | ||
* number it centres the login window on the screen. | ||
* @return {?} | ||
*/ | ||
windowOpen(loginOptions, width = 650, height = 1000, top = -1, left = -1) { | ||
if (left < 0) { | ||
const /** @type {?} */ screenWidth = screen.width; | ||
if (screenWidth > width) { | ||
left = Math.round(screenWidth / 2 - width / 2); | ||
} | ||
} | ||
if (top < 0) { | ||
const /** @type {?} */ screenHeight = screen.height; | ||
if (screenHeight > height) { | ||
top = Math.round(screenHeight / 2 - height / 2); | ||
} | ||
} | ||
const /** @type {?} */ windowOptions = [ | ||
`width=${width}`, | ||
`height=${height}`, | ||
`left=${left}`, | ||
`top=${top}`, | ||
'personalbar=no', | ||
'toolbar=no', | ||
'scrollbars=yes', | ||
'resizable=yes', | ||
'directories=no', | ||
'location=no', | ||
'menubar=no', | ||
'titlebar=no', | ||
'toolbar=no' | ||
]; | ||
const /** @type {?} */ loginWindow = window.open(this.getSSOURL(loginOptions), 'Sign in to Elixir', windowOptions.join(',')); | ||
if (loginWindow) { | ||
loginWindow.focus(); | ||
} | ||
} | ||
/** | ||
* Functions that opens a tab (in modern browser). | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} loginOptions Options passed as URL parameters to the SSO. | ||
* @return {?} | ||
*/ | ||
tabOpen(loginOptions) { | ||
const /** @type {?} */ loginWindow = window.open(this.getSSOURL(loginOptions), 'Sign in to Elixir'); | ||
if (loginWindow) { | ||
loginWindow.focus(); | ||
} | ||
} | ||
/** | ||
* Produces a URL that allows logging into the single sign on (SSO) page. | ||
* The URL cans be opened in a new tab using target="_blank", | ||
* or in a new window using window.open(). | ||
* | ||
* See method _filterLoginOptions regarding security risks of certain | ||
* LoginOptions. | ||
* | ||
* @param {?=} options | ||
* @return {?} The SSO URL. | ||
* | ||
*/ | ||
getSSOURL(options) { | ||
let /** @type {?} */ extra = ''; | ||
if (options) { | ||
this._filterLoginOptions(options); | ||
extra = Object.keys(options) | ||
.map(key => [key, options[key]]) | ||
.reduce((accumulator, keyvalue) => `${accumulator}&${keyvalue[0]}=${keyvalue[1]}`, ''); | ||
} | ||
return `${this._appURL}/sso?from=${this._domain}${extra}`; | ||
} | ||
/** | ||
* Filters options that are unsecure. | ||
* | ||
* See the advance options that can be requested through the options parameter: | ||
* https://api.aai.ebi.ac.uk/docs/authentication/authentication.index.html#_common_attributes | ||
* | ||
* The time to live paramenter (ttl) default value is 60 minutes. It is a | ||
* big security risk to request longer ttl. If a third party gets hold of | ||
* such token, means that they could use it for a day, week, year | ||
* (essentially, like having the username/password). | ||
* | ||
* @param {?} options | ||
* @return {?} | ||
*/ | ||
_filterLoginOptions(options) { | ||
if (Object.keys(options).indexOf('ttl') > -1) { | ||
const /** @type {?} */ ttl = +options['ttl']; | ||
const /** @type {?} */ softLimit = 60; | ||
const /** @type {?} */ hardLimit = 60 * 24; | ||
if (ttl > hardLimit) { | ||
window.console.error(`Login requested with an expiration longer than ${hardLimit} minutes! This is not allowed.`); | ||
window.console.error(`Expiration request reset to ${hardLimit} minutes.`); | ||
options['ttl'] = '' + hardLimit; | ||
} | ||
else if (ttl > softLimit) { | ||
window.console.warn(`Login requested with an expiration longer than ${softLimit} minutes!`); | ||
} | ||
} | ||
} | ||
/** | ||
* Functions that logs out the user. | ||
* It triggers the logout callbacks. | ||
* It is an arrow function (lambda) because in that way it has a reference | ||
* to 'this' when used in setTimeout call. | ||
* @return {?} | ||
*/ | ||
logOut() { | ||
this._storageRemover(); | ||
this._updateCredentials(); | ||
// Triggers updating other windows | ||
this._commKeyUpdater(); | ||
} | ||
/** | ||
* Add a callback to the LogIn event. | ||
* | ||
* @param {?} callback The Function called when the login event is triggered and the | ||
* JWT token is received and accepted. | ||
* | ||
* @return {?} The event registration id (necessary to unregister the event). | ||
*/ | ||
addLogInEventListener(callback) { | ||
return this._loginCallbacks.push(callback); | ||
} | ||
/** | ||
* Remove a callback from the LogIn event. | ||
* | ||
* @param {?} id The id given when event listener was added. | ||
* | ||
* @return {?} true when remove successfully, false otherwise. | ||
*/ | ||
removeLogInEventListener(id) { | ||
return delete this._loginCallbacks[id - 1]; | ||
} | ||
/** | ||
* Add a callback to the LogOut event. | ||
* | ||
* @param {?} callback The Function called when the logout event is triggered and the | ||
* JWT token is received and accepted. | ||
* | ||
* @return {?} The registration id (necessary to unregister the event). | ||
*/ | ||
addLogOutEventListener(callback) { | ||
return this._logoutCallbacks.push(callback); | ||
} | ||
/** | ||
* Remove a callback from the LogOut event. | ||
* | ||
* @param {?} id The id given when event listener was added. | ||
* | ||
* @return {?} true when remove successfully, false otherwise. | ||
*/ | ||
removeLogOutEventListener(id) { | ||
return delete this._logoutCallbacks[id - 1]; | ||
} | ||
/** | ||
* Listen for login messages from other windows. | ||
* These messages contain the tokens from the AAP. | ||
* If a token is received then the callbacks are triggered. | ||
* @param {?} renderer | ||
* @return {?} | ||
*/ | ||
_listenLoginMessage(renderer) { | ||
renderer.listen('window', 'message', (event) => { | ||
if (!this.messageIsAcceptable(event)) { | ||
return; | ||
} | ||
this._storageUpdater(event.data); | ||
event.source.close(); | ||
this._updateCredentials(); | ||
// Triggers updating other windows | ||
this._commKeyUpdater(); | ||
}); | ||
} | ||
/** | ||
* Listen to changes in the token from *other* windows. | ||
* | ||
* For inter-window communication messages are transmitted trough changes | ||
* on a dummy storage key property: '_commKeyName'. | ||
* | ||
* Notice that changes in the '_commKeyName' produced by this class doesn't | ||
* trigger this event. | ||
* @param {?} renderer | ||
* @return {?} | ||
*/ | ||
_listenChangesFromOtherWindows(renderer) { | ||
renderer.listen('window', 'storage', (event) => { | ||
if (event.key === this._commKeyName) { | ||
this._updateCredentials(); | ||
} | ||
}); | ||
} | ||
/** | ||
* Check if the message is coming from the same domain we use to generate | ||
* the SSO URL, otherwise it's iffy and shouldn't trust it. | ||
* @param {?} event | ||
* @return {?} | ||
*/ | ||
messageIsAcceptable(event) { | ||
return event.origin === this._appURL; | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
_updateCredentials() { | ||
const /** @type {?} */ isAuthenticated = this._loggedIn(); | ||
if (this._timeoutID) { | ||
window.clearTimeout(this._timeoutID); | ||
} | ||
if (isAuthenticated) { | ||
this._credentials.next({ | ||
realname: /** @type {?} */ (this._getRealName()), | ||
username: /** @type {?} */ (this._getUserName()), | ||
token: /** @type {?} */ (this._getToken()) | ||
}); | ||
this._loginCallbacks.map(callback => callback && callback()); | ||
// Schedule future logout event base on token expiration | ||
const /** @type {?} */ expireDate = /** @type {?} */ (this._tokenService.getTokenExpirationDate()); | ||
// Coercing dates to numbers with the unary operator '+' | ||
const /** @type {?} */ delay = +expireDate - +new Date(); | ||
this._timeoutID = window.setTimeout(() => this.logOut(), delay); | ||
} | ||
else { | ||
this._storageRemover(); // Cleanup possible left behind token | ||
this._credentials.next(null); | ||
this._logoutCallbacks.map(callback => callback && callback()); | ||
} | ||
} | ||
/** | ||
* Check if there's a user logging on and whether the token is still valid. | ||
* | ||
* @return {?} Whether the user user is authenticated or not. | ||
*/ | ||
_loggedIn() { | ||
return this._tokenService.isTokenValid(); | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
_getToken() { | ||
return this._tokenService.getToken(); | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
_getUserName() { | ||
return this._tokenService.getClaim('email', null); | ||
} | ||
/** | ||
* @return {?} | ||
*/ | ||
_getRealName() { | ||
return this._tokenService.getClaim('name', null); | ||
} | ||
} | ||
AuthService.decorators = [ | ||
{ type: Injectable }, | ||
]; | ||
/** @nocollapse */ | ||
AuthService.ctorParameters = () => [ | ||
{ type: RendererFactory2, }, | ||
{ type: TokenService, }, | ||
{ type: undefined, decorators: [{ type: Inject, args: [AAP_CONFIG,] },] }, | ||
]; | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
class AuthModule { | ||
/** | ||
* @param {?} parentModule | ||
*/ | ||
constructor(parentModule) { | ||
if (parentModule) { | ||
throw new Error('AuthModule is already loaded. It should only be imported in your application\'s main module.'); | ||
} | ||
} | ||
/** | ||
* @param {?=} options | ||
* @return {?} | ||
*/ | ||
static forRoot(options) { | ||
return { | ||
ngModule: AuthModule, | ||
providers: [ | ||
TokenService, | ||
{ | ||
provide: AAP_CONFIG, | ||
useValue: options ? options : DEFAULT_CONF | ||
}, | ||
AuthService | ||
] | ||
}; | ||
} | ||
} | ||
AuthModule.decorators = [ | ||
{ type: NgModule, args: [{},] }, | ||
]; | ||
/** @nocollapse */ | ||
AuthModule.ctorParameters = () => [ | ||
{ type: AuthModule, decorators: [{ type: Optional }, { type: SkipSelf },] }, | ||
]; | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
/** | ||
* Generated bundle index. Do not edit. | ||
*/ | ||
export { AuthModule, AuthService, TokenService } from './public_api'; | ||
export { AAP_CONFIG as ɵb, DEFAULT_CONF as ɵf, getToken as ɵc, removeToken as ɵd, updateToken as ɵe } from './app/modules/auth/auth.config'; | ||
export { AuthModule, AuthService, TokenService, AAP_CONFIG as ɵb, DEFAULT_CONF as ɵf, getToken as ɵc, removeToken as ɵd, updateToken as ɵe }; | ||
//# sourceMappingURL=angular-aap-auth.js.map | ||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1hYXAtYXV0aC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2FuZ3VsYXItYWFwLWF1dGgvIiwic291cmNlcyI6WyJhbmd1bGFyLWFhcC1hdXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFJQSxzREFBYyxjQUFjLENBQUM7QUFFN0IsT0FBTyxFQUFDLFVBQVUsSUFBSSxFQUFFLEVBQWtCLFlBQVksSUFBSSxFQUFFLEVBQUMsUUFBUSxJQUFJLEVBQUUsRUFBQyxXQUFXLElBQUksRUFBRSxFQUFDLFdBQVcsSUFBSSxFQUFFLEVBQUMsTUFBTSxnQ0FBZ0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWNfYXBpJztcblxuZXhwb3J0IHtBQVBfQ09ORklHIGFzIMm1YixBdXRoQ29uZmlnIGFzIMm1YSxERUZBVUxUX0NPTkYgYXMgybVmLGdldFRva2VuIGFzIMm1YyxyZW1vdmVUb2tlbiBhcyDJtWQsdXBkYXRlVG9rZW4gYXMgybVlfSBmcm9tICcuL2FwcC9tb2R1bGVzL2F1dGgvYXV0aC5jb25maWcnOyJdfQ== |
@@ -1,288 +0,11 @@ | ||
import { Injectable, InjectionToken, Inject, RendererFactory2, NgModule, Optional, SkipSelf } from '@angular/core'; | ||
import { JwtHelperService } from '@auth0/angular-jwt'; | ||
import { BehaviorSubject } from 'rxjs'; | ||
import { map } from 'rxjs/operators'; | ||
/** | ||
* @fileoverview added by tsickle | ||
* @suppress {checkTypes} checked by tsc | ||
*/ | ||
/** | ||
* Generated bundle index. Do not edit. | ||
*/ | ||
export { AuthModule, AuthService, TokenService } from './public_api'; | ||
export { AAP_CONFIG as ɵb, DEFAULT_CONF as ɵf, getToken as ɵc, removeToken as ɵd, updateToken as ɵe } from './app/modules/auth/auth.config'; | ||
var TokenService = /** @class */ (function () { | ||
function TokenService(_jwt) { | ||
this._jwt = _jwt; | ||
} | ||
TokenService.prototype.getToken = function () { | ||
return this._jwt.tokenGetter(); | ||
}; | ||
TokenService.prototype.getTokenExpirationDate = function () { | ||
try { | ||
return this._jwt.getTokenExpirationDate(); | ||
} | ||
catch (e) { | ||
return null; | ||
} | ||
}; | ||
TokenService.prototype.isTokenValid = function () { | ||
try { | ||
return !this._jwt.isTokenExpired(); | ||
} | ||
catch (error) { | ||
return false; | ||
} | ||
}; | ||
TokenService.prototype.getClaim = function (claim, defaultValue) { | ||
try { | ||
var value = (this._jwt.decodeToken()[claim]); | ||
if (value === undefined) { | ||
return defaultValue; | ||
} | ||
return value; | ||
} | ||
catch (e) { | ||
return defaultValue; | ||
} | ||
}; | ||
return TokenService; | ||
}()); | ||
TokenService.decorators = [ | ||
{ type: Injectable }, | ||
]; | ||
TokenService.ctorParameters = function () { return [ | ||
{ type: JwtHelperService, }, | ||
]; }; | ||
var AAP_CONFIG = new InjectionToken('AAP_CONFIG'); | ||
function getToken() { | ||
return localStorage.getItem('id_token') || ''; | ||
} | ||
function removeToken() { | ||
return localStorage.removeItem('id_token'); | ||
} | ||
function updateToken(newToken) { | ||
return localStorage.setItem('id_token', newToken); | ||
} | ||
var DEFAULT_CONF = { | ||
aapURL: 'https://api.aai.ebi.ac.uk', | ||
tokenGetter: getToken, | ||
tokenRemover: removeToken, | ||
tokenUpdater: updateToken | ||
}; | ||
var AuthService = /** @class */ (function () { | ||
function AuthService(_rendererFactory, _tokenService, config) { | ||
var _this = this; | ||
this._rendererFactory = _rendererFactory; | ||
this._tokenService = _tokenService; | ||
this.config = config; | ||
this._credentials = new BehaviorSubject(null); | ||
this._loginCallbacks = []; | ||
this._logoutCallbacks = []; | ||
this._timeoutID = null; | ||
this._commKeyName = 'AngularAapAuthUpdated'; | ||
this._commKeyUpdater = function () { return localStorage.setItem(_this._commKeyName, '' + new Date().getTime()); }; | ||
this._domain = encodeURIComponent(window.location.origin); | ||
this._appURL = config.aapURL.replace(/\/$/, ''); | ||
this._storageUpdater = config.tokenUpdater; | ||
if (config.tokenRemover) { | ||
this._storageRemover = config.tokenRemover; | ||
} | ||
else { | ||
this._storageRemover = function () { return config.tokenUpdater(null); }; | ||
} | ||
var renderer = this._rendererFactory.createRenderer(null, null); | ||
this._listenLoginMessage(renderer); | ||
this._listenChangesFromOtherWindows(renderer); | ||
this._updateCredentials(); | ||
} | ||
AuthService.prototype.isAuthenticated = function () { | ||
return this._credentials.asObservable().pipe(map(function (credentials) { return credentials ? true : false; })); | ||
}; | ||
AuthService.prototype.credentials = function () { | ||
return this._credentials.asObservable(); | ||
}; | ||
AuthService.prototype.realname = function () { | ||
return this._credentials.asObservable().pipe(map(function (credentials) { return credentials ? credentials.realname : null; })); | ||
}; | ||
AuthService.prototype.username = function () { | ||
return this._credentials.asObservable().pipe(map(function (credentials) { return credentials ? credentials.username : null; })); | ||
}; | ||
AuthService.prototype.token = function () { | ||
return this._credentials.asObservable().pipe(map(function (credentials) { return credentials ? credentials.token : null; })); | ||
}; | ||
AuthService.prototype.windowOpen = function (loginOptions, width, height, top, left) { | ||
if (width === void 0) { width = 650; } | ||
if (height === void 0) { height = 1000; } | ||
if (top === void 0) { top = -1; } | ||
if (left === void 0) { left = -1; } | ||
if (left < 0) { | ||
var screenWidth = screen.width; | ||
if (screenWidth > width) { | ||
left = Math.round(screenWidth / 2 - width / 2); | ||
} | ||
} | ||
if (top < 0) { | ||
var screenHeight = screen.height; | ||
if (screenHeight > height) { | ||
top = Math.round(screenHeight / 2 - height / 2); | ||
} | ||
} | ||
var windowOptions = [ | ||
"width=" + width, | ||
"height=" + height, | ||
"left=" + left, | ||
"top=" + top, | ||
'personalbar=no', | ||
'toolbar=no', | ||
'scrollbars=yes', | ||
'resizable=yes', | ||
'directories=no', | ||
'location=no', | ||
'menubar=no', | ||
'titlebar=no', | ||
'toolbar=no' | ||
]; | ||
var loginWindow = window.open(this.getSSOURL(loginOptions), 'Sign in to Elixir', windowOptions.join(',')); | ||
if (loginWindow) { | ||
loginWindow.focus(); | ||
} | ||
}; | ||
AuthService.prototype.tabOpen = function (loginOptions) { | ||
var loginWindow = window.open(this.getSSOURL(loginOptions), 'Sign in to Elixir'); | ||
if (loginWindow) { | ||
loginWindow.focus(); | ||
} | ||
}; | ||
AuthService.prototype.getSSOURL = function (options) { | ||
var extra = ''; | ||
if (options) { | ||
this._filterLoginOptions(options); | ||
extra = Object.keys(options) | ||
.map(function (key) { return [key, options[key]]; }) | ||
.reduce(function (accumulator, keyvalue) { return accumulator + "&" + keyvalue[0] + "=" + keyvalue[1]; }, ''); | ||
} | ||
return this._appURL + "/sso?from=" + this._domain + extra; | ||
}; | ||
AuthService.prototype._filterLoginOptions = function (options) { | ||
if (Object.keys(options).indexOf('ttl') > -1) { | ||
var ttl = +options['ttl']; | ||
var softLimit = 60; | ||
var hardLimit = 60 * 24; | ||
if (ttl > hardLimit) { | ||
window.console.error("Login requested with an expiration longer than " + hardLimit + " minutes! This is not allowed."); | ||
window.console.error("Expiration request reset to " + hardLimit + " minutes."); | ||
options['ttl'] = '' + hardLimit; | ||
} | ||
else if (ttl > softLimit) { | ||
window.console.warn("Login requested with an expiration longer than " + softLimit + " minutes!"); | ||
} | ||
} | ||
}; | ||
AuthService.prototype.logOut = function () { | ||
this._storageRemover(); | ||
this._updateCredentials(); | ||
this._commKeyUpdater(); | ||
}; | ||
AuthService.prototype.addLogInEventListener = function (callback) { | ||
return this._loginCallbacks.push(callback); | ||
}; | ||
AuthService.prototype.removeLogInEventListener = function (id) { | ||
return delete this._loginCallbacks[id - 1]; | ||
}; | ||
AuthService.prototype.addLogOutEventListener = function (callback) { | ||
return this._logoutCallbacks.push(callback); | ||
}; | ||
AuthService.prototype.removeLogOutEventListener = function (id) { | ||
return delete this._logoutCallbacks[id - 1]; | ||
}; | ||
AuthService.prototype._listenLoginMessage = function (renderer) { | ||
var _this = this; | ||
renderer.listen('window', 'message', function (event) { | ||
if (!_this.messageIsAcceptable(event)) { | ||
return; | ||
} | ||
_this._storageUpdater(event.data); | ||
event.source.close(); | ||
_this._updateCredentials(); | ||
_this._commKeyUpdater(); | ||
}); | ||
}; | ||
AuthService.prototype._listenChangesFromOtherWindows = function (renderer) { | ||
var _this = this; | ||
renderer.listen('window', 'storage', function (event) { | ||
if (event.key === _this._commKeyName) { | ||
_this._updateCredentials(); | ||
} | ||
}); | ||
}; | ||
AuthService.prototype.messageIsAcceptable = function (event) { | ||
return event.origin === this._appURL; | ||
}; | ||
AuthService.prototype._updateCredentials = function () { | ||
var _this = this; | ||
var isAuthenticated = this._loggedIn(); | ||
if (this._timeoutID) { | ||
window.clearTimeout(this._timeoutID); | ||
} | ||
if (isAuthenticated) { | ||
this._credentials.next({ | ||
realname: (this._getRealName()), | ||
username: (this._getUserName()), | ||
token: (this._getToken()) | ||
}); | ||
this._loginCallbacks.map(function (callback) { return callback && callback(); }); | ||
var expireDate = (this._tokenService.getTokenExpirationDate()); | ||
var delay = +expireDate - +new Date(); | ||
this._timeoutID = window.setTimeout(function () { return _this.logOut(); }, delay); | ||
} | ||
else { | ||
this._storageRemover(); | ||
this._credentials.next(null); | ||
this._logoutCallbacks.map(function (callback) { return callback && callback(); }); | ||
} | ||
}; | ||
AuthService.prototype._loggedIn = function () { | ||
return this._tokenService.isTokenValid(); | ||
}; | ||
AuthService.prototype._getToken = function () { | ||
return this._tokenService.getToken(); | ||
}; | ||
AuthService.prototype._getUserName = function () { | ||
return this._tokenService.getClaim('email', null); | ||
}; | ||
AuthService.prototype._getRealName = function () { | ||
return this._tokenService.getClaim('name', null); | ||
}; | ||
return AuthService; | ||
}()); | ||
AuthService.decorators = [ | ||
{ type: Injectable }, | ||
]; | ||
AuthService.ctorParameters = function () { return [ | ||
{ type: RendererFactory2, }, | ||
{ type: TokenService, }, | ||
{ type: undefined, decorators: [{ type: Inject, args: [AAP_CONFIG,] },] }, | ||
]; }; | ||
var AuthModule = /** @class */ (function () { | ||
function AuthModule(parentModule) { | ||
if (parentModule) { | ||
throw new Error('AuthModule is already loaded. It should only be imported in your application\'s main module.'); | ||
} | ||
} | ||
AuthModule.forRoot = function (options) { | ||
return { | ||
ngModule: AuthModule, | ||
providers: [ | ||
TokenService, | ||
{ | ||
provide: AAP_CONFIG, | ||
useValue: options ? options : DEFAULT_CONF | ||
}, | ||
AuthService | ||
] | ||
}; | ||
}; | ||
return AuthModule; | ||
}()); | ||
AuthModule.decorators = [ | ||
{ type: NgModule, args: [{},] }, | ||
]; | ||
AuthModule.ctorParameters = function () { return [ | ||
{ type: AuthModule, decorators: [{ type: Optional }, { type: SkipSelf },] }, | ||
]; }; | ||
export { AuthModule, AuthService, TokenService, AAP_CONFIG as ɵb, DEFAULT_CONF as ɵf, getToken as ɵc, removeToken as ɵd, updateToken as ɵe }; | ||
//# sourceMappingURL=angular-aap-auth.js.map | ||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1hYXAtYXV0aC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2FuZ3VsYXItYWFwLWF1dGgvIiwic291cmNlcyI6WyJhbmd1bGFyLWFhcC1hdXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFJQSxzREFBYyxjQUFjLENBQUM7QUFFN0IsT0FBTyxFQUFDLFVBQVUsSUFBSSxFQUFFLEVBQWtCLFlBQVksSUFBSSxFQUFFLEVBQUMsUUFBUSxJQUFJLEVBQUUsRUFBQyxXQUFXLElBQUksRUFBRSxFQUFDLFdBQVcsSUFBSSxFQUFFLEVBQUMsTUFBTSxnQ0FBZ0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWNfYXBpJztcblxuZXhwb3J0IHtBQVBfQ09ORklHIGFzIMm1YixBdXRoQ29uZmlnIGFzIMm1YSxERUZBVUxUX0NPTkYgYXMgybVmLGdldFRva2VuIGFzIMm1YyxyZW1vdmVUb2tlbiBhcyDJtWQsdXBkYXRlVG9rZW4gYXMgybVlfSBmcm9tICcuL2FwcC9tb2R1bGVzL2F1dGgvYXV0aC5jb25maWcnOyJdfQ== |
{ | ||
"name": "angular-aap-auth", | ||
"version": "1.0.0-alpha.10", | ||
"version": "1.0.0-alpha.11", | ||
"license": "Apache-2.0", | ||
@@ -31,30 +31,30 @@ "private": false, | ||
"devDependencies": { | ||
"@angular-devkit/build-angular": "~0.6.1", | ||
"@angular/cli": "6.0.1", | ||
"@angular/common": "6.0.2", | ||
"@angular/compiler": "6.0.2", | ||
"@angular/compiler-cli": "6.0.2", | ||
"@angular/core": "6.0.2", | ||
"@angular/language-service": "6.0.2", | ||
"@angular/platform-browser": "6.0.2", | ||
"@angular/platform-browser-dynamic": "6.0.2", | ||
"@angular-devkit/build-angular": "~0.6.8", | ||
"@angular/cli": "6.0.8", | ||
"@angular/common": "6.0.5", | ||
"@angular/compiler": "6.0.5", | ||
"@angular/compiler-cli": "6.0.5", | ||
"@angular/core": "6.0.5", | ||
"@angular/language-service": "6.0.5", | ||
"@angular/platform-browser": "6.0.5", | ||
"@angular/platform-browser-dynamic": "6.0.5", | ||
"@auth0/angular-jwt": "^2.0.0", | ||
"@types/jasmine": "~2.8.7", | ||
"@types/jasmine": "~2.8.8", | ||
"@types/jasminewd2": "~2.0.3", | ||
"@types/node": "~10.1.0", | ||
"@types/node": "~10.3.4", | ||
"codelyzer": "^4.3.0", | ||
"core-js": "^2.5.6", | ||
"core-js": "^2.5.7", | ||
"jasmine-core": "^3.1.0", | ||
"jasmine-spec-reporter": "~4.2.1", | ||
"karma": "~2.0.2", | ||
"karma": "~2.0.3", | ||
"karma-chrome-launcher": "~2.2.0", | ||
"karma-coverage-istanbul-reporter": "^1.4.2", | ||
"karma-coverage-istanbul-reporter": "^2.0.1", | ||
"karma-jasmine": "~1.1.2", | ||
"karma-jasmine-html-reporter": "^1.1.0", | ||
"ng-packagr": "^2.4.4", | ||
"ng-packagr": "^3.0.3", | ||
"npm-check-updates": "^2.14.2", | ||
"protractor": "~5.3.2", | ||
"rxjs": "^6.1.0", | ||
"rxjs-tslint-rules": "^4.2.0", | ||
"ts-node": "~6.0.3", | ||
"rxjs": "^6.2.1", | ||
"rxjs-tslint-rules": "^4.4.2", | ||
"ts-node": "~6.1.1", | ||
"tslint": "~5.10.0", | ||
@@ -66,6 +66,11 @@ "typedoc": "^0.11.1", | ||
"main": "bundles/angular-aap-auth.umd.js", | ||
"module": "esm5/angular-aap-auth.js", | ||
"es2015": "esm2015/angular-aap-auth.js", | ||
"module": "fesm5/angular-aap-auth.js", | ||
"es2015": "fesm2015/angular-aap-auth.js", | ||
"esm5": "esm5/angular-aap-auth.js", | ||
"esm2015": "esm2015/angular-aap-auth.js", | ||
"fesm5": "fesm5/angular-aap-auth.js", | ||
"fesm2015": "fesm2015/angular-aap-auth.js", | ||
"typings": "angular-aap-auth.d.ts", | ||
"metadata": "angular-aap-auth.metadata.json" | ||
"metadata": "angular-aap-auth.metadata.json", | ||
"sideEffects": false | ||
} |
@@ -40,8 +40,12 @@ # angular-aap-auth | ||
import { | ||
AppComponent | ||
} from './app.component'; | ||
import { | ||
AuthModule | ||
} from 'angular-aap-auth'; | ||
import { | ||
JwtModule | ||
} from '@auth0/angular-jwt'; | ||
import { | ||
AppComponent | ||
} from './app.component'; | ||
@NgModule({ | ||
@@ -53,6 +57,6 @@ declarations: [ | ||
BrowserModule, | ||
AuthModule.forRoot(), | ||
JwtModuld.forRoot({ | ||
AuthModule.forRoot(), // Defaults to localStorage `id_token` key. | ||
JwtModule.forRoot({ | ||
config: { | ||
tokenGetter: () => localStorage.getItem( 'id_token') | ||
tokenGetter: () => localStorage.getItem('id_token') | ||
} | ||
@@ -79,3 +83,3 @@ }) | ||
Observable, | ||
} from 'rxjs/Observable'; | ||
} from 'rxjs'; | ||
@@ -130,3 +134,3 @@ import { | ||
Observable, | ||
} from 'rxjs/Observable'; | ||
} from 'rxjs'; | ||
import { | ||
@@ -197,2 +201,5 @@ map | ||
} from 'angular-aap-auth'; | ||
import { | ||
JwtModule | ||
} from '@auth0/angular-jwt'; | ||
@@ -222,3 +229,3 @@ export function getToken(): string { | ||
}), | ||
JwtModuld.forRoot({ | ||
JwtModule.forRoot({ | ||
config: { | ||
@@ -244,3 +251,3 @@ tokenGetter: getToken, | ||
Observable, | ||
} from 'rxjs/Observable'; | ||
} from 'Observable'; | ||
import { | ||
@@ -247,0 +254,0 @@ map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
402875
31
3410
335
1