angular-auth-oidc-client
Version:
Angular Lib for OpenID Connect & OAuth2
170 lines • 30.6 kB
JavaScript
import { Injectable, inject } from '@angular/core';
import { BehaviorSubject, of, throwError } from 'rxjs';
import { map, retry, switchMap } from 'rxjs/operators';
import { DataService } from '../api/data.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 { FlowHelper } from '../utils/flowHelper/flow-helper.service';
import { TokenHelperService } from '../utils/tokenHelper/token-helper.service';
import * as i0 from "@angular/core";
const DEFAULT_USERRESULT = { userData: null, allUserData: [] };
export class UserService {
constructor() {
this.userDataInternal$ = new BehaviorSubject(DEFAULT_USERRESULT);
this.loggerService = inject(LoggerService);
this.tokenHelperService = inject(TokenHelperService);
this.flowHelper = inject(FlowHelper);
this.oidcDataService = inject(DataService);
this.storagePersistenceService = inject(StoragePersistenceService);
this.eventService = inject(PublicEventsService);
}
get userData$() {
return this.userDataInternal$.asObservable();
}
getAndPersistUserDataInStore(currentConfiguration, allConfigs, isRenewProcess = false, idToken, decodedIdToken) {
idToken =
idToken ||
this.storagePersistenceService.getIdToken(currentConfiguration);
decodedIdToken =
decodedIdToken ||
this.tokenHelperService.getPayloadFromToken(idToken, false, currentConfiguration);
const existingUserDataFromStorage = this.getUserDataFromStore(currentConfiguration);
const haveUserData = !!existingUserDataFromStorage;
const isCurrentFlowImplicitFlowWithAccessToken = this.flowHelper.isCurrentFlowImplicitFlowWithAccessToken(currentConfiguration);
const isCurrentFlowCodeFlow = this.flowHelper.isCurrentFlowCodeFlow(currentConfiguration);
const accessToken = this.storagePersistenceService.getAccessToken(currentConfiguration);
if (!(isCurrentFlowImplicitFlowWithAccessToken || isCurrentFlowCodeFlow)) {
this.loggerService.logDebug(currentConfiguration, `authCallback idToken flow with accessToken ${accessToken}`);
this.setUserDataToStore(decodedIdToken, currentConfiguration, allConfigs);
return of(decodedIdToken);
}
const { renewUserInfoAfterTokenRenew } = currentConfiguration;
if (!isRenewProcess || renewUserInfoAfterTokenRenew || !haveUserData) {
return this.getUserDataOidcFlowAndSave(decodedIdToken.sub, currentConfiguration, allConfigs).pipe(switchMap((userData) => {
this.loggerService.logDebug(currentConfiguration, 'Received user data: ', userData);
if (!!userData) {
this.loggerService.logDebug(currentConfiguration, 'accessToken: ', accessToken);
return of(userData);
}
else {
return throwError(() => new Error('Received no user data, request failed'));
}
}));
}
return of(existingUserDataFromStorage);
}
getUserDataFromStore(currentConfiguration) {
if (!currentConfiguration) {
return throwError(() => new Error('Please provide a configuration before setting up the module'));
}
return (this.storagePersistenceService.read('userData', currentConfiguration) ||
null);
}
publishUserDataIfExists(currentConfiguration, allConfigs) {
const userData = this.getUserDataFromStore(currentConfiguration);
if (userData) {
this.fireUserDataEvent(currentConfiguration, allConfigs, userData);
}
}
setUserDataToStore(userData, currentConfiguration, allConfigs) {
this.storagePersistenceService.write('userData', userData, currentConfiguration);
this.fireUserDataEvent(currentConfiguration, allConfigs, userData);
}
resetUserDataInStore(currentConfiguration, allConfigs) {
this.storagePersistenceService.remove('userData', currentConfiguration);
this.fireUserDataEvent(currentConfiguration, allConfigs, null);
}
getUserDataOidcFlowAndSave(idTokenSub, currentConfiguration, allConfigs) {
return this.getIdentityUserData(currentConfiguration).pipe(map((data) => {
if (this.validateUserDataSubIdToken(currentConfiguration, idTokenSub, data?.sub)) {
this.setUserDataToStore(data, currentConfiguration, allConfigs);
return data;
}
else {
// something went wrong, user data sub does not match that from id_token
this.loggerService.logWarning(currentConfiguration, `User data sub does not match sub in id_token, resetting`);
this.resetUserDataInStore(currentConfiguration, allConfigs);
return null;
}
}));
}
getIdentityUserData(currentConfiguration) {
const token = this.storagePersistenceService.getAccessToken(currentConfiguration);
const authWellKnownEndPoints = this.storagePersistenceService.read('authWellKnownEndPoints', currentConfiguration);
if (!authWellKnownEndPoints) {
this.loggerService.logWarning(currentConfiguration, 'init check session: authWellKnownEndpoints is undefined');
return throwError(() => new Error('authWellKnownEndpoints is undefined'));
}
const userInfoEndpoint = authWellKnownEndPoints.userInfoEndpoint;
if (!userInfoEndpoint) {
this.loggerService.logError(currentConfiguration, 'init check session: authWellKnownEndpoints.userinfo_endpoint is undefined; set auto_userinfo = false in config');
return throwError(() => new Error('authWellKnownEndpoints.userinfo_endpoint is undefined'));
}
return this.oidcDataService
.get(userInfoEndpoint, currentConfiguration, token)
.pipe(retry(2));
}
validateUserDataSubIdToken(currentConfiguration, idTokenSub, userDataSub) {
if (!idTokenSub) {
return false;
}
if (!userDataSub) {
return false;
}
if (idTokenSub.toString() !== userDataSub.toString()) {
this.loggerService.logDebug(currentConfiguration, 'validateUserDataSubIdToken failed', idTokenSub, userDataSub);
return false;
}
return true;
}
fireUserDataEvent(currentConfiguration, allConfigs, passedUserData) {
const userData = this.composeSingleOrMultipleUserDataObject(currentConfiguration, allConfigs, passedUserData);
this.userDataInternal$.next(userData);
const { configId } = currentConfiguration;
this.eventService.fireEvent(EventTypes.UserDataChanged, {
configId,
userData: passedUserData,
});
}
composeSingleOrMultipleUserDataObject(currentConfiguration, allConfigs, passedUserData) {
const hasManyConfigs = allConfigs.length > 1;
if (!hasManyConfigs) {
const { configId } = currentConfiguration;
return this.composeSingleUserDataResult(configId ?? '', passedUserData);
}
const allUserData = allConfigs.map((config) => {
const currentConfigId = currentConfiguration.configId ?? '';
const configId = config.configId ?? '';
if (this.currentConfigIsToUpdate(currentConfigId, config)) {
return { configId, userData: passedUserData };
}
const alreadySavedUserData = this.storagePersistenceService.read('userData', config) || null;
return {
configId,
userData: alreadySavedUserData,
};
});
return {
userData: null,
allUserData,
};
}
composeSingleUserDataResult(configId, userData) {
return {
userData,
allUserData: [{ configId, userData }],
};
}
currentConfigIsToUpdate(configId, config) {
return config.configId === configId;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: UserService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: UserService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1hdXRoLW9pZGMtY2xpZW50L3NyYy9saWIvdXNlci1kYXRhL3VzZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQUUsZUFBZSxFQUFjLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDbkUsT0FBTyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWxELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDMUQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDN0UsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDbkYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDJDQUEyQyxDQUFDOztBQUcvRSxNQUFNLGtCQUFrQixHQUFHLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLENBQUM7QUFHL0QsTUFBTSxPQUFPLFdBQVc7SUFEeEI7UUFFbUIsc0JBQWlCLEdBQUcsSUFBSSxlQUFlLENBQ3RELGtCQUFrQixDQUNuQixDQUFDO1FBTWUsa0JBQWEsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFdEMsdUJBQWtCLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFFaEQs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QztTQUN0QyxDQUFDO0lBQ0osQ0FBQztJQUVPLHVCQUF1QixDQUM3QixRQUFnQixFQUNoQixNQUEyQjtRQUUzQixPQUFPLE1BQU0sQ0FBQyxRQUFRLEtBQUssUUFBUSxDQUFDO0lBQ3RDLENBQUM7OEdBM1RVLFdBQVc7a0hBQVgsV0FBVyxjQURFLE1BQU07OzJGQUNuQixXQUFXO2tCQUR2QixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBvZiwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCByZXRyeSwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgRGF0YVNlcnZpY2UgfSBmcm9tICcuLi9hcGkvZGF0YS5zZXJ2aWNlJztcbmltcG9ydCB7IE9wZW5JZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9jb25maWcvb3BlbmlkLWNvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgTG9nZ2VyU2VydmljZSB9IGZyb20gJy4uL2xvZ2dpbmcvbG9nZ2VyLnNlcnZpY2UnO1xuaW1wb3J0IHsgRXZlbnRUeXBlcyB9IGZyb20gJy4uL3B1YmxpYy1ldmVudHMvZXZlbnQtdHlwZXMnO1xuaW1wb3J0IHsgUHVibGljRXZlbnRzU2VydmljZSB9IGZyb20gJy4uL3B1YmxpYy1ldmVudHMvcHVibGljLWV2ZW50cy5zZXJ2aWNlJztcbmltcG9ydCB7IFN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UgfSBmcm9tICcuLi9zdG9yYWdlL3N0b3JhZ2UtcGVyc2lzdGVuY2Uuc2VydmljZSc7XG5pbXBvcnQgeyBGbG93SGVscGVyIH0gZnJvbSAnLi4vdXRpbHMvZmxvd0hlbHBlci9mbG93LWhlbHBlci5zZXJ2aWNlJztcbmltcG9ydCB7IFRva2VuSGVscGVyU2VydmljZSB9IGZyb20gJy4uL3V0aWxzL3Rva2VuSGVscGVyL3Rva2VuLWhlbHBlci5zZXJ2aWNlJztcbmltcG9ydCB7IENvbmZpZ1VzZXJEYXRhUmVzdWx0LCBVc2VyRGF0YVJlc3VsdCB9IGZyb20gJy4vdXNlcmRhdGEtcmVzdWx0JztcblxuY29uc3QgREVGQVVMVF9VU0VSUkVTVUxUID0geyB1c2VyRGF0YTogbnVsbCwgYWxsVXNlckRhdGE6IFtdIH07XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgVXNlclNlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IHVzZXJEYXRhSW50ZXJuYWwkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxVc2VyRGF0YVJlc3VsdD4oXG4gICAgREVGQVVMVF9VU0VSUkVTVUxUXG4gICk7XG5cbiAgZ2V0IHVzZXJEYXRhJCgpOiBPYnNlcnZhYmxlPFVzZXJEYXRhUmVzdWx0PiB7XG4gICAgcmV0dXJuIHRoaXMudXNlckRhdGFJbnRlcm5hbCQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IGxvZ2dlclNlcnZpY2UgPSBpbmplY3QoTG9nZ2VyU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB0b2tlbkhlbHBlclNlcnZpY2UgPSBpbmplY3QoVG9rZW5IZWxwZXJTZXJ2aWNlKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGZsb3dIZWxwZXIgPSBpbmplY3QoRmxvd0hlbHBlcik7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBvaWRjRGF0YVNlcnZpY2UgPSBpbmplY3QoRGF0YVNlcnZpY2UpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZSA9IGluamVjdChcbiAgICBTdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlXG4gICk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBldmVudFNlcnZpY2UgPSBpbmplY3QoUHVibGljRXZlbnRzU2VydmljZSk7XG5cbiAgZ2V0QW5kUGVyc2lzdFVzZXJEYXRhSW5TdG9yZShcbiAgICBjdXJyZW50Q29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvbixcbiAgICBhbGxDb25maWdzOiBPcGVuSWRDb25maWd1cmF0aW9uW10sXG4gICAgaXNSZW5ld1Byb2Nlc3MgPSBmYWxzZSxcbiAgICBpZFRva2VuPzogc3RyaW5nLFxuICAgIGRlY29kZWRJZFRva2VuPzogYW55XG4gICk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgaWRUb2tlbiA9XG4gICAgICBpZFRva2VuIHx8XG4gICAgICB0aGlzLnN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UuZ2V0SWRUb2tlbihjdXJyZW50Q29uZmlndXJhdGlvbik7XG4gICAgZGVjb2RlZElkVG9rZW4gPVxuICAgICAgZGVjb2RlZElkVG9rZW4gfHxcbiAgICAgIHRoaXMudG9rZW5IZWxwZXJTZXJ2aWNlLmdldFBheWxvYWRGcm9tVG9rZW4oXG4gICAgICAgIGlkVG9rZW4sXG4gICAgICAgIGZhbHNlLFxuICAgICAgICBjdXJyZW50Q29uZmlndXJhdGlvblxuICAgICAgKTtcblxuICAgIGNvbnN0IGV4aXN0aW5nVXNlckRhdGFGcm9tU3RvcmFnZSA9XG4gICAgICB0aGlzLmdldFVzZXJEYXRhRnJvbVN0b3JlKGN1cnJlbnRDb25maWd1cmF0aW9uKTtcbiAgICBjb25zdCBoYXZlVXNlckRhdGEgPSAhIWV4aXN0aW5nVXNlckRhdGFGcm9tU3RvcmFnZTtcbiAgICBjb25zdCBpc0N1cnJlbnRGbG93SW1wbGljaXRGbG93V2l0aEFjY2Vzc1Rva2VuID1cbiAgICAgIHRoaXMuZmxvd0hlbHBlci5pc0N1cnJlbnRGbG93SW1wbGljaXRGbG93V2l0aEFjY2Vzc1Rva2VuKFxuICAgICAgICBjdXJyZW50Q29uZmlndXJhdGlvblxuICAgICAgKTtcbiAgICBjb25zdCBpc0N1cnJlbnRGbG93Q29kZUZsb3cgPVxuICAgICAgdGhpcy5mbG93SGVscGVyLmlzQ3VycmVudEZsb3dDb2RlRmxvdyhjdXJyZW50Q29uZmlndXJhdGlvbik7XG5cbiAgICBjb25zdCBhY2Nlc3NUb2tlbiA9XG4gICAgICB0aGlzLnN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UuZ2V0QWNjZXNzVG9rZW4oY3VycmVudENvbmZpZ3VyYXRpb24pO1xuXG4gICAgaWYgKCEoaXNDdXJyZW50Rmxvd0ltcGxpY2l0Rmxvd1dpdGhBY2Nlc3NUb2tlbiB8fCBpc0N1cnJlbnRGbG93Q29kZUZsb3cpKSB7XG4gICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoXG4gICAgICAgIGN1cnJlbnRDb25maWd1cmF0aW9uLFxuICAgICAgICBgYXV0aENhbGxiYWNrIGlkVG9rZW4gZmxvdyB3aXRoIGFjY2Vzc1Rva2VuICR7YWNjZXNzVG9rZW59YFxuICAgICAgKTtcblxuICAgICAgdGhpcy5zZXRVc2VyRGF0YVRvU3RvcmUoZGVjb2RlZElkVG9rZW4sIGN1cnJlbnRDb25maWd1cmF0aW9uLCBhbGxDb25maWdzKTtcblxuICAgICAgcmV0dXJuIG9mKGRlY29kZWRJZFRva2VuKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IHJlbmV3VXNlckluZm9BZnRlclRva2VuUmVuZXcgfSA9IGN1cnJlbnRDb25maWd1cmF0aW9uO1xuXG4gICAgaWYgKCFpc1JlbmV3UHJvY2VzcyB8fCByZW5ld1VzZXJJbmZvQWZ0ZXJUb2tlblJlbmV3IHx8ICFoYXZlVXNlckRhdGEpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldFVzZXJEYXRhT2lkY0Zsb3dBbmRTYXZlKFxuICAgICAgICBkZWNvZGVkSWRUb2tlbi5zdWIsXG4gICAgICAgIGN1cnJlbnRDb25maWd1cmF0aW9uLFxuICAgICAgICBhbGxDb25maWdzXG4gICAgICApLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgodXNlckRhdGEpID0+IHtcbiAgICAgICAgICB0aGlzLmxvZ2dlclNlcnZpY2UubG9nRGVidWcoXG4gICAgICAgICAgICBjdXJyZW50Q29uZmlndXJhdGlvbixcbiAgICAgICAgICAgICdSZWNlaXZlZCB1c2VyIGRhdGE6ICcsXG4gICAgICAgICAgICB1c2VyRGF0YVxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKCEhdXNlckRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dEZWJ1ZyhcbiAgICAgICAgICAgICAgY3VycmVudENvbmZpZ3VyYXRpb24sXG4gICAgICAgICAgICAgICdhY2Nlc3NUb2tlbjogJyxcbiAgICAgICAgICAgICAgYWNjZXNzVG9rZW5cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIHJldHVybiBvZih1c2VyRGF0YSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKFxuICAgICAgICAgICAgICAoKSA9PiBuZXcgRXJyb3IoJ1JlY2VpdmVkIG5vIHVzZXIgZGF0YSwgcmVxdWVzdCBmYWlsZWQnKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBvZihleGlzdGluZ1VzZXJEYXRhRnJvbVN0b3JhZ2UpO1xuICB9XG5cbiAgZ2V0VXNlckRhdGFGcm9tU3RvcmUoY3VycmVudENvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb24gfCBudWxsKTogYW55IHtcbiAgICBpZiAoIWN1cnJlbnRDb25maWd1cmF0aW9uKSB7XG4gICAgICByZXR1cm4gdGhyb3dFcnJvcihcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnUGxlYXNlIHByb3ZpZGUgYSBjb25maWd1cmF0aW9uIGJlZm9yZSBzZXR0aW5nIHVwIHRoZSBtb2R1bGUnXG4gICAgICAgICAgKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLnJlYWQoJ3VzZXJEYXRhJywgY3VycmVudENvbmZpZ3VyYXRpb24pIHx8XG4gICAgICBudWxsXG4gICAgKTtcbiAgfVxuXG4gIHB1Ymxpc2hVc2VyRGF0YUlmRXhpc3RzKFxuICAgIGN1cnJlbnRDb25maWd1cmF0aW9uOiBPcGVuSWRDb25maWd1cmF0aW9uLFxuICAgIGFsbENvbmZpZ3M6IE9wZW5JZENvbmZpZ3VyYXRpb25bXVxuICApOiB2b2lkIHtcbiAgICBjb25zdCB1c2VyRGF0YSA9IHRoaXMuZ2V0VXNlckRhdGFGcm9tU3RvcmUoY3VycmVudENvbmZpZ3VyYXRpb24pO1xuXG4gICAgaWYgKHVzZXJEYXRhKSB7XG4gICAgICB0aGlzLmZpcmVVc2VyRGF0YUV2ZW50KGN1cnJlbnRDb25maWd1cmF0aW9uLCBhbGxDb25maWdzLCB1c2VyRGF0YSk7XG4gICAgfVxuICB9XG5cbiAgc2V0VXNlckRhdGFUb1N0b3JlKFxuICAgIHVzZXJEYXRhOiBhbnksXG4gICAgY3VycmVudENvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb24sXG4gICAgYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS53cml0ZShcbiAgICAgICd1c2VyRGF0YScsXG4gICAgICB1c2VyRGF0YSxcbiAgICAgIGN1cnJlbnRDb25maWd1cmF0aW9uXG4gICAgKTtcbiAgICB0aGlzLmZpcmVVc2VyRGF0YUV2ZW50KGN1cnJlbnRDb25maWd1cmF0aW9uLCBhbGxDb25maWdzLCB1c2VyRGF0YSk7XG4gIH1cblxuICByZXNldFVzZXJEYXRhSW5TdG9yZShcbiAgICBjdXJyZW50Q29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvbixcbiAgICBhbGxDb25maWdzOiBPcGVuSWRDb25maWd1cmF0aW9uW11cbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLnJlbW92ZSgndXNlckRhdGEnLCBjdXJyZW50Q29uZmlndXJhdGlvbik7XG4gICAgdGhpcy5maXJlVXNlckRhdGFFdmVudChjdXJyZW50Q29uZmlndXJhdGlvbiwgYWxsQ29uZmlncywgbnVsbCk7XG4gIH1cblxuICBwcml2YXRlIGdldFVzZXJEYXRhT2lkY0Zsb3dBbmRTYXZlKFxuICAgIGlkVG9rZW5TdWI6IGFueSxcbiAgICBjdXJyZW50Q29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvbixcbiAgICBhbGxDb25maWdzOiBPcGVuSWRDb25maWd1cmF0aW9uW11cbiAgKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRJZGVudGl0eVVzZXJEYXRhKGN1cnJlbnRDb25maWd1cmF0aW9uKS5waXBlKFxuICAgICAgbWFwKChkYXRhOiBhbnkpID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMudmFsaWRhdGVVc2VyRGF0YVN1YklkVG9rZW4oXG4gICAgICAgICAgICBjdXJyZW50Q29uZmlndXJhdGlvbixcbiAgICAgICAgICAgIGlkVG9rZW5TdWIsXG4gICAgICAgICAgICBkYXRhPy5zdWJcbiAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMuc2V0VXNlckRhdGFUb1N0b3JlKGRhdGEsIGN1cnJlbnRDb25maWd1cmF0aW9uLCBhbGxDb25maWdzKTtcblxuICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nLCB1c2VyIGRhdGEgc3ViIGRvZXMgbm90IG1hdGNoIHRoYXQgZnJvbSBpZF90b2tlblxuICAgICAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dXYXJuaW5nKFxuICAgICAgICAgICAgY3VycmVudENvbmZpZ3VyYXRpb24sXG4gICAgICAgICAgICBgVXNlciBkYXRhIHN1YiBkb2VzIG5vdCBtYXRjaCBzdWIgaW4gaWRfdG9rZW4sIHJlc2V0dGluZ2BcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMucmVzZXRVc2VyRGF0YUluU3RvcmUoY3VycmVudENvbmZpZ3VyYXRpb24sIGFsbENvbmZpZ3MpO1xuXG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0SWRlbnRpdHlVc2VyRGF0YShcbiAgICBjdXJyZW50Q29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvblxuICApOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIGNvbnN0IHRva2VuID1cbiAgICAgIHRoaXMuc3RvcmFnZVBlcnNpc3RlbmNlU2VydmljZS5nZXRBY2Nlc3NUb2tlbihjdXJyZW50Q29uZmlndXJhdGlvbik7XG5cbiAgICBjb25zdCBhdXRoV2VsbEtub3duRW5kUG9pbnRzID0gdGhpcy5zdG9yYWdlUGVyc2lzdGVuY2VTZXJ2aWNlLnJlYWQoXG4gICAgICAnYXV0aFdlbGxLbm93bkVuZFBvaW50cycsXG4gICAgICBjdXJyZW50Q29uZmlndXJhdGlvblxuICAgICk7XG5cbiAgICBpZiAoIWF1dGhXZWxsS25vd25FbmRQb2ludHMpIHtcbiAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dXYXJuaW5nKFxuICAgICAgICBjdXJyZW50Q29uZmlndXJhdGlvbixcbiAgICAgICAgJ2luaXQgY2hlY2sgc2Vzc2lvbjogYXV0aFdlbGxLbm93bkVuZHBvaW50cyBpcyB1bmRlZmluZWQnXG4gICAgICApO1xuXG4gICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBuZXcgRXJyb3IoJ2F1dGhXZWxsS25vd25FbmRwb2ludHMgaXMgdW5kZWZpbmVkJykpO1xuICAgIH1cblxuICAgIGNvbnN0IHVzZXJJbmZvRW5kcG9pbnQgPSBhdXRoV2VsbEtub3duRW5kUG9pbnRzLnVzZXJJbmZvRW5kcG9pbnQ7XG5cbiAgICBpZiAoIXVzZXJJbmZvRW5kcG9pbnQpIHtcbiAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dFcnJvcihcbiAgICAgICAgY3VycmVudENvbmZpZ3VyYXRpb24sXG4gICAgICAgICdpbml0IGNoZWNrIHNlc3Npb246IGF1dGhXZWxsS25vd25FbmRwb2ludHMudXNlcmluZm9fZW5kcG9pbnQgaXMgdW5kZWZpbmVkOyBzZXQgYXV0b191c2VyaW5mbyA9IGZhbHNlIGluIGNvbmZpZydcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKFxuICAgICAgICAoKSA9PiBuZXcgRXJyb3IoJ2F1dGhXZWxsS25vd25FbmRwb2ludHMudXNlcmluZm9fZW5kcG9pbnQgaXMgdW5kZWZpbmVkJylcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMub2lkY0RhdGFTZXJ2aWNlXG4gICAgICAuZ2V0KHVzZXJJbmZvRW5kcG9pbnQsIGN1cnJlbnRDb25maWd1cmF0aW9uLCB0b2tlbilcbiAgICAgIC5waXBlKHJldHJ5KDIpKTtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVVc2VyRGF0YVN1YklkVG9rZW4oXG4gICAgY3VycmVudENvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb24sXG4gICAgaWRUb2tlblN1YjogYW55LFxuICAgIHVzZXJEYXRhU3ViOiBhbnlcbiAgKTogYm9vbGVhbiB7XG4gICAgaWYgKCFpZFRva2VuU3ViKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKCF1c2VyRGF0YVN1Yikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChpZFRva2VuU3ViLnRvU3RyaW5nKCkgIT09IHVzZXJEYXRhU3ViLnRvU3RyaW5nKCkpIHtcbiAgICAgIHRoaXMubG9nZ2VyU2VydmljZS5sb2dEZWJ1ZyhcbiAgICAgICAgY3VycmVudENvbmZpZ3VyYXRpb24sXG4gICAgICAgICd2YWxpZGF0ZVVzZXJEYXRhU3ViSWRUb2tlbiBmYWlsZWQnLFxuICAgICAgICBpZFRva2VuU3ViLFxuICAgICAgICB1c2VyRGF0YVN1YlxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBmaXJlVXNlckRhdGFFdmVudChcbiAgICBjdXJyZW50Q29uZmlndXJhdGlvbjogT3BlbklkQ29uZmlndXJhdGlvbixcbiAgICBhbGxDb25maWdzOiBPcGVuSWRDb25maWd1cmF0aW9uW10sXG4gICAgcGFzc2VkVXNlckRhdGE6IGFueVxuICApOiB2b2lkIHtcbiAgICBjb25zdCB1c2VyRGF0YSA9IHRoaXMuY29tcG9zZVNpbmdsZU9yTXVsdGlwbGVVc2VyRGF0YU9iamVjdChcbiAgICAgIGN1cnJlbnRDb25maWd1cmF0aW9uLFxuICAgICAgYWxsQ29uZmlncyxcbiAgICAgIHBhc3NlZFVzZXJEYXRhXG4gICAgKTtcblxuICAgIHRoaXMudXNlckRhdGFJbnRlcm5hbCQubmV4dCh1c2VyRGF0YSk7XG5cbiAgICBjb25zdCB7IGNvbmZpZ0lkIH0gPSBjdXJyZW50Q29uZmlndXJhdGlvbjtcblxuICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmZpcmVFdmVudChFdmVudFR5cGVzLlVzZXJEYXRhQ2hhbmdlZCwge1xuICAgICAgY29uZmlnSWQsXG4gICAgICB1c2VyRGF0YTogcGFzc2VkVXNlckRhdGEsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGNvbXBvc2VTaW5nbGVPck11bHRpcGxlVXNlckRhdGFPYmplY3QoXG4gICAgY3VycmVudENvbmZpZ3VyYXRpb246IE9wZW5JZENvbmZpZ3VyYXRpb24sXG4gICAgYWxsQ29uZmlnczogT3BlbklkQ29uZmlndXJhdGlvbltdLFxuICAgIHBhc3NlZFVzZXJEYXRhOiBhbnlcbiAgKTogVXNlckRhdGFSZXN1bHQge1xuICAgIGNvbnN0IGhhc01hbnlDb25maWdzID0gYWxsQ29uZmlncy5sZW5ndGggPiAxO1xuXG4gICAgaWYgKCFoYXNNYW55Q29uZmlncykge1xuICAgICAgY29uc3QgeyBjb25maWdJZCB9ID0gY3VycmVudENvbmZpZ3VyYXRpb247XG5cbiAgICAgIHJldHVybiB0aGlzLmNvbXBvc2VTaW5nbGVVc2VyRGF0YVJlc3VsdChjb25maWdJZCA/PyAnJywgcGFzc2VkVXNlckRhdGEpO1xuICAgIH1cblxuICAgIGNvbnN0IGFsbFVzZXJEYXRhOiBDb25maWdVc2VyRGF0YVJlc3VsdFtdID0gYWxsQ29uZmlncy5tYXAoKGNvbmZpZykgPT4ge1xuICAgICAgY29uc3QgY3VycmVudENvbmZpZ0lkID0gY3VycmVudENvbmZpZ3VyYXRpb24uY29uZmlnSWQgPz8gJyc7XG4gICAgICBjb25zdCBjb25maWdJZCA9IGNvbmZpZy5jb25maWdJZCA/PyAnJztcblxuICAgICAgaWYgKHRoaXMuY3VycmVudENvbmZpZ0lzVG9VcGRhdGUoY3VycmVudENvbmZpZ0lkLCBjb25maWcpKSB7XG4gICAgICAgIHJldHVybiB7IGNvbmZpZ0lkLCB1c2VyRGF0YTogcGFzc2VkVXNlckRhdGEgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYWxyZWFkeVNhdmVkVXNlckRhdGEgPVxuICAgICAgICB0aGlzLnN0b3JhZ2VQZXJzaXN0ZW5jZVNlcnZpY2UucmVhZCgndXNlckRhdGEnLCBjb25maWcpIHx8IG51bGw7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbmZpZ0lkLFxuICAgICAgICB1c2VyRGF0YTogYWxyZWFkeVNhdmVkVXNlckRhdGEsXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZXJEYXRhOiBudWxsLFxuICAgICAgYWxsVXNlckRhdGEsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgY29tcG9zZVNpbmdsZVVzZXJEYXRhUmVzdWx0KFxuICAgIGNvbmZpZ0lkOiBzdHJpbmcsXG4gICAgdXNlckRhdGE6IGFueVxuICApOiBVc2VyRGF0YVJlc3VsdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHVzZXJEYXRhLFxuICAgICAgYWxsVXNlckRhdGE6IFt7IGNvbmZpZ0lkLCB1c2VyRGF0YSB9XSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBjdXJyZW50Q29uZmlnSXNUb1VwZGF0ZShcbiAgICBjb25maWdJZDogc3RyaW5nLFxuICAgIGNvbmZpZzogT3BlbklkQ29uZmlndXJhdGlvblxuICApOiBib29sZWFuIHtcbiAgICByZXR1cm4gY29uZmlnLmNvbmZpZ0lkID09PSBjb25maWdJZDtcbiAgfVxufVxuIl19