ngx-gem-spaas
Version:
This library contains services, components, images and styles to provide a unified look and way-of-working throughout GEM SPaaS.
191 lines • 27.7 kB
JavaScript
import { BehaviorSubject, ReplaySubject, Subject } from 'rxjs';
import { Injectable } from '@angular/core';
import { NavigationStart } from '@angular/router';
import { OktaAuth } from '@okta/okta-auth-js';
import { takeUntil } from 'rxjs/operators';
import { OktaUserModel } from "../_models/okta.model";
import { UtilsService } from "./utils.service";
import * as i0 from "@angular/core";
import * as i1 from "./config.service";
import * as i2 from "./local-storage.service";
import * as i3 from "@angular/router";
import * as i4 from "./session-storage.service";
export class OktaService {
constructor(configService, lsService, router, ssService) {
this.configService = configService;
this.lsService = lsService;
this.router = router;
this.ssService = ssService;
this.LS_ACTIVEROUTE = 'activeRoute';
this.SS_ERROR = 'oktaError';
this.oktaError = null;
this.oktaError$ = new BehaviorSubject(null);
this.oktaUserInfo = new OktaUserModel({});
this.oktaUserInfo$ = new ReplaySubject(1);
this.onDestroy$ = new Subject();
this.oktaClientConfig = this.setConfig();
// CLIENT, TOKENPARAMS AND TOKENMANAGER
this.oktaClient = new OktaAuth(this.oktaClientConfig);
this.oktaClient.start(); // as of v5, needs to be started as a service to auto-renew
this.tokenParams = { scopes: this.oktaClientConfig.scopes };
this.tokenManager = this.oktaClient.tokenManager;
this.tokenManager.on('error', (error) => {
// auto-renew failed, usually cuz user deleted cookies or something (no more valid okta session), so sign out
console.log(error);
this.oktaClient.signOut({ postLogoutRedirectUri: null }).catch((err) => console.log(err));
});
// SUBSCRIBE TO ROUTING
this.onRouting();
}
ngOnDestroy() {
this.onDestroy$.next();
this.onDestroy$.complete();
}
// ********************************************************************************************************
// GENERIC STUFF
// ********************************************************************************************************
setConfig() {
const spaasConfig = this.configService.getConfig();
if (!spaasConfig?.oktaConfig) {
throw new Error('please provide a valid Okta configuration via the "forRoot" method of the SpaasModule');
}
if (spaasConfig?.oktaConfig?.url?.slice(-1) === '/') {
throw new Error('the okta url should not have a trailing slash');
}
if (spaasConfig?.oktaConfig?.tenantId.includes('/')) {
throw new Error('the okta tenant id should not contain slashes');
}
return {
clientId: spaasConfig.oktaConfig.clientId,
issuer: spaasConfig.oktaConfig.url + '/oauth2/' + spaasConfig.oktaConfig.tenantId,
pkce: true,
redirectUri: spaasConfig.oktaConfig.withPath ? window.location.origin + window.location.pathname : window.location.origin,
responseType: ['id_token', 'token'],
scopes: ['openid', 'email'].concat(spaasConfig.oktaConfig.additionalScopes || []),
tokenManager: {
storage: 'sessionStorage',
storageKey: spaasConfig.storagePrefix + 'tokens',
expireEarlySeconds: 300
},
transactionManager: {
saveNonceCookie: false,
saveParamsCookie: false,
saveStateCookie: false,
},
};
}
onRouting() {
this.router.events
.pipe(takeUntil(this.onDestroy$))
.subscribe((event) => {
if (event instanceof NavigationStart) {
// set active route here, so we know where to route to after token redirection
if (event.url !== '/') {
this.setActiveRoute(event.url);
}
// BECAUSE WE HANDLE THE CALLBACK BEFORE ROUTING, THE HIDDEN IFRAME REMAINS EMPTY
this.handleRedirect();
}
});
}
// ********************************************************************************************************
// OKTA STUFF
// ********************************************************************************************************
handleRedirect() {
if (this.oktaClient.token.isLoginRedirect() || window.location.search.includes('error=')) {
// IS REDIRECT OR OKTA ERROR
this.updateOktaError(null);
this.parseFromUrl();
}
else if (!this.oktaError) {
// IS REGULAR NAVIGATION: CHECK USER INFO
this.getUserInfoFromToken();
}
}
parseFromUrl() {
this.oktaClient.token.parseFromUrl()
.then((tokenResponse) => {
this.tokenManager.setTokens(tokenResponse.tokens);
// NOW SET USER INFO FROM THE TOKEN
// IT'S THE USER INFO OBSERVABLE THAT OTHER COMPONENTS OR SERVICES SHOULD USE AS INDICATION THAT ALL IS GOOD TO GO
this.getUserInfoFromToken();
})
.catch((err) => {
this.updateOktaError(err);
});
}
getUserInfoFromToken() {
if (this.oktaUserInfo.email) {
return;
}
this.tokenManager.getTokens()
.then((tokens) => {
this.newUserInfo(tokens?.accessToken?.claims);
// set a default url. If it exists, fine, if not, it will force the configured redirects to kick in
this.router.navigate([this.getActiveRoute() || '/home']);
})
.catch(() => {
this.getTokenWithRedirect();
});
}
getTokenWithRedirect() {
this.oktaClient.token.getWithRedirect(this.tokenParams)
.catch((e) => console.log(e));
}
getCachedAccessToken() {
// TO BE USED IN CANACTIVE AND/OR CANLOAD AND/OR HTTP INTERCEPTOR
if (this.oktaClient && this.tokenManager) {
return this.oktaClient.getAccessToken() || '';
}
else {
console.log('should never happen: tokenmanager is null! Nothing left to do but redirect');
this.getTokenWithRedirect();
return '';
}
}
updateOktaError(newState) {
this.oktaError = newState;
this.ssService.setItem(this.SS_ERROR, this.oktaError);
this.newOktaError();
}
forceRetry() {
// METHOD THAT CAN BE CALLED BY WHICHEVER COMPONENT YOU HAVE TO HANDLE/DISPLAY OKTA ERRORS
// FOR EXAMPLE ON A BUTTON CLICK 'TRY AGAIN' SO USER CAN FORCE AN OKTA RETRY
this.updateOktaError(null);
this.getTokenWithRedirect();
}
setActiveRoute(url) {
this.lsService.setItem(this.LS_ACTIVEROUTE, url);
}
getActiveRoute() {
return this.lsService.getItem(this.LS_ACTIVEROUTE) || '';
}
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newUserInfo(userInfo) {
this.oktaUserInfo = new OktaUserModel(userInfo);
this.oktaUserInfo$.next(this.oktaUserInfo);
}
onNewUserInfo() {
return this.oktaUserInfo$.asObservable();
}
getUserInfo() {
return UtilsService.copy(this.oktaUserInfo);
}
newOktaError() {
this.oktaError$.next(this.oktaError);
}
onNewOktaError() {
return this.oktaError$.asObservable();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaService, deps: [{ token: i1.ConfigService }, { token: i2.LocalStorageService }, { token: i3.Router }, { token: i4.SessionStorageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.ConfigService }, { type: i2.LocalStorageService }, { type: i3.Router }, { type: i4.SessionStorageService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2t0YS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWdlbS1zcGFhcy9zcmMvX3NlcnZpY2VzL29rdGEuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsZUFBZSxFQUFjLGFBQWEsRUFBRSxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDekUsT0FBTyxFQUFDLFVBQVUsRUFBWSxNQUFNLGVBQWUsQ0FBQztBQUNwRCxPQUFPLEVBQUMsZUFBZSxFQUFTLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUVMLFFBQVEsRUFLVCxNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUl6QyxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGlCQUFpQixDQUFDOzs7Ozs7QUFLN0MsTUFBTSxPQUFPLFdBQVc7SUFrQnRCLFlBQ1UsYUFBNEIsRUFDNUIsU0FBOEIsRUFDOUIsTUFBYyxFQUNkLFNBQWdDO1FBSGhDLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLGNBQVMsR0FBVCxTQUFTLENBQXFCO1FBQzlCLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxjQUFTLEdBQVQsU0FBUyxDQUF1QjtRQXBCakMsbUJBQWMsR0FBRyxhQUFhLENBQUM7UUFDL0IsYUFBUSxHQUFHLFdBQVcsQ0FBQztRQUV4QixjQUFTLEdBQXNCLElBQUksQ0FBQztRQUNwQyxlQUFVLEdBQXVDLElBQUksZUFBZSxDQUFvQixJQUFJLENBQUMsQ0FBQztRQUU5RixpQkFBWSxHQUFHLElBQUksYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3JDLGtCQUFhLEdBQUcsSUFBSSxhQUFhLENBQWdCLENBQUMsQ0FBQyxDQUFDO1FBT3BELGVBQVUsR0FBa0IsSUFB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QVksQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCxhQUFhO1FBQ1gsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRCxXQUFXO1FBQ1QsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRU8sWUFBWTtRQUNsQixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDeEMsQ0FBQzsrR0F2TVUsV0FBVzttSEFBWCxXQUFXLGNBRlYsTUFBTTs7NEZBRVAsV0FBVztrQkFIdkIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCwgU3ViamVjdH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7SW5qZWN0YWJsZSwgT25EZXN0cm95fSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtOYXZpZ2F0aW9uU3RhcnQsIFJvdXRlcn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHtcclxuICBPQXV0aEVycm9yLFxyXG4gIE9rdGFBdXRoLFxyXG4gIE9rdGFBdXRoT3B0aW9ucyxcclxuICBUb2tlbk1hbmFnZXJJbnRlcmZhY2UsXHJcbiAgVG9rZW5QYXJhbXMsXHJcbiAgVXNlckNsYWltc1xyXG59IGZyb20gJ0Bva3RhL29rdGEtYXV0aC1qcyc7XHJcbmltcG9ydCB7dGFrZVVudGlsfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7Q29uZmlnU2VydmljZX0gZnJvbSBcIi4vY29uZmlnLnNlcnZpY2VcIjtcclxuaW1wb3J0IHtMb2NhbFN0b3JhZ2VTZXJ2aWNlfSBmcm9tIFwiLi9sb2NhbC1zdG9yYWdlLnNlcnZpY2VcIjtcclxuaW1wb3J0IHtTZXNzaW9uU3RvcmFnZVNlcnZpY2V9IGZyb20gXCIuL3Nlc3Npb24tc3RvcmFnZS5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7T2t0YVVzZXJNb2RlbH0gZnJvbSBcIi4uL19tb2RlbHMvb2t0YS5tb2RlbFwiO1xyXG5pbXBvcnQge1V0aWxzU2VydmljZX0gZnJvbSBcIi4vdXRpbHMuc2VydmljZVwiO1xyXG5cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290J1xyXG59KVxyXG5leHBvcnQgY2xhc3MgT2t0YVNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xyXG5cclxuICByZWFkb25seSBMU19BQ1RJVkVST1VURSA9ICdhY3RpdmVSb3V0ZSc7XHJcbiAgcmVhZG9ubHkgU1NfRVJST1IgPSAnb2t0YUVycm9yJztcclxuXHJcbiAgcHJpdmF0ZSBva3RhRXJyb3I6IE9BdXRoRXJyb3IgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIG9rdGFFcnJvciQ6IEJlaGF2aW9yU3ViamVjdDxPQXV0aEVycm9yIHwgbnVsbD4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0PE9BdXRoRXJyb3IgfCBudWxsPihudWxsKTtcclxuXHJcbiAgcHJpdmF0ZSBva3RhVXNlckluZm8gPSBuZXcgT2t0YVVzZXJNb2RlbCh7fSk7XHJcbiAgcHJpdmF0ZSBva3RhVXNlckluZm8kID0gbmV3IFJlcGxheVN1YmplY3Q8T2t0YVVzZXJNb2RlbD4oMSk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgb2t0YUNsaWVudDogT2t0YUF1dGg7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBva3RhQ2xpZW50Q29uZmlnOiBPa3RhQXV0aE9wdGlvbnM7XHJcbiAgcHJpdmF0ZSByZWFkb25seSB0b2tlbk1hbmFnZXI6IFRva2VuTWFuYWdlckludGVyZmFjZTtcclxuICBwcml2YXRlIHJlYWRvbmx5IHRva2VuUGFyYW1zOiBUb2tlblBhcmFtcztcclxuXHJcbiAgcHJpdmF0ZSBvbkRlc3Ryb3kkOiBTdWJqZWN0PHZvaWQ+ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2UsXHJcbiAgICBwcml2YXRlIGxzU2VydmljZTogTG9jYWxTdG9yYWdlU2VydmljZSxcclxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXHJcbiAgICBwcml2YXRlIHNzU2VydmljZTogU2Vzc2lvblN0b3JhZ2VTZXJ2aWNlLFxyXG4gICkge1xyXG4gICAgdGhpcy5va3RhQ2xpZW50Q29uZmlnID0gdGhpcy5zZXRDb25maWcoKTtcclxuICAgIC8vIENMSUVOVCwgVE9LRU5QQVJBTVMgQU5EIFRPS0VOTUFOQUdFUlxyXG4gICAgdGhpcy5va3RhQ2xpZW50ID0gbmV3IE9rdGFBdXRoKHRoaXMub2t0YUNsaWVudENvbmZpZyk7XHJcbiAgICB0aGlzLm9rdGFDbGllbnQuc3RhcnQoKTsgLy8gYXMgb2YgdjUsIG5lZWRzIHRvIGJlIHN0YXJ0ZWQgYXMgYSBzZXJ2aWNlIHRvIGF1dG8tcmVuZXdcclxuICAgIHRoaXMudG9rZW5QYXJhbXMgPSB7c2NvcGVzOiB0aGlzLm9rdGFDbGllbnRDb25maWcuc2NvcGVzfTtcclxuICAgIHRoaXMudG9rZW5NYW5hZ2VyID0gdGhpcy5va3RhQ2xpZW50LnRva2VuTWFuYWdlcjtcclxuICAgIHRoaXMudG9rZW5NYW5hZ2VyLm9uKCdlcnJvcicsIChlcnJvcikgPT4ge1xyXG4gICAgICAgIC8vIGF1dG8tcmVuZXcgZmFpbGVkLCB1c3VhbGx5IGN1eiB1c2VyIGRlbGV0ZWQgY29va2llcyBvciBzb21ldGhpbmcgKG5vIG1vcmUgdmFsaWQgb2t0YSBzZXNzaW9uKSwgc28gc2lnbiBvdXRcclxuICAgICAgICBjb25zb2xlLmxvZyhlcnJvcik7XHJcbiAgICAgICAgdGhpcy5va3RhQ2xpZW50LnNpZ25PdXQoe3Bvc3RMb2dvdXRSZWRpcmVjdFVyaTogbnVsbH0pLmNhdGNoKChlcnIpID0+IGNvbnNvbGUubG9nKGVycikpO1xyXG4gICAgICB9XHJcbiAgICApO1xyXG4gICAgLy8gU1VCU0NSSUJFIFRPIFJPVVRJTkdcclxuICAgIHRoaXMub25Sb3V0aW5nKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMub25EZXN0cm95JC5uZXh0KCk7XHJcbiAgICB0aGlzLm9uRGVzdHJveSQuY29tcGxldGUoKTtcclxuICB9XHJcblxyXG4gIC8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbiAgLy8gR0VORVJJQyBTVFVGRlxyXG4gIC8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcblxyXG4gIHByaXZhdGUgc2V0Q29uZmlnKCk6IE9rdGFBdXRoT3B0aW9ucyB7XHJcbiAgICBjb25zdCBzcGFhc0NvbmZpZyA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcoKTtcclxuICAgIGlmICghc3BhYXNDb25maWc/Lm9rdGFDb25maWcpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdwbGVhc2UgcHJvdmlkZSBhIHZhbGlkIE9rdGEgY29uZmlndXJhdGlvbiB2aWEgdGhlIFwiZm9yUm9vdFwiIG1ldGhvZCBvZiB0aGUgU3BhYXNNb2R1bGUnKTtcclxuICAgIH1cclxuICAgIGlmIChzcGFhc0NvbmZpZz8ub2t0YUNvbmZpZz8udXJsPy5zbGljZSgtMSkgPT09ICcvJykge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RoZSBva3RhIHVybCBzaG91bGQgbm90IGhhdmUgYSB0cmFpbGluZyBzbGFzaCcpO1xyXG4gICAgfVxyXG4gICAgaWYgKHNwYWFzQ29uZmlnPy5va3RhQ29uZmlnPy50ZW5hbnRJZC5pbmNsdWRlcygnLycpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGhlIG9rdGEgdGVuYW50IGlkIHNob3VsZCBub3QgY29udGFpbiBzbGFzaGVzJyk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBjbGllbnRJZDogc3BhYXNDb25maWcub2t0YUNvbmZpZy5jbGllbnRJZCxcclxuICAgICAgaXNzdWVyOiBzcGFhc0NvbmZpZy5va3RhQ29uZmlnLnVybCArICcvb2F1dGgyLycgKyBzcGFhc0NvbmZpZy5va3RhQ29uZmlnLnRlbmFudElkLFxyXG4gICAgICBwa2NlOiB0cnVlLFxyXG4gICAgICByZWRpcmVjdFVyaTogc3BhYXNDb25maWcub2t0YUNvbmZpZy53aXRoUGF0aCA/IHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4gKyB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUgOiB3aW5kb3cubG9jYXRpb24ub3JpZ2luLFxyXG4gICAgICByZXNwb25zZVR5cGU6IFsnaWRfdG9rZW4nLCAndG9rZW4nXSxcclxuICAgICAgc2NvcGVzOiBbJ29wZW5pZCcsICdlbWFpbCddLmNvbmNhdChzcGFhc0NvbmZpZy5va3RhQ29uZmlnLmFkZGl0aW9uYWxTY29wZXMgfHwgW10pLFxyXG4gICAgICB0b2tlbk1hbmFnZXI6IHtcclxuICAgICAgICBzdG9yYWdlOiAnc2Vzc2lvblN0b3JhZ2UnLFxyXG4gICAgICAgIHN0b3JhZ2VLZXk6IHNwYWFzQ29uZmlnLnN0b3JhZ2VQcmVmaXggKyAndG9rZW5zJyxcclxuICAgICAgICBleHBpcmVFYXJseVNlY29uZHM6IDMwMFxyXG4gICAgICB9LFxyXG4gICAgICB0cmFuc2FjdGlvbk1hbmFnZXI6IHtcclxuICAgICAgICBzYXZlTm9uY2VDb29raWU6IGZhbHNlLFxyXG4gICAgICAgIHNhdmVQYXJhbXNDb29raWU6IGZhbHNlLFxyXG4gICAgICAgIHNhdmVTdGF0ZUNvb2tpZTogZmFsc2UsXHJcbiAgICAgIH0sXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBvblJvdXRpbmcoKTogdm9pZCB7XHJcbiAgICB0aGlzLnJvdXRlci5ldmVudHNcclxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMub25EZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoXHJcbiAgICAgICAgKGV2ZW50KSA9PiB7XHJcbiAgICAgICAgICBpZiAoZXZlbnQgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uU3RhcnQpIHtcclxuICAgICAgICAgICAgLy8gc2V0IGFjdGl2ZSByb3V0ZSBoZXJlLCBzbyB3ZSBrbm93IHdoZXJlIHRvIHJvdXRlIHRvIGFmdGVyIHRva2VuIHJlZGlyZWN0aW9uXHJcbiAgICAgICAgICAgIGlmIChldmVudC51cmwgIT09ICcvJykge1xyXG4gICAgICAgICAgICAgIHRoaXMuc2V0QWN0aXZlUm91dGUoZXZlbnQudXJsKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBCRUNBVVNFIFdFIEhBTkRMRSBUSEUgQ0FMTEJBQ0sgQkVGT1JFIFJPVVRJTkcsIFRIRSBISURERU4gSUZSQU1FIFJFTUFJTlMgRU1QVFlcclxuICAgICAgICAgICAgdGhpcy5oYW5kbGVSZWRpcmVjdCgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAvLyBPS1RBIFNUVUZGXHJcbiAgLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVSZWRpcmVjdCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm9rdGFDbGllbnQudG9rZW4uaXNMb2dpblJlZGlyZWN0KCkgfHwgd2luZG93LmxvY2F0aW9uLnNlYXJjaC5pbmNsdWRlcygnZXJyb3I9JykpIHtcclxuICAgICAgLy8gSVMgUkVESVJFQ1QgT1IgT0tUQSBFUlJPUlxyXG4gICAgICB0aGlzLnVwZGF0ZU9rdGFFcnJvcihudWxsKTtcclxuICAgICAgdGhpcy5wYXJzZUZyb21VcmwoKTtcclxuICAgIH0gZWxzZSBpZiAoIXRoaXMub2t0YUVycm9yKSB7XHJcbiAgICAgIC8vIElTIFJFR1VMQVIgTkFWSUdBVElPTjogQ0hFQ0sgVVNFUiBJTkZPXHJcbiAgICAgIHRoaXMuZ2V0VXNlckluZm9Gcm9tVG9rZW4oKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgcGFyc2VGcm9tVXJsKCkge1xyXG4gICAgdGhpcy5va3RhQ2xpZW50LnRva2VuLnBhcnNlRnJvbVVybCgpXHJcbiAgICAgIC50aGVuKCh0b2tlblJlc3BvbnNlKSA9PiB7XHJcbiAgICAgICAgdGhpcy50b2tlbk1hbmFnZXIuc2V0VG9rZW5zKHRva2VuUmVzcG9uc2UudG9rZW5zKTtcclxuICAgICAgICAvLyBOT1cgU0VUIFVTRVIgSU5GTyBGUk9NIFRIRSBUT0tFTlxyXG4gICAgICAgIC8vIElUJ1MgVEhFIFVTRVIgSU5GTyBPQlNFUlZBQkxFIFRIQVQgT1RIRVIgQ09NUE9ORU5UUyBPUiBTRVJWSUNFUyBTSE9VTEQgVVNFIEFTIElORElDQVRJT04gVEhBVCBBTEwgSVMgR09PRCBUTyBHT1xyXG4gICAgICAgIHRoaXMuZ2V0VXNlckluZm9Gcm9tVG9rZW4oKTtcclxuICAgICAgfSlcclxuICAgICAgLmNhdGNoKChlcnI6IE9BdXRoRXJyb3IpID0+IHtcclxuICAgICAgICB0aGlzLnVwZGF0ZU9rdGFFcnJvcihlcnIpO1xyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0VXNlckluZm9Gcm9tVG9rZW4oKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5va3RhVXNlckluZm8uZW1haWwpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy50b2tlbk1hbmFnZXIuZ2V0VG9rZW5zKClcclxuICAgICAgLnRoZW4oKHRva2VucykgPT4ge1xyXG4gICAgICAgIHRoaXMubmV3VXNlckluZm8odG9rZW5zPy5hY2Nlc3NUb2tlbj8uY2xhaW1zKTtcclxuICAgICAgICAvLyBzZXQgYSBkZWZhdWx0IHVybC4gSWYgaXQgZXhpc3RzLCBmaW5lLCBpZiBub3QsIGl0IHdpbGwgZm9yY2UgdGhlIGNvbmZpZ3VyZWQgcmVkaXJlY3RzIHRvIGtpY2sgaW5cclxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbdGhpcy5nZXRBY3RpdmVSb3V0ZSgpIHx8ICcvaG9tZSddKTtcclxuICAgICAgfSlcclxuICAgICAgLmNhdGNoKCgpID0+IHtcclxuICAgICAgICB0aGlzLmdldFRva2VuV2l0aFJlZGlyZWN0KCk7XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRUb2tlbldpdGhSZWRpcmVjdCgpOiB2b2lkIHtcclxuICAgIHRoaXMub2t0YUNsaWVudC50b2tlbi5nZXRXaXRoUmVkaXJlY3QodGhpcy50b2tlblBhcmFtcylcclxuICAgICAgLmNhdGNoKChlKSA9PiBjb25zb2xlLmxvZyhlKSk7XHJcbiAgfVxyXG5cclxuICBnZXRDYWNoZWRBY2Nlc3NUb2tlbigpOiBzdHJpbmcge1xyXG4gICAgLy8gVE8gQkUgVVNFRCBJTiBDQU5BQ1RJVkUgQU5EL09SIENBTkxPQUQgQU5EL09SIEhUVFAgSU5URVJDRVBUT1JcclxuICAgIGlmICh0aGlzLm9rdGFDbGllbnQgJiYgdGhpcy50b2tlbk1hbmFnZXIpIHtcclxuICAgICAgcmV0dXJuIHRoaXMub2t0YUNsaWVudC5nZXRBY2Nlc3NUb2tlbigpIHx8ICcnO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc29sZS5sb2coJ3Nob3VsZCBuZXZlciBoYXBwZW46IHRva2VubWFuYWdlciBpcyBudWxsISBOb3RoaW5nIGxlZnQgdG8gZG8gYnV0IHJlZGlyZWN0Jyk7XHJcbiAgICAgIHRoaXMuZ2V0VG9rZW5XaXRoUmVkaXJlY3QoKTtcclxuICAgICAgcmV0dXJuICcnO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdXBkYXRlT2t0YUVycm9yKG5ld1N0YXRlOiBPQXV0aEVycm9yIHwgbnVsbCk6IHZvaWQge1xyXG4gICAgdGhpcy5va3RhRXJyb3IgPSBuZXdTdGF0ZTtcclxuICAgIHRoaXMuc3NTZXJ2aWNlLnNldEl0ZW0odGhpcy5TU19FUlJPUiwgdGhpcy5va3RhRXJyb3IpO1xyXG4gICAgdGhpcy5uZXdPa3RhRXJyb3IoKTtcclxuICB9XHJcblxyXG4gIGZvcmNlUmV0cnkoKTogdm9pZCB7XHJcbiAgICAvLyBNRVRIT0QgVEhBVCBDQU4gQkUgQ0FMTEVEIEJZIFdISUNIRVZFUiBDT01QT05FTlQgWU9VIEhBVkUgVE8gSEFORExFL0RJU1BMQVkgT0tUQSBFUlJPUlNcclxuICAgIC8vIEZPUiBFWEFNUExFIE9OIEEgQlVUVE9OIENMSUNLICdUUlkgQUdBSU4nIFNPIFVTRVIgQ0FOIEZPUkNFIEFOIE9LVEEgUkVUUllcclxuICAgIHRoaXMudXBkYXRlT2t0YUVycm9yKG51bGwpO1xyXG4gICAgdGhpcy5nZXRUb2tlbldpdGhSZWRpcmVjdCgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXRBY3RpdmVSb3V0ZSh1cmw6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5sc1NlcnZpY2Uuc2V0SXRlbSh0aGlzLkxTX0FDVElWRVJPVVRFLCB1cmwpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRBY3RpdmVSb3V0ZSgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHRoaXMubHNTZXJ2aWNlLmdldEl0ZW0odGhpcy5MU19BQ1RJVkVST1VURSkgfHwgJyc7XHJcbiAgfVxyXG5cclxuICAvLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gIC8vIEJST0FEQ0FTVCBEQVRBXHJcbiAgLy8gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuXHJcbiAgcHJpdmF0ZSBuZXdVc2VySW5mbyh1c2VySW5mbzogVXNlckNsYWltcyB8IHVuZGVmaW5lZCk6IHZvaWQge1xyXG4gICAgdGhpcy5va3RhVXNlckluZm8gPSBuZXcgT2t0YVVzZXJNb2RlbCh1c2VySW5mbyk7XHJcbiAgICB0aGlzLm9rdGFVc2VySW5mbyQubmV4dCh0aGlzLm9rdGFVc2VySW5mbyk7XHJcbiAgfVxyXG5cclxuICBvbk5ld1VzZXJJbmZvKCk6IE9ic2VydmFibGU8T2t0YVVzZXJNb2RlbD4ge1xyXG4gICAgcmV0dXJuIHRoaXMub2t0YVVzZXJJbmZvJC5hc09ic2VydmFibGUoKTtcclxuICB9XHJcblxyXG4gIGdldFVzZXJJbmZvKCk6IE9rdGFVc2VyTW9kZWwge1xyXG4gICAgcmV0dXJuIFV0aWxzU2VydmljZS5jb3B5KHRoaXMub2t0YVVzZXJJbmZvKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgbmV3T2t0YUVycm9yKCk6IHZvaWQge1xyXG4gICAgdGhpcy5va3RhRXJyb3IkLm5leHQodGhpcy5va3RhRXJyb3IpO1xyXG4gIH1cclxuXHJcbiAgb25OZXdPa3RhRXJyb3IoKTogT2JzZXJ2YWJsZTxPQXV0aEVycm9yIHwgbnVsbD4ge1xyXG4gICAgcmV0dXJuIHRoaXMub2t0YUVycm9yJC5hc09ic2VydmFibGUoKTtcclxuICB9XHJcblxyXG59XHJcbiJdfQ==