angular-auth-oidc-client
Version:
Angular Lib for OpenID Connect & OAuth2
187 lines • 28.8 kB
JavaScript
import { Injectable, inject } from '@angular/core';
import { BehaviorSubject, throwError } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';
import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types';
import { PublicEventsService } from '../public-events/public-events.service';
import { StoragePersistenceService } from '../storage/storage-persistence.service';
import { TokenValidationService } from '../validation/token-validation.service';
import * as i0 from "@angular/core";
const DEFAULT_AUTHRESULT = {
isAuthenticated: false,
allConfigsAuthenticated: [],
};
export class AuthStateService {
constructor() {
this.storagePersistenceService = inject(StoragePersistenceService);
this.loggerService = inject(LoggerService);
this.publicEventsService = inject(PublicEventsService);
this.tokenValidationService = inject(TokenValidationService);
this.authenticatedInternal$ = new BehaviorSubject(DEFAULT_AUTHRESULT);
}
get authenticated$() {
return this.authenticatedInternal$
.asObservable()
.pipe(distinctUntilChanged());
}
setAuthenticatedAndFireEvent(allConfigs) {
const result = this.composeAuthenticatedResult(allConfigs);
this.authenticatedInternal$.next(result);
}
setUnauthenticatedAndFireEvent(currentConfig, allConfigs) {
this.storagePersistenceService.resetAuthStateInStorage(currentConfig);
const result = this.composeUnAuthenticatedResult(allConfigs);
this.authenticatedInternal$.next(result);
}
updateAndPublishAuthState(authenticationResult) {
this.publicEventsService.fireEvent(EventTypes.NewAuthenticationResult, authenticationResult);
}
setAuthorizationData(accessToken, authResult, currentConfig, allConfigs) {
this.loggerService.logDebug(currentConfig, `storing the accessToken '${accessToken}'`);
this.storagePersistenceService.write('authzData', accessToken, currentConfig);
this.persistAccessTokenExpirationTime(authResult, currentConfig);
this.setAuthenticatedAndFireEvent(allConfigs);
}
getAccessToken(configuration) {
if (!configuration) {
return '';
}
if (!this.isAuthenticated(configuration)) {
return '';
}
const token = this.storagePersistenceService.getAccessToken(configuration);
return this.decodeURIComponentSafely(token);
}
getIdToken(configuration) {
if (!configuration) {
return '';
}
if (!this.isAuthenticated(configuration)) {
return '';
}
const token = this.storagePersistenceService.getIdToken(configuration);
return this.decodeURIComponentSafely(token);
}
getRefreshToken(configuration) {
if (!configuration) {
return '';
}
if (!this.isAuthenticated(configuration)) {
return '';
}
const token = this.storagePersistenceService.getRefreshToken(configuration);
return this.decodeURIComponentSafely(token);
}
getAuthenticationResult(configuration) {
if (!configuration) {
return null;
}
if (!this.isAuthenticated(configuration)) {
return null;
}
return this.storagePersistenceService.getAuthenticationResult(configuration);
}
areAuthStorageTokensValid(configuration) {
if (!configuration) {
return false;
}
if (!this.isAuthenticated(configuration)) {
return false;
}
if (this.hasIdTokenExpiredAndRenewCheckIsEnabled(configuration)) {
this.loggerService.logDebug(configuration, 'persisted idToken is expired');
return false;
}
if (this.hasAccessTokenExpiredIfExpiryExists(configuration)) {
this.loggerService.logDebug(configuration, 'persisted accessToken is expired');
return false;
}
this.loggerService.logDebug(configuration, 'persisted idToken and accessToken are valid');
return true;
}
hasIdTokenExpiredAndRenewCheckIsEnabled(configuration) {
const { renewTimeBeforeTokenExpiresInSeconds, triggerRefreshWhenIdTokenExpired, disableIdTokenValidation, } = configuration;
if (!triggerRefreshWhenIdTokenExpired || disableIdTokenValidation) {
return false;
}
const tokenToCheck = this.storagePersistenceService.getIdToken(configuration);
const idTokenExpired = this.tokenValidationService.hasIdTokenExpired(tokenToCheck, configuration, renewTimeBeforeTokenExpiresInSeconds);
if (idTokenExpired) {
this.publicEventsService.fireEvent(EventTypes.IdTokenExpired, idTokenExpired);
}
return idTokenExpired;
}
hasAccessTokenExpiredIfExpiryExists(configuration) {
const { renewTimeBeforeTokenExpiresInSeconds } = configuration;
const accessTokenExpiresIn = this.storagePersistenceService.read('access_token_expires_at', configuration);
const accessTokenHasNotExpired = this.tokenValidationService.validateAccessTokenNotExpired(accessTokenExpiresIn, configuration, renewTimeBeforeTokenExpiresInSeconds);
const hasExpired = !accessTokenHasNotExpired;
if (hasExpired) {
this.publicEventsService.fireEvent(EventTypes.TokenExpired, hasExpired);
}
return hasExpired;
}
isAuthenticated(configuration) {
if (!configuration) {
throwError(() => new Error('Please provide a configuration before setting up the module'));
return false;
}
const hasAccessToken = !!this.storagePersistenceService.getAccessToken(configuration);
const hasIdToken = !!this.storagePersistenceService.getIdToken(configuration);
return hasAccessToken && hasIdToken;
}
decodeURIComponentSafely(token) {
if (token) {
return decodeURIComponent(token);
}
else {
return '';
}
}
persistAccessTokenExpirationTime(authResult, configuration) {
if (authResult?.expires_in) {
const accessTokenExpiryTime = new Date(new Date().toUTCString()).valueOf() +
authResult.expires_in * 1000;
this.storagePersistenceService.write('access_token_expires_at', accessTokenExpiryTime, configuration);
}
}
composeAuthenticatedResult(allConfigs) {
if (allConfigs.length === 1) {
const { configId } = allConfigs[0];
return {
isAuthenticated: true,
allConfigsAuthenticated: [
{ configId: configId ?? '', isAuthenticated: true },
],
};
}
return this.checkAllConfigsIfTheyAreAuthenticated(allConfigs);
}
composeUnAuthenticatedResult(allConfigs) {
if (allConfigs.length === 1) {
const { configId } = allConfigs[0];
return {
isAuthenticated: false,
allConfigsAuthenticated: [
{ configId: configId ?? '', isAuthenticated: false },
],
};
}
return this.checkAllConfigsIfTheyAreAuthenticated(allConfigs);
}
checkAllConfigsIfTheyAreAuthenticated(allConfigs) {
const allConfigsAuthenticated = allConfigs.map((config) => ({
configId: config.configId ?? '',
isAuthenticated: this.isAuthenticated(config),
}));
const isAuthenticated = allConfigsAuthenticated.every((x) => !!x.isAuthenticated);
return { allConfigsAuthenticated, isAuthenticated };
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: AuthStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: AuthStateService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: AuthStateService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC1zdGF0ZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1hdXRoLW9pZGMtY2xpZW50L3NyYy9saWIvYXV0aC1zdGF0ZS9hdXRoLXN0YXRlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFFLGVBQWUsRUFBYyxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHdEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzFELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUM3RSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUNuRixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQzs7QUFJaEYsTUFBTSxrQkFBa0IsR0FBRztJQUN6QixlQUFlLEVBQUUsS0FBSztJQUN0Qix1QkFBdUIsRUFBRSxFQUFFO0NBQzVCLENBQUM7QUFHRixNQUFNLE9BQU8sZ0JBQWdCO0lBRDdCO1FBRW1CLDhCQUF5QixHQUFHLE1BQU0sQ0FDakQseUJBQXlCLENBQzFCLENBQUM7UUFFZSxrQkFBYSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUV0Qyx3QkFBbUIsR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUVsRCwyQkFBc0IsR0FBRyxNQUFNLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUV4RCwyQkFBc0IsR0FDckMsSUFBSSxlQUFlLENBQXNCLGtCQUFrQixDQUFDLENBQUM7S0EwU2hFO0lBeFNDLElBQUksY0FBYztRQUNoQixPQUFPLElBQUksQ0FBQyxzQkFBc0I7YUFDL0IsWUFBWSxFQUFFO2FBQ2QsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQsNEJBQTRCLENBQUMsVUFBaUM7UUFDNUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRTNELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELDhCQUE4QixDQUM1QixhQUFrQyxFQUNsQyxVQUFpQztRQUVqQyxJQUFJLENBQUMseUJBQXlCLENBQUMsdUJBQXVCLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFdEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLDRCQUE0QixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRTdELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELHlCQUF5QixDQUFDLG9CQUFxQztRQUM3RCxJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUNoQyxVQUFVLENBQUMsdUJBQXVCLEVBQ2xDLG9CQUFvQixDQUNyQixDQUFDO0lBQ0osQ0FBQztJQUVELG9CQUFvQixDQUNsQixXQUFtQixFQUNuQixVQUE2QixFQUM3QixhQUFrQyxFQUNsQyxVQUFpQztRQUVqQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FDekIsYUFBYSxFQUNiLDRCQUE0QixXQUFXLEdBQUcsQ0FDM0MsQ0FBQztRQUVGLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQ2xDLFdBQVcsRUFDWCxXQUFXLEVBQ1gsYUFBYSxDQUNkLENBQUM7UUFDRixJQUFJLENBQUMsZ0NBQWdDLENBQUMsVUFBVSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQ2pFLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQsY0FBYyxDQUFDLGFBQXlDO1FBQ3RELElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNuQixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ3pDLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFM0UsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVELFVBQVUsQ0FBQyxhQUF5QztRQUNsRCxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDbkIsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztZQUN6QyxPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMseUJBQXlCLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRXZFLE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFRCxlQUFlLENBQUMsYUFBeUM7UUFDdkQsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ25CLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7WUFDekMsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLHlCQUF5QixDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUU1RSxPQUFPLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRUQsdUJBQXVCLENBQ3JCLGFBQXlDO1FBRXpDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNuQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ3pDLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLHlCQUF5QixDQUFDLHVCQUF1QixDQUMzRCxhQUFhLENBQ2QsQ0FBQztJQUNKLENBQUM7SUFFRCx5QkFBeUIsQ0FDdkIsYUFBeUM7UUFFekMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ25CLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7WUFDekMsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsdUNBQXVDLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztZQUNoRSxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FDekIsYUFBYSxFQUNiLDhCQUE4QixDQUMvQixDQUFDO1lBRUYsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsbUNBQW1DLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztZQUM1RCxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FDekIsYUFBYSxFQUNiLGtDQUFrQyxDQUNuQyxDQUFDO1lBRUYsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQ3pCLGFBQWEsRUFDYiw2Q0FBNkMsQ0FDOUMsQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELHVDQUF1QyxDQUNyQyxhQUFrQztRQUVsQyxNQUFNLEVBQ0osb0NBQW9DLEVBQ3BDLGdDQUFnQyxFQUNoQyx3QkFBd0IsR0FDekIsR0FBRyxhQUFhLENBQUM7UUFFbEIsSUFBSSxDQUFDLGdDQUFnQyxJQUFJLHdCQUF3QixFQUFFLENBQUM7WUFDbEUsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBQ0QsTUFBTSxZQUFZLEdBQ2hCLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFM0QsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLGlCQUFpQixDQUNsRSxZQUFZLEVBQ1osYUFBYSxFQUNiLG9DQUFvQyxDQUNyQyxDQUFDO1FBRUYsSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUNoQyxVQUFVLENBQUMsY0FBYyxFQUN6QixjQUFjLENBQ2YsQ0FBQztRQUNKLENBQUM7UUFFRCxPQUFPLGNBQWMsQ0FBQztJQUN4QixDQUFDO0lBRUQsbUNBQW1DLENBQ2pDLGFBQWtDO1FBRWxDLE1BQU0sRUFBRSxvQ0FBb0MsRUFBRSxHQUFHLGFBQWEsQ0FBQztRQUMvRCxNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQzlELHlCQUF5QixFQUN6QixhQUFhLENBQ2QsQ0FBQztRQUNGLE1BQU0sd0JBQXdCLEdBQzVCLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyw2QkFBNkIsQ0FDdkQsb0JBQW9CLEVBQ3BCLGFBQWEsRUFDYixvQ0FBb0MsQ0FDckMsQ0FBQztRQUVKLE1BQU0sVUFBVSxHQUFHLENBQUMsd0JBQXdCLENBQUM7UUFFN0MsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQ2hDLFVBQVUsQ0FBQyxZQUFZLEVBQ3ZCLFVBQVUsQ0FDWCxDQUFDO1FBQ0osQ0FBQztRQUVELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxlQUFlLENBQUMsYUFBeUM7UUFDdkQsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ25CLFVBQVUsQ0FDUixHQUFHLEVBQUUsQ0FDSCxJQUFJLEtBQUssQ0FDUCw2REFBNkQsQ0FDOUQsQ0FDSixDQUFDO1lBRUYsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsTUFBTSxjQUFjLEdBQ2xCLENBQUMsQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ2pFLE1BQU0sVUFBVSxHQUNkLENBQUMsQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRTdELE9BQU8sY0FBYyxJQUFJLFVBQVUsQ0FBQztJQUN0QyxDQUFDO0lBRU8sd0JBQXdCLENBQUMsS0FBYTtRQUM1QyxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1YsT0FBTyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQyxDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztJQUNILENBQUM7SUFFTyxnQ0FBZ0MsQ0FDdEMsVUFBNkIsRUFDN0IsYUFBa0M7UUFFbEMsSUFBSSxVQUFVLEVBQUUsVUFBVSxFQUFFLENBQUM7WUFDM0IsTUFBTSxxQkFBcUIsR0FDekIsSUFBSSxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRTtnQkFDNUMsVUFBVSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7WUFFL0IsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FDbEMseUJBQXlCLEVBQ3pCLHFCQUFxQixFQUNyQixhQUFhLENBQ2QsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRU8sMEJBQTBCLENBQ2hDLFVBQWlDO1FBRWpDLElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM1QixNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRW5DLE9BQU87Z0JBQ0wsZUFBZSxFQUFFLElBQUk7Z0JBQ3JCLHVCQUF1QixFQUFFO29CQUN2QixFQUFFLFFBQVEsRUFBRSxRQUFRLElBQUksRUFBRSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUU7aUJBQ3BEO2FBQ0YsQ0FBQztRQUNKLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxxQ0FBcUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBRU8sNEJBQTRCLENBQ2xDLFVBQWlDO1FBRWpDLElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM1QixNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRW5DLE9BQU87Z0JBQ0wsZUFBZSxFQUFFLEtBQUs7Z0JBQ3RCLHVCQUF1QixFQUFFO29CQUN2QixFQUFFLFFBQVEsRUFBRSxRQUFRLElBQUksRUFBRSxFQUFFLGVBQWUsRUFBRSxLQUFLLEVBQUU7aUJBQ3JEO2FBQ0YsQ0FBQztRQUNKLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxxQ0FBcUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBRU8scUNBQXFDLENBQzNDLFVBQWlDO1FBRWpDLE1BQU0sdUJBQXVCLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMxRCxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsSUFBSSxFQUFFO1lBQy9CLGVBQWUsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQztTQUM5QyxDQUFDLENBQUMsQ0FBQztRQUVKLE1BQU0sZUFBZSxHQUFHLHVCQUF1QixDQUFDLEtBQUssQ0FDbkQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUMzQixDQUFDO1FBRUYsT0FBTyxFQUFFLHVCQUF1QixFQUFFLGVBQWUsRUFBRSxDQUFDO0lBQ3RELENBQUM7OEdBclRVLGdCQUFnQjtrSEFBaEIsZ0JBQWdCLGNBREgsTUFBTTs7MkZBQ25CLGdCQUFnQjtrQkFENUIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGlzdGluY3RVbnRpbENoYW5nZWQgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBPcGVuSWRDb25maWd1cmF0aW9uIH0gZnJvbSAnLi4vY29uZmlnL29wZW5pZC1jb25maWd1cmF0aW9uJztcbmltcG9ydCB7IEF1dGhSZXN1bHQgfSBmcm9tICcuLi9mbG93cy9jYWxsYmFjay1jb250ZXh0JztcbmltcG9ydCB7IExvZ2dlclNlcnZpY2UgfSBmcm9tICcuLi9sb2dnaW5nL2xvZ2dlci5zZXJ2aWNlJztcbmltcG9ydCB7IEV2ZW50VHlwZXMgfSBmcm9tICcuLi9wdWJsaWMtZXZlbnRzL2V2ZW50LXR5cGVzJztcbmltcG9ydCB7IFB1YmxpY0V2ZW50c1NlcnZpY2UgfSBmcm9tICcuLi9wdWJsaWMtZXZlbnRzL3B1YmxpYy1ldmVudHMuc2VydmljZSc7XG5pbXBvcnQgeyBTdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlIH0gZnJvbSAnLi4vc3RvcmFnZS9zdG9yYWdlLXBlcnNpc3RlbmNlLnNlcnZpY2UnO1xuaW1wb3J0IHsgVG9rZW5WYWxpZGF0aW9uU2VydmljZSB9IGZyb20gJy4uL3ZhbGlkYXRpb24vdG9rZW4tdmFsaWRhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IEF1dGhlbnRpY2F0ZWRSZXN1bHQgfSBmcm9tICcuL2F1dGgtcmVzdWx0JztcbmltcG9ydCB7IEF1dGhTdGF0ZVJlc3VsdCB9IGZyb20gJy4vYXV0aC1zdGF0ZSc7XG5cbmNvbnN0IERFRkFVTFRfQVVUSFJFU1VMVCA9IHtcbiAgaXNBdXRoZW50aWNhdGVkOiBmYWxzZSxcbiAgYWxsQ29uZmlnc0F1dGhlbnRpY2F0ZWQ6IFtdLFxufTtcblxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBBdXRoU3RhdGVTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBzdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlID0gaW5qZWN0KFxuICAgIFN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2VcbiAgKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGxvZ2dlclNlcnZpY2UgPSBpbmplY3QoTG9nZ2VyU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwdWJsaWNFdmVudHNTZXJ2aWNlID0gaW5qZWN0KFB1YmxpY0V2ZW50c1NlcnZpY2UpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgdG9rZW5WYWxpZGF0aW9uU2VydmljZSA9IGluamVjdChUb2tlblZhbGlkYXRpb25TZXJ2aWNlKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGF1dGhlbnRpY2F0ZWRJbnRlcm5hbCQgPVxuICAgIG5ldyBCZWhhdmlvclN1YmplY3Q8QXV0aGVudGljYXRlZFJlc3VsdD4oREVGQVVMVF9BVVRIUkVTVUxUKTtcblxuICBnZXQgYXV0aGVudGljYXRlZCQoKTogT2JzZXJ2YWJsZTxBdXRoZW50aWNhdGVkUmVzdWx0PiB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aGVudGljYXRlZEludGVybmFsJFxuICAgICAgLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpKTtcbiAgfVxuXG4gIHNldEF1dGhlbnRpY2F0ZWRBbmRGaXJlRXZlbnQoYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdKTogdm9pZCB7XG4gICAgY29uc3QgcmVzdWx0ID0gdGhpcy5jb21wb3NlQXV0aGVudGljYXRlZFJlc3VsdChhbGxDb25maWdzKTtcblxuICAgIHRoaXMuYXV0aGVudGljYXRlZEludGVybmFsJC5uZXh0KHJlc3VsdCk7XG4gIH1cblxuICBzZXRVbmF1dGhlbnRpY2F0ZWRBbmRGaXJlRXZlbnQoXG4gICAgY3VycmVudENvbmZpZzogT3BlbklkQ29uZmlndXJhdGlvbixcbiAgICBhbGxDb25maWdzOiBPcGVuSWRDb25maWd1cmF0aW9uW11cbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLnJlc2V0QXV0aFN0YXRlSW5TdG9yYWdlKGN1cnJlbnRDb25maWcpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gdGhpcy5jb21wb3NlVW5BdXRoZW50aWNhdGVkUmVzdWx0KGFsbENvbmZpZ3MpO1xuXG4gICAgdGhpcy5hdXRoZW50aWNhdGVkSW50ZXJuYWwkLm5leHQocmVzdWx0KTtcbiAgfVxuXG4gIHVwZGF0ZUFuZFB1Ymxpc2hBdXRoU3RhdGUoYXV0aGVudGljYXRpb25SZXN1bHQ6IEF1dGhTdGF0ZVJlc3VsdCk6IHZvaWQge1xuICAgIHRoaXMucHVibGljRXZlbnRzU2VydmljZS5maXJlRXZlbnQ8QXV0aFN0YXRlUmVzdWx0PihcbiAgICAgIEV2ZW50VHlwZXMuTmV3QXV0aGVudGljYXRpb25SZXN1bHQsXG4gICAgICBhdXRoZW50aWNhdGlvblJlc3VsdFxuICAgICk7XG4gIH1cblxuICBzZXRBdXRob3JpemF0aW9uRGF0YShcbiAgICBhY2Nlc3NUb2tlbjogc3RyaW5nLFxuICAgIGF1dGhSZXN1bHQ6IEF1dGhSZXN1bHQgfCBudWxsLFxuICAgIGN1cnJlbnRDb25maWc6IE9wZW5JZENvbmZpZ3VyYXRpb24sXG4gICAgYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdXG4gICk6IHZvaWQge1xuICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dEZWJ1ZyhcbiAgICAgIGN1cnJlbnRDb25maWcsXG4gICAgICBgc3RvcmluZyB0aGUgYWNjZXNzVG9rZW4gJyR7YWNjZXNzVG9rZW59J2BcbiAgICApO1xuXG4gICAgdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLndyaXRlKFxuICAgICAgJ2F1dGh6RGF0YScsXG4gICAgICBhY2Nlc3NUb2tlbixcbiAgICAgIGN1cnJlbnRDb25maWdcbiAgICApO1xuICAgIHRoaXMucGVyc2lzdEFjY2Vzc1Rva2VuRXhwaXJhdGlvblRpbWUoYXV0aFJlc3VsdCwgY3VycmVudENvbmZpZyk7XG4gICAgdGhpcy5zZXRBdXRoZW50aWNhdGVkQW5kRmlyZUV2ZW50KGFsbENvbmZpZ3MpO1xuICB9XG5cbiAgZ2V0QWNjZXNzVG9rZW4oY29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvbiB8IG51bGwpOiBzdHJpbmcge1xuICAgIGlmICghY29uZmlndXJhdGlvbikge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5pc0F1dGhlbnRpY2F0ZWQoY29uZmlndXJhdGlvbikpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG5cbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5nZXRBY2Nlc3NUb2tlbihjb25maWd1cmF0aW9uKTtcblxuICAgIHJldHVybiB0aGlzLmRlY29kZVVSSUNvbXBvbmVudFNhZmVseSh0b2tlbik7XG4gIH1cblxuICBnZXRJZFRva2VuKGNvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb24gfCBudWxsKTogc3RyaW5nIHtcbiAgICBpZiAoIWNvbmZpZ3VyYXRpb24pIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNBdXRoZW50aWNhdGVkKGNvbmZpZ3VyYXRpb24pKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLnN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UuZ2V0SWRUb2tlbihjb25maWd1cmF0aW9uKTtcblxuICAgIHJldHVybiB0aGlzLmRlY29kZVVSSUNvbXBvbmVudFNhZmVseSh0b2tlbik7XG4gIH1cblxuICBnZXRSZWZyZXNoVG9rZW4oY29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvbiB8IG51bGwpOiBzdHJpbmcge1xuICAgIGlmICghY29uZmlndXJhdGlvbikge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5pc0F1dGhlbnRpY2F0ZWQoY29uZmlndXJhdGlvbikpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG5cbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5nZXRSZWZyZXNoVG9rZW4oY29uZmlndXJhdGlvbik7XG5cbiAgICByZXR1cm4gdGhpcy5kZWNvZGVVUklDb21wb25lbnRTYWZlbHkodG9rZW4pO1xuICB9XG5cbiAgZ2V0QXV0aGVudGljYXRpb25SZXN1bHQoXG4gICAgY29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvbiB8IG51bGxcbiAgKTogQXV0aFJlc3VsdCB8IG51bGwge1xuICAgIGlmICghY29uZmlndXJhdGlvbikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmlzQXV0aGVudGljYXRlZChjb25maWd1cmF0aW9uKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5nZXRBdXRoZW50aWNhdGlvblJlc3VsdChcbiAgICAgIGNvbmZpZ3VyYXRpb25cbiAgICApO1xuICB9XG5cbiAgYXJlQXV0aFN0b3JhZ2VUb2tlbnNWYWxpZChcbiAgICBjb25maWd1cmF0aW9uOiBPcGVuSWRDb25maWd1cmF0aW9uIHwgbnVsbFxuICApOiBib29sZWFuIHtcbiAgICBpZiAoIWNvbmZpZ3VyYXRpb24pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNBdXRoZW50aWNhdGVkKGNvbmZpZ3VyYXRpb24pKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaGFzSWRUb2tlbkV4cGlyZWRBbmRSZW5ld0NoZWNrSXNFbmFibGVkKGNvbmZpZ3VyYXRpb24pKSB7XG4gICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoXG4gICAgICAgIGNvbmZpZ3VyYXRpb24sXG4gICAgICAgICdwZXJzaXN0ZWQgaWRUb2tlbiBpcyBleHBpcmVkJ1xuICAgICAgKTtcblxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc0FjY2Vzc1Rva2VuRXhwaXJlZElmRXhwaXJ5RXhpc3RzKGNvbmZpZ3VyYXRpb24pKSB7XG4gICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoXG4gICAgICAgIGNvbmZpZ3VyYXRpb24sXG4gICAgICAgICdwZXJzaXN0ZWQgYWNjZXNzVG9rZW4gaXMgZXhwaXJlZCdcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoXG4gICAgICBjb25maWd1cmF0aW9uLFxuICAgICAgJ3BlcnNpc3RlZCBpZFRva2VuIGFuZCBhY2Nlc3NUb2tlbiBhcmUgdmFsaWQnXG4gICAgKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgaGFzSWRUb2tlbkV4cGlyZWRBbmRSZW5ld0NoZWNrSXNFbmFibGVkKFxuICAgIGNvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb25cbiAgKTogYm9vbGVhbiB7XG4gICAgY29uc3Qge1xuICAgICAgcmVuZXdUaW1lQmVmb3JlVG9rZW5FeHBpcmVzSW5TZWNvbmRzLFxuICAgICAgdHJpZ2dlclJlZnJlc2hXaGVuSWRUb2tlbkV4cGlyZWQsXG4gICAgICBkaXNhYmxlSWRUb2tlblZhbGlkYXRpb24sXG4gICAgfSA9IGNvbmZpZ3VyYXRpb247XG5cbiAgICBpZiAoIXRyaWdnZXJSZWZyZXNoV2hlbklkVG9rZW5FeHBpcmVkIHx8IGRpc2FibGVJZFRva2VuVmFsaWRhdGlvbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCB0b2tlblRvQ2hlY2sgPVxuICAgICAgdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLmdldElkVG9rZW4oY29uZmlndXJhdGlvbik7XG5cbiAgICBjb25zdCBpZFRva2VuRXhwaXJlZCA9IHRoaXMudG9rZW5WYWxpZGF0aW9uU2VydmljZS5oYXNJZFRva2VuRXhwaXJlZChcbiAgICAgIHRva2VuVG9DaGVjayxcbiAgICAgIGNvbmZpZ3VyYXRpb24sXG4gICAgICByZW5ld1RpbWVCZWZvcmVUb2tlbkV4cGlyZXNJblNlY29uZHNcbiAgICApO1xuXG4gICAgaWYgKGlkVG9rZW5FeHBpcmVkKSB7XG4gICAgICB0aGlzLnB1YmxpY0V2ZW50c1NlcnZpY2UuZmlyZUV2ZW50PGJvb2xlYW4+KFxuICAgICAgICBFdmVudFR5cGVzLklkVG9rZW5FeHBpcmVkLFxuICAgICAgICBpZFRva2VuRXhwaXJlZFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaWRUb2tlbkV4cGlyZWQ7XG4gIH1cblxuICBoYXNBY2Nlc3NUb2tlbkV4cGlyZWRJZkV4cGlyeUV4aXN0cyhcbiAgICBjb25maWd1cmF0aW9uOiBPcGVuSWRDb25maWd1cmF0aW9uXG4gICk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHsgcmVuZXdUaW1lQmVmb3JlVG9rZW5FeHBpcmVzSW5TZWNvbmRzIH0gPSBjb25maWd1cmF0aW9uO1xuICAgIGNvbnN0IGFjY2Vzc1Rva2VuRXhwaXJlc0luID0gdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLnJlYWQoXG4gICAgICAnYWNjZXNzX3Rva2VuX2V4cGlyZXNfYXQnLFxuICAgICAgY29uZmlndXJhdGlvblxuICAgICk7XG4gICAgY29uc3QgYWNjZXNzVG9rZW5IYXNOb3RFeHBpcmVkID1cbiAgICAgIHRoaXMudG9rZW5WYWxpZGF0aW9uU2VydmljZS52YWxpZGF0ZUFjY2Vzc1Rva2VuTm90RXhwaXJlZChcbiAgICAgICAgYWNjZXNzVG9rZW5FeHBpcmVzSW4sXG4gICAgICAgIGNvbmZpZ3VyYXRpb24sXG4gICAgICAgIHJlbmV3VGltZUJlZm9yZVRva2VuRXhwaXJlc0luU2Vjb25kc1xuICAgICAgKTtcblxuICAgIGNvbnN0IGhhc0V4cGlyZWQgPSAhYWNjZXNzVG9rZW5IYXNOb3RFeHBpcmVkO1xuXG4gICAgaWYgKGhhc0V4cGlyZWQpIHtcbiAgICAgIHRoaXMucHVibGljRXZlbnRzU2VydmljZS5maXJlRXZlbnQ8Ym9vbGVhbj4oXG4gICAgICAgIEV2ZW50VHlwZXMuVG9rZW5FeHBpcmVkLFxuICAgICAgICBoYXNFeHBpcmVkXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBoYXNFeHBpcmVkO1xuICB9XG5cbiAgaXNBdXRoZW50aWNhdGVkKGNvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb24gfCBudWxsKTogYm9vbGVhbiB7XG4gICAgaWYgKCFjb25maWd1cmF0aW9uKSB7XG4gICAgICB0aHJvd0Vycm9yKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICdQbGVhc2UgcHJvdmlkZSBhIGNvbmZpZ3VyYXRpb24gYmVmb3JlIHNldHRpbmcgdXAgdGhlIG1vZHVsZSdcbiAgICAgICAgICApXG4gICAgICApO1xuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGFzQWNjZXNzVG9rZW4gPVxuICAgICAgISF0aGlzLnN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UuZ2V0QWNjZXNzVG9rZW4oY29uZmlndXJhdGlvbik7XG4gICAgY29uc3QgaGFzSWRUb2tlbiA9XG4gICAgICAhIXRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5nZXRJZFRva2VuKGNvbmZpZ3VyYXRpb24pO1xuXG4gICAgcmV0dXJuIGhhc0FjY2Vzc1Rva2VuICYmIGhhc0lkVG9rZW47XG4gIH1cblxuICBwcml2YXRlIGRlY29kZVVSSUNvbXBvbmVudFNhZmVseSh0b2tlbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAodG9rZW4pIHtcbiAgICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQodG9rZW4pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwZXJzaXN0QWNjZXNzVG9rZW5FeHBpcmF0aW9uVGltZShcbiAgICBhdXRoUmVzdWx0OiBBdXRoUmVzdWx0IHwgbnVsbCxcbiAgICBjb25maWd1cmF0aW9uOiBPcGVuSWRDb25maWd1cmF0aW9uXG4gICk6IHZvaWQge1xuICAgIGlmIChhdXRoUmVzdWx0Py5leHBpcmVzX2luKSB7XG4gICAgICBjb25zdCBhY2Nlc3NUb2tlbkV4cGlyeVRpbWUgPVxuICAgICAgICBuZXcgRGF0ZShuZXcgRGF0ZSgpLnRvVVRDU3RyaW5nKCkpLnZhbHVlT2YoKSArXG4gICAgICAgIGF1dGhSZXN1bHQuZXhwaXJlc19pbiAqIDEwMDA7XG5cbiAgICAgIHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS53cml0ZShcbiAgICAgICAgJ2FjY2Vzc190b2tlbl9leHBpcmVzX2F0JyxcbiAgICAgICAgYWNjZXNzVG9rZW5FeHBpcnlUaW1lLFxuICAgICAgICBjb25maWd1cmF0aW9uXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY29tcG9zZUF1dGhlbnRpY2F0ZWRSZXN1bHQoXG4gICAgYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdXG4gICk6IEF1dGhlbnRpY2F0ZWRSZXN1bHQge1xuICAgIGlmIChhbGxDb25maWdzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgY29uc3QgeyBjb25maWdJZCB9ID0gYWxsQ29uZmlnc1swXTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaXNBdXRoZW50aWNhdGVkOiB0cnVlLFxuICAgICAgICBhbGxDb25maWdzQXV0aGVudGljYXRlZDogW1xuICAgICAgICAgIHsgY29uZmlnSWQ6IGNvbmZpZ0lkID8/ICcnLCBpc0F1dGhlbnRpY2F0ZWQ6IHRydWUgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY2hlY2tBbGxDb25maWdzSWZUaGV5QXJlQXV0aGVudGljYXRlZChhbGxDb25maWdzKTtcbiAgfVxuXG4gIHByaXZhdGUgY29tcG9zZVVuQXV0aGVudGljYXRlZFJlc3VsdChcbiAgICBhbGxDb25maWdzOiBPcGVuSWRDb25maWd1cmF0aW9uW11cbiAgKTogQXV0aGVudGljYXRlZFJlc3VsdCB7XG4gICAgaWYgKGFsbENvbmZpZ3MubGVuZ3RoID09PSAxKSB7XG4gICAgICBjb25zdCB7IGNvbmZpZ0lkIH0gPSBhbGxDb25maWdzWzBdO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBpc0F1dGhlbnRpY2F0ZWQ6IGZhbHNlLFxuICAgICAgICBhbGxDb25maWdzQXV0aGVudGljYXRlZDogW1xuICAgICAgICAgIHsgY29uZmlnSWQ6IGNvbmZpZ0lkID8/ICcnLCBpc0F1dGhlbnRpY2F0ZWQ6IGZhbHNlIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNoZWNrQWxsQ29uZmlnc0lmVGhleUFyZUF1dGhlbnRpY2F0ZWQoYWxsQ29uZmlncyk7XG4gIH1cblxuICBwcml2YXRlIGNoZWNrQWxsQ29uZmlnc0lmVGhleUFyZUF1dGhlbnRpY2F0ZWQoXG4gICAgYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdXG4gICk6IEF1dGhlbnRpY2F0ZWRSZXN1bHQge1xuICAgIGNvbnN0IGFsbENvbmZpZ3NBdXRoZW50aWNhdGVkID0gYWxsQ29uZmlncy5tYXAoKGNvbmZpZykgPT4gKHtcbiAgICAgIGNvbmZpZ0lkOiBjb25maWcuY29uZmlnSWQgPz8gJycsXG4gICAgICBpc0F1dGhlbnRpY2F0ZWQ6IHRoaXMuaXNBdXRoZW50aWNhdGVkKGNvbmZpZyksXG4gICAgfSkpO1xuXG4gICAgY29uc3QgaXNBdXRoZW50aWNhdGVkID0gYWxsQ29uZmlnc0F1dGhlbnRpY2F0ZWQuZXZlcnkoXG4gICAgICAoeCkgPT4gISF4LmlzQXV0aGVudGljYXRlZFxuICAgICk7XG5cbiAgICByZXR1cm4geyBhbGxDb25maWdzQXV0aGVudGljYXRlZCwgaXNBdXRoZW50aWNhdGVkIH07XG4gIH1cbn1cbiJdfQ==