UNPKG

angular-auth-oidc-client

Version:
146 lines 28.4 kB
import { inject, Injectable } from '@angular/core'; import { forkJoin, of, throwError } from 'rxjs'; import { catchError, switchMap } from 'rxjs/operators'; import { AuthStateService } from '../auth-state/auth-state.service'; import { ConfigurationService } from '../config/config.service'; import { FlowsDataService } from '../flows/flows-data.service'; import { ResetAuthDataService } from '../flows/reset-auth-data.service'; import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service'; 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 { UserService } from '../user-data/user.service'; import { FlowHelper } from '../utils/flowHelper/flow-helper.service'; import { IntervalService } from './interval.service'; import { RefreshSessionRefreshTokenService } from './refresh-session-refresh-token.service'; import * as i0 from "@angular/core"; export class PeriodicallyTokenCheckService { constructor() { this.resetAuthDataService = inject(ResetAuthDataService); this.flowHelper = inject(FlowHelper); this.flowsDataService = inject(FlowsDataService); this.loggerService = inject(LoggerService); this.userService = inject(UserService); this.authStateService = inject(AuthStateService); this.refreshSessionIframeService = inject(RefreshSessionIframeService); this.refreshSessionRefreshTokenService = inject(RefreshSessionRefreshTokenService); this.intervalService = inject(IntervalService); this.storagePersistenceService = inject(StoragePersistenceService); this.publicEventsService = inject(PublicEventsService); this.configurationService = inject(ConfigurationService); } startTokenValidationPeriodically(allConfigs, currentConfig) { const configsWithSilentRenewEnabled = this.getConfigsWithSilentRenewEnabled(allConfigs); if (configsWithSilentRenewEnabled.length <= 0) { return; } if (this.intervalService.isTokenValidationRunning()) { return; } const refreshTimeInSeconds = this.getSmallestRefreshTimeFromConfigs(configsWithSilentRenewEnabled); const periodicallyCheck$ = this.intervalService .startPeriodicTokenCheck(refreshTimeInSeconds) .pipe(switchMap(() => { const objectWithConfigIdsAndRefreshEvent = {}; configsWithSilentRenewEnabled.forEach((config) => { const identifier = config.configId; const refreshEvent = this.getRefreshEvent(config, allConfigs); objectWithConfigIdsAndRefreshEvent[identifier] = refreshEvent; }); return forkJoin(objectWithConfigIdsAndRefreshEvent); })); this.intervalService.runTokenValidationRunning = periodicallyCheck$ .pipe(catchError((error) => throwError(() => new Error(error)))) .subscribe({ next: (objectWithConfigIds) => { for (const [configId, _] of Object.entries(objectWithConfigIds)) { this.configurationService .getOpenIDConfiguration(configId) .subscribe((config) => { this.loggerService.logDebug(config, 'silent renew, periodic check finished!'); if (this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config)) { this.flowsDataService.resetSilentRenewRunning(config); } }); } }, error: (error) => { this.loggerService.logError(currentConfig, 'silent renew failed!', error); }, }); } getRefreshEvent(config, allConfigs) { const shouldStartRefreshEvent = this.shouldStartPeriodicallyCheckForConfig(config); if (!shouldStartRefreshEvent) { return of(null); } const refreshEvent$ = this.createRefreshEventForConfig(config, allConfigs); this.publicEventsService.fireEvent(EventTypes.SilentRenewStarted); return refreshEvent$.pipe(catchError((error) => { this.loggerService.logError(config, 'silent renew failed!', error); this.publicEventsService.fireEvent(EventTypes.SilentRenewFailed, error); this.flowsDataService.resetSilentRenewRunning(config); return throwError(() => new Error(error)); })); } getSmallestRefreshTimeFromConfigs(configsWithSilentRenewEnabled) { const result = configsWithSilentRenewEnabled.reduce((prev, curr) => (prev.tokenRefreshInSeconds ?? 0) < (curr.tokenRefreshInSeconds ?? 0) ? prev : curr); return result.tokenRefreshInSeconds ?? 0; } getConfigsWithSilentRenewEnabled(allConfigs) { return allConfigs.filter((x) => x.silentRenew); } createRefreshEventForConfig(configuration, allConfigs) { this.loggerService.logDebug(configuration, 'starting silent renew...'); return this.configurationService .getOpenIDConfiguration(configuration.configId) .pipe(switchMap((config) => { if (!config?.silentRenew) { this.resetAuthDataService.resetAuthorizationData(config, allConfigs); return of(null); } this.flowsDataService.setSilentRenewRunning(config); if (this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config)) { // Retrieve Dynamically Set Custom Params for refresh body const customParamsRefresh = this.storagePersistenceService.read('storageCustomParamsRefresh', config) || {}; const { customParamsRefreshTokenRequest } = config; const mergedParams = { ...customParamsRefreshTokenRequest, ...customParamsRefresh, }; // Refresh Session using Refresh tokens return this.refreshSessionRefreshTokenService.refreshSessionWithRefreshTokens(config, allConfigs, mergedParams); } // Retrieve Dynamically Set Custom Params const customParams = this.storagePersistenceService.read('storageCustomParamsAuthRequest', config); return this.refreshSessionIframeService.refreshSessionWithIframe(config, allConfigs, customParams); })); } shouldStartPeriodicallyCheckForConfig(config) { const idToken = this.authStateService.getIdToken(config); const isSilentRenewRunning = this.flowsDataService.isSilentRenewRunning(config); const isCodeFlowInProgress = this.flowsDataService.isCodeFlowInProgress(config); const userDataFromStore = this.userService.getUserDataFromStore(config); this.loggerService.logDebug(config, `Checking: silentRenewRunning: ${isSilentRenewRunning}, isCodeFlowInProgress: ${isCodeFlowInProgress} - has idToken: ${!!idToken} - has userData: ${!!userDataFromStore}`); const shouldBeExecuted = !!userDataFromStore && !isSilentRenewRunning && !!idToken && !isCodeFlowInProgress; if (!shouldBeExecuted) { return false; } const idTokenExpired = this.authStateService.hasIdTokenExpiredAndRenewCheckIsEnabled(config); const accessTokenExpired = this.authStateService.hasAccessTokenExpiredIfExpiryExists(config); return idTokenExpired || accessTokenExpired; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: PeriodicallyTokenCheckService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: PeriodicallyTokenCheckService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: PeriodicallyTokenCheckService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVyaW9kaWNhbGx5LXRva2VuLWNoZWNrLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWF1dGgtb2lkYy1jbGllbnQvc3JjL2xpYi9jYWxsYmFjay9wZXJpb2RpY2FsbHktdG9rZW4tY2hlY2suc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQUUsUUFBUSxFQUFjLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDNUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNwRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUdoRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUN4RSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUN2RixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzFELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQzdFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ25GLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDckUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG9CQUFv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Q0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV4RSxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FDekIsTUFBTSxFQUNOLGlDQUFpQyxvQkFBb0IsMkJBQTJCLG9CQUFvQixtQkFBbUIsQ0FBQyxDQUFDLE9BQU8sb0JBQW9CLENBQUMsQ0FBQyxpQkFBaUIsRUFBRSxDQUMxSyxDQUFDO1FBRUYsTUFBTSxnQkFBZ0IsR0FDcEIsQ0FBQyxDQUFDLGlCQUFpQjtZQUNuQixDQUFDLG9CQUFvQjtZQUNyQixDQUFDLENBQUMsT0FBTztZQUNULENBQUMsb0JBQW9CLENBQUM7UUFFeEIsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDdEIsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsTUFBTSxjQUFjLEdBQ2xCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyx1Q0FBdUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4RSxNQUFNLGtCQUFrQixHQUN0QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsbUNBQW1DLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFcEUsT0FBTyxjQUFjLElBQUksa0JBQWtCLENBQUM7SUFDOUMsQ0FBQzs4R0E1T1UsNkJBQTZCO2tIQUE3Qiw2QkFBNkIsY0FEaEIsTUFBTTs7MkZBQ25CLDZCQUE2QjtrQkFEekMsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGZvcmtKb2luLCBPYnNlcnZhYmxlLCBvZiwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQXV0aFN0YXRlU2VydmljZSB9IGZyb20gJy4uL2F1dGgtc3RhdGUvYXV0aC1zdGF0ZS5zZXJ2aWNlJztcbmltcG9ydCB7IENvbmZpZ3VyYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vY29uZmlnL2NvbmZpZy5zZXJ2aWNlJztcbmltcG9ydCB7IE9wZW5JZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9jb25maWcvb3BlbmlkLWNvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgQ2FsbGJhY2tDb250ZXh0IH0gZnJvbSAnLi4vZmxvd3MvY2FsbGJhY2stY29udGV4dCc7XG5pbXBvcnQgeyBGbG93c0RhdGFTZXJ2aWNlIH0gZnJvbSAnLi4vZmxvd3MvZmxvd3MtZGF0YS5zZXJ2aWNlJztcbmltcG9ydCB7IFJlc2V0QXV0aERhdGFTZXJ2aWNlIH0gZnJvbSAnLi4vZmxvd3MvcmVzZXQtYXV0aC1kYXRhLnNlcnZpY2UnO1xuaW1wb3J0IHsgUmVmcmVzaFNlc3Npb25JZnJhbWVTZXJ2aWNlIH0gZnJvbSAnLi4vaWZyYW1lL3JlZnJlc2gtc2Vzc2lvbi1pZnJhbWUuc2VydmljZSc7XG5pbXBvcnQgeyBMb2dnZXJTZXJ2aWNlIH0gZnJvbSAnLi4vbG9nZ2luZy9sb2dnZXIuc2VydmljZSc7XG5pbXBvcnQgeyBFdmVudFR5cGVzIH0gZnJvbSAnLi4vcHVibGljLWV2ZW50cy9ldmVudC10eXBlcyc7XG5pbXBvcnQgeyBQdWJsaWNFdmVudHNTZXJ2aWNlIH0gZnJvbSAnLi4vcHVibGljLWV2ZW50cy9wdWJsaWMtZXZlbnRzLnNlcnZpY2UnO1xuaW1wb3J0IHsgU3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZSB9IGZyb20gJy4uL3N0b3JhZ2Uvc3RvcmFnZS1wZXJzaXN0ZW5jZS5zZXJ2aWNlJztcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlci1kYXRhL3VzZXIuc2VydmljZSc7XG5pbXBvcnQgeyBGbG93SGVscGVyIH0gZnJvbSAnLi4vdXRpbHMvZmxvd0hlbHBlci9mbG93LWhlbHBlci5zZXJ2aWNlJztcbmltcG9ydCB7IEludGVydmFsU2VydmljZSB9IGZyb20gJy4vaW50ZXJ2YWwuc2VydmljZSc7XG5pbXBvcnQgeyBSZWZyZXNoU2Vzc2lvblJlZnJlc2hUb2tlblNlcnZpY2UgfSBmcm9tICcuL3JlZnJlc2gtc2Vzc2lvbi1yZWZyZXNoLXRva2VuLnNlcnZpY2UnO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFBlcmlvZGljYWxseVRva2VuQ2hlY2tTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSByZXNldEF1dGhEYXRhU2VydmljZSA9IGluamVjdChSZXNldEF1dGhEYXRhU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBmbG93SGVscGVyID0gaW5qZWN0KEZsb3dIZWxwZXIpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZmxvd3NEYXRhU2VydmljZSA9IGluamVjdChGbG93c0RhdGFTZXJ2aWNlKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGxvZ2dlclNlcnZpY2UgPSBpbmplY3QoTG9nZ2VyU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB1c2VyU2VydmljZSA9IGluamVjdChVc2VyU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBhdXRoU3RhdGVTZXJ2aWNlID0gaW5qZWN0KEF1dGhTdGF0ZVNlcnZpY2UpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVmcmVzaFNlc3Npb25JZnJhbWVTZXJ2aWNlID0gaW5qZWN0KFxuICAgIFJlZnJlc2hTZXNzaW9uSWZyYW1lU2VydmljZVxuICApO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVmcmVzaFNlc3Npb25SZWZyZXNoVG9rZW5TZXJ2aWNlID0gaW5qZWN0KFxuICAgIFJlZnJlc2hTZXNzaW9uUmVmcmVzaFRva2VuU2VydmljZVxuICApO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaW50ZXJ2YWxTZXJ2aWNlID0gaW5qZWN0KEludGVydmFsU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlID0gaW5qZWN0KFxuICAgIFN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2VcbiAgKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHB1YmxpY0V2ZW50c1NlcnZpY2UgPSBpbmplY3QoUHVibGljRXZlbnRzU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjb25maWd1cmF0aW9uU2VydmljZSA9IGluamVjdChDb25maWd1cmF0aW9uU2VydmljZSk7XG5cbiAgc3RhcnRUb2tlblZhbGlkYXRpb25QZXJpb2RpY2FsbHkoXG4gICAgYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdLFxuICAgIGN1cnJlbnRDb25maWc6IE9wZW5JZENvbmZpZ3VyYXRpb25cbiAgKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnc1dpdGhTaWxlbnRSZW5ld0VuYWJsZWQgPVxuICAgICAgdGhpcy5nZXRDb25maWdzV2l0aFNpbGVudFJlbmV3RW5hYmxlZChhbGxDb25maWdzKTtcblxuICAgIGlmIChjb25maWdzV2l0aFNpbGVudFJlbmV3RW5hYmxlZC5sZW5ndGggPD0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmludGVydmFsU2VydmljZS5pc1Rva2VuVmFsaWRhdGlvblJ1bm5pbmcoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJlZnJlc2hUaW1lSW5TZWNvbmRzID0gdGhpcy5nZXRTbWFsbGVzdFJlZnJlc2hUaW1lRnJvbUNvbmZpZ3MoXG4gICAgICBjb25maWdzV2l0aFNpbGVudFJlbmV3RW5hYmxlZFxuICAgICk7XG4gICAgY29uc3QgcGVyaW9kaWNhbGx5Q2hlY2skID0gdGhpcy5pbnRlcnZhbFNlcnZpY2VcbiAgICAgIC5zdGFydFBlcmlvZGljVG9rZW5DaGVjayhyZWZyZXNoVGltZUluU2Vjb25kcylcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IG9iamVjdFdpdGhDb25maWdJZHNBbmRSZWZyZXNoRXZlbnQ6IHtcbiAgICAgICAgICAgIFtpZDogc3RyaW5nXTogT2JzZXJ2YWJsZTxib29sZWFuIHwgQ2FsbGJhY2tDb250ZXh0IHwgbnVsbD47XG4gICAgICAgICAgfSA9IHt9O1xuXG4gICAgICAgICAgY29uZmlnc1dpdGhTaWxlbnRSZW5ld0VuYWJsZWQuZm9yRWFjaCgoY29uZmlnKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBpZGVudGlmaWVyID0gY29uZmlnLmNvbmZpZ0lkIGFzIHN0cmluZztcbiAgICAgICAgICAgIGNvbnN0IHJlZnJlc2hFdmVudCA9IHRoaXMuZ2V0UmVmcmVzaEV2ZW50KGNvbmZpZywgYWxsQ29uZmlncyk7XG5cbiAgICAgICAgICAgIG9iamVjdFdpdGhDb25maWdJZHNBbmRSZWZyZXNoRXZlbnRbaWRlbnRpZmllcl0gPSByZWZyZXNoRXZlbnQ7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXR1cm4gZm9ya0pvaW4ob2JqZWN0V2l0aENvbmZpZ0lkc0FuZFJlZnJlc2hFdmVudCk7XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgdGhpcy5pbnRlcnZhbFNlcnZpY2UucnVuVG9rZW5WYWxpZGF0aW9uUnVubmluZyA9IHBlcmlvZGljYWxseUNoZWNrJFxuICAgICAgLnBpcGUoY2F0Y2hFcnJvcigoZXJyb3IpID0+IHRocm93RXJyb3IoKCkgPT4gbmV3IEVycm9yKGVycm9yKSkpKVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChvYmplY3RXaXRoQ29uZmlnSWRzKSA9PiB7XG4gICAgICAgICAgZm9yIChjb25zdCBbY29uZmlnSWQsIF9dIG9mIE9iamVjdC5lbnRyaWVzKG9iamVjdFdpdGhDb25maWdJZHMpKSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb25TZXJ2aWNlXG4gICAgICAgICAgICAgIC5nZXRPcGVuSURDb25maWd1cmF0aW9uKGNvbmZpZ0lkKVxuICAgICAgICAgICAgICAuc3Vic2NyaWJlKChjb25maWcpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoXG4gICAgICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgICAgICAnc2lsZW50IHJlbmV3LCBwZXJpb2RpYyBjaGVjayBmaW5pc2hlZCEnXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgIHRoaXMuZmxvd0hlbHBlci5pc0N1cnJlbnRGbG93Q29kZUZsb3dXaXRoUmVmcmVzaFRva2Vucyhjb25maWcpXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICB0aGlzLmZsb3dzRGF0YVNlcnZpY2UucmVzZXRTaWxlbnRSZW5ld1J1bm5pbmcoY29uZmlnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dFcnJvcihcbiAgICAgICAgICAgIGN1cnJlbnRDb25maWcsXG4gICAgICAgICAgICAnc2lsZW50IHJlbmV3IGZhaWxlZCEnLFxuICAgICAgICAgICAgZXJyb3JcbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGdldFJlZnJlc2hFdmVudChcbiAgICBjb25maWc6IE9wZW5JZENvbmZpZ3VyYXRpb24sXG4gICAgYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdXG4gICk6IE9ic2VydmFibGU8Ym9vbGVhbiB8IENhbGxiYWNrQ29udGV4dCB8IG51bGw+IHtcbiAgICBjb25zdCBzaG91bGRTdGFydFJlZnJlc2hFdmVudCA9XG4gICAgICB0aGlzLnNob3VsZFN0YXJ0UGVyaW9kaWNhbGx5Q2hlY2tGb3JDb25maWcoY29uZmlnKTtcblxuICAgIGlmICghc2hvdWxkU3RhcnRSZWZyZXNoRXZlbnQpIHtcbiAgICAgIHJldHVybiBvZihudWxsKTtcbiAgICB9XG5cbiAgICBjb25zdCByZWZyZXNoRXZlbnQkID0gdGhpcy5jcmVhdGVSZWZyZXNoRXZlbnRGb3JDb25maWcoY29uZmlnLCBhbGxDb25maWdzKTtcblxuICAgIHRoaXMucHVibGljRXZlbnRzU2VydmljZS5maXJlRXZlbnQoRXZlbnRUeXBlcy5TaWxlbnRSZW5ld1N0YXJ0ZWQpO1xuXG4gICAgcmV0dXJuIHJlZnJlc2hFdmVudCQucGlwZShcbiAgICAgIGNhdGNoRXJyb3IoKGVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dFcnJvcihjb25maWcsICdzaWxlbnQgcmVuZXcgZmFpbGVkIScsIGVycm9yKTtcbiAgICAgICAgdGhpcy5wdWJsaWNFdmVudHNTZXJ2aWNlLmZpcmVFdmVudChFdmVudFR5cGVzLlNpbGVudFJlbmV3RmFpbGVkLCBlcnJvcik7XG4gICAgICAgIHRoaXMuZmxvd3NEYXRhU2VydmljZS5yZXNldFNpbGVudFJlbmV3UnVubmluZyhjb25maWcpO1xuXG4gICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBFcnJvcihlcnJvcikpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTbWFsbGVzdFJlZnJlc2hUaW1lRnJvbUNvbmZpZ3MoXG4gICAgY29uZmlnc1dpdGhTaWxlbnRSZW5ld0VuYWJsZWQ6IE9wZW5JZENvbmZpZ3VyYXRpb25bXVxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IHJlc3VsdCA9IGNvbmZpZ3NXaXRoU2lsZW50UmVuZXdFbmFibGVkLnJlZHVjZSgocHJldiwgY3VycikgPT5cbiAgICAgIChwcmV2LnRva2VuUmVmcmVzaEluU2Vjb25kcyA/PyAwKSA8IChjdXJyLnRva2VuUmVmcmVzaEluU2Vjb25kcyA/PyAwKVxuICAgICAgICA/IHByZXZcbiAgICAgICAgOiBjdXJyXG4gICAgKTtcblxuICAgIHJldHVybiByZXN1bHQudG9rZW5SZWZyZXNoSW5TZWNvbmRzID8/IDA7XG4gIH1cblxuICBwcml2YXRlIGdldENvbmZpZ3NXaXRoU2lsZW50UmVuZXdFbmFibGVkKFxuICAgIGFsbENvbmZpZ3M6IE9wZW5JZENvbmZpZ3VyYXRpb25bXVxuICApOiBPcGVuSWRDb25maWd1cmF0aW9uW10ge1xuICAgIHJldHVybiBhbGxDb25maWdzLmZpbHRlcigoeCkgPT4geC5zaWxlbnRSZW5ldyk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVJlZnJlc2hFdmVudEZvckNvbmZpZyhcbiAgICBjb25maWd1cmF0aW9uOiBPcGVuSWRDb25maWd1cmF0aW9uLFxuICAgIGFsbENvbmZpZ3M6IE9wZW5JZENvbmZpZ3VyYXRpb25bXVxuICApOiBPYnNlcnZhYmxlPGJvb2xlYW4gfCBDYWxsYmFja0NvbnRleHQgfCBudWxsPiB7XG4gICAgdGhpcy5sb2dnZXJTZXJ2aWNlLmxvZ0RlYnVnKGNvbmZpZ3VyYXRpb24sICdzdGFydGluZyBzaWxlbnQgcmVuZXcuLi4nKTtcblxuICAgIHJldHVybiB0aGlzLmNvbmZpZ3VyYXRpb25TZXJ2aWNlXG4gICAgICAuZ2V0T3BlbklEQ29uZmlndXJhdGlvbihjb25maWd1cmF0aW9uLmNvbmZpZ0lkKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgoY29uZmlnKSA9PiB7XG4gICAgICAgICAgaWYgKCFjb25maWc/LnNpbGVudFJlbmV3KSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0QXV0aERhdGFTZXJ2aWNlLnJlc2V0QXV0aG9yaXphdGlvbkRhdGEoXG4gICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgYWxsQ29uZmlnc1xuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgcmV0dXJuIG9mKG51bGwpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuZmxvd3NEYXRhU2VydmljZS5zZXRTaWxlbnRSZW5ld1J1bm5pbmcoY29uZmlnKTtcblxuICAgICAgICAgIGlmICh0aGlzLmZsb3dIZWxwZXIuaXNDdXJyZW50Rmxvd0NvZGVGbG93V2l0aFJlZnJlc2hUb2tlbnMoY29uZmlnKSkge1xuICAgICAgICAgICAgLy8gUmV0cmlldmUgRHluYW1pY2FsbHkgU2V0IEN1c3RvbSBQYXJhbXMgZm9yIHJlZnJlc2ggYm9keVxuICAgICAgICAgICAgY29uc3QgY3VzdG9tUGFyYW1zUmVmcmVzaDoge1xuICAgICAgICAgICAgICBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuO1xuICAgICAgICAgICAgfSA9XG4gICAgICAgICAgICAgIHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5yZWFkKFxuICAgICAgICAgICAgICAgICdzdG9yYWdlQ3VzdG9tUGFyYW1zUmVmcmVzaCcsXG4gICAgICAgICAgICAgICAgY29uZmlnXG4gICAgICAgICAgICAgICkgfHwge307XG5cbiAgICAgICAgICAgIGNvbnN0IHsgY3VzdG9tUGFyYW1zUmVmcmVzaFRva2VuUmVxdWVzdCB9ID0gY29uZmlnO1xuXG4gICAgICAgICAgICBjb25zdCBtZXJnZWRQYXJhbXMgPSB7XG4gICAgICAgICAgICAgIC4uLmN1c3RvbVBhcmFtc1JlZnJlc2hUb2tlblJlcXVlc3QsXG4gICAgICAgICAgICAgIC4uLmN1c3RvbVBhcmFtc1JlZnJlc2gsXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBSZWZyZXNoIFNlc3Npb24gdXNpbmcgUmVmcmVzaCB0b2tlbnNcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlZnJlc2hTZXNzaW9uUmVmcmVzaFRva2VuU2VydmljZS5yZWZyZXNoU2Vzc2lvbldpdGhSZWZyZXNoVG9rZW5zKFxuICAgICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICAgIGFsbENvbmZpZ3MsXG4gICAgICAgICAgICAgIG1lcmdlZFBhcmFtc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBSZXRyaWV2ZSBEeW5hbWljYWxseSBTZXQgQ3VzdG9tIFBhcmFtc1xuICAgICAgICAgIGNvbnN0IGN1c3RvbVBhcmFtczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIH0gPVxuICAgICAgICAgICAgdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLnJlYWQoXG4gICAgICAgICAgICAgICdzdG9yYWdlQ3VzdG9tUGFyYW1zQXV0aFJlcXVlc3QnLFxuICAgICAgICAgICAgICBjb25maWdcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoU2Vzc2lvbklmcmFtZVNlcnZpY2UucmVmcmVzaFNlc3Npb25XaXRoSWZyYW1lKFxuICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgYWxsQ29uZmlncyxcbiAgICAgICAgICAgIGN1c3RvbVBhcmFtc1xuICAgICAgICAgICk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzaG91bGRTdGFydFBlcmlvZGljYWxseUNoZWNrRm9yQ29uZmlnKFxuICAgIGNvbmZpZzogT3BlbklkQ29uZmlndXJhdGlvblxuICApOiBib29sZWFuIHtcbiAgICBjb25zdCBpZFRva2VuID0gdGhpcy5hdXRoU3RhdGVTZXJ2aWNlLmdldElkVG9rZW4oY29uZmlnKTtcbiAgICBjb25zdCBpc1NpbGVudFJlbmV3UnVubmluZyA9XG4gICAgICB0aGlzLmZsb3dzRGF0YVNlcnZpY2UuaXNTaWxlbnRSZW5ld1J1bm5pbmcoY29uZmlnKTtcbiAgICBjb25zdCBpc0NvZGVGbG93SW5Qcm9ncmVzcyA9XG4gICAgICB0aGlzLmZsb3dzRGF0YVNlcnZpY2UuaXNDb2RlRmxvd0luUHJvZ3Jlc3MoY29uZmlnKTtcbiAgICBjb25zdCB1c2VyRGF0YUZyb21TdG9yZSA9IHRoaXMudXNlclNlcnZpY2UuZ2V0VXNlckRhdGFGcm9tU3RvcmUoY29uZmlnKTtcblxuICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dEZWJ1ZyhcbiAgICAgIGNvbmZpZyxcbiAgICAgIGBDaGVja2luZzogc2lsZW50UmVuZXdSdW5uaW5nOiAke2lzU2lsZW50UmVuZXdSdW5uaW5nfSwgaXNDb2RlRmxvd0luUHJvZ3Jlc3M6ICR7aXNDb2RlRmxvd0luUHJvZ3Jlc3N9IC0gaGFzIGlkVG9rZW46ICR7ISFpZFRva2VufSAtIGhhcyB1c2VyRGF0YTogJHshIXVzZXJEYXRhRnJvbVN0b3JlfWBcbiAgICApO1xuXG4gICAgY29uc3Qgc2hvdWxkQmVFeGVjdXRlZCA9XG4gICAgICAhIXVzZXJEYXRhRnJvbVN0b3JlICYmXG4gICAgICAhaXNTaWxlbnRSZW5ld1J1bm5pbmcgJiZcbiAgICAgICEhaWRUb2tlbiAmJlxuICAgICAgIWlzQ29kZUZsb3dJblByb2dyZXNzO1xuXG4gICAgaWYgKCFzaG91bGRCZUV4ZWN1dGVkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaWRUb2tlbkV4cGlyZWQgPVxuICAgICAgdGhpcy5hdXRoU3RhdGVTZXJ2aWNlLmhhc0lkVG9rZW5FeHBpcmVkQW5kUmVuZXdDaGVja0lzRW5hYmxlZChjb25maWcpO1xuICAgIGNvbnN0IGFjY2Vzc1Rva2VuRXhwaXJlZCA9XG4gICAgICB0aGlzLmF1dGhTdGF0ZVNlcnZpY2UuaGFzQWNjZXNzVG9rZW5FeHBpcmVkSWZFeHBpcnlFeGlzdHMoY29uZmlnKTtcblxuICAgIHJldHVybiBpZFRva2VuRXhwaXJlZCB8fCBhY2Nlc3NUb2tlbkV4cGlyZWQ7XG4gIH1cbn1cbiJdfQ==