@nebular/auth
Version:
@nebular/auth
338 lines • 48.3 kB
JavaScript
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
import { Inject, Injectable } from '@angular/core';
import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { of as observableOf } from 'rxjs';
import { switchMap, map, catchError } from 'rxjs/operators';
import { NB_WINDOW } from '@nebular/theme';
import { NbAuthStrategy } from '../auth-strategy';
import { NbAuthIllegalTokenError } from '../../services/token/token';
import { NbAuthResult } from '../../services/auth-result';
import { NbOAuth2ResponseType, auth2StrategyOptions, NbOAuth2GrantType, NbOAuth2ClientAuthMethod, } from './oauth2-strategy.options';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common/http";
import * as i2 from "@angular/router";
/**
* OAuth2 authentication strategy.
*
* Strategy settings:
*
* ```ts
* export enum NbOAuth2ResponseType {
* CODE = 'code',
* TOKEN = 'token',
* }
*
* export enum NbOAuth2GrantType {
* AUTHORIZATION_CODE = 'authorization_code',
* PASSWORD = 'password',
* REFRESH_TOKEN = 'refresh_token',
* }
*
* export class NbOAuth2AuthStrategyOptions {
* name: string;
* baseEndpoint?: string = '';
* clientId: string = '';
* clientSecret: string = '';
* clientAuthMethod: string = NbOAuth2ClientAuthMethod.NONE;
* redirect?: { success?: string; failure?: string } = {
* success: '/',
* failure: null,
* };
* defaultErrors?: any[] = ['Something went wrong, please try again.'];
* defaultMessages?: any[] = ['You have been successfully authenticated.'];
* authorize?: {
* endpoint?: string;
* redirectUri?: string;
* responseType?: string;
* requireValidToken: true,
* scope?: string;
* state?: string;
* params?: { [key: string]: string };
* } = {
* endpoint: 'authorize',
* responseType: NbOAuth2ResponseType.CODE,
* };
* token?: {
* endpoint?: string;
* grantType?: string;
* requireValidToken: true,
* redirectUri?: string;
* scope?: string;
* class: NbAuthTokenClass,
* } = {
* endpoint: 'token',
* grantType: NbOAuth2GrantType.AUTHORIZATION_CODE,
* class: NbAuthOAuth2Token,
* };
* refresh?: {
* endpoint?: string;
* grantType?: string;
* scope?: string;
* requireValidToken: true,
* } = {
* endpoint: 'token',
* grantType: NbOAuth2GrantType.REFRESH_TOKEN,
* };
* }
* ```
*
*/
export class NbOAuth2AuthStrategy extends NbAuthStrategy {
constructor(http, route, window) {
super();
this.http = http;
this.route = route;
this.window = window;
this.redirectResultHandlers = {
[NbOAuth2ResponseType.CODE]: () => {
return observableOf(this.route.snapshot.queryParams).pipe(switchMap((params) => {
if (params.code) {
return this.requestToken(params.code);
}
return observableOf(new NbAuthResult(false, params, this.getOption('redirect.failure'), this.getOption('defaultErrors'), []));
}));
},
[NbOAuth2ResponseType.TOKEN]: () => {
const module = 'authorize';
const requireValidToken = this.getOption(`${module}.requireValidToken`);
return observableOf(this.route.snapshot.fragment).pipe(map((fragment) => this.parseHashAsQueryParams(fragment)), map((params) => {
if (!params.error) {
return new NbAuthResult(true, params, this.getOption('redirect.success'), [], this.getOption('defaultMessages'), this.createToken(params, requireValidToken));
}
return new NbAuthResult(false, params, this.getOption('redirect.failure'), this.getOption('defaultErrors'), []);
}), catchError((err) => {
const errors = [];
if (err instanceof NbAuthIllegalTokenError) {
errors.push(err.message);
}
else {
errors.push('Something went wrong.');
}
return observableOf(new NbAuthResult(false, err, this.getOption('redirect.failure'), errors));
}));
},
};
this.redirectResults = {
[NbOAuth2ResponseType.CODE]: () => {
return observableOf(this.route.snapshot.queryParams).pipe(map((params) => !!(params && (params.code || params.error))));
},
[NbOAuth2ResponseType.TOKEN]: () => {
return observableOf(this.route.snapshot.fragment).pipe(map((fragment) => this.parseHashAsQueryParams(fragment)), map((params) => !!(params && (params.access_token || params.error))));
},
};
this.defaultOptions = auth2StrategyOptions;
}
static setup(options) {
return [NbOAuth2AuthStrategy, options];
}
get responseType() {
return this.getOption('authorize.responseType');
}
get clientAuthMethod() {
return this.getOption('clientAuthMethod');
}
authenticate(data) {
if (this.getOption('token.grantType') === NbOAuth2GrantType.PASSWORD) {
return this.passwordToken(data.email, data.password);
}
else {
return this.isRedirectResult().pipe(switchMap((result) => {
if (!result) {
this.authorizeRedirect();
return observableOf(new NbAuthResult(true));
}
return this.getAuthorizationResult();
}));
}
}
getAuthorizationResult() {
const redirectResultHandler = this.redirectResultHandlers[this.responseType];
if (redirectResultHandler) {
return redirectResultHandler.call(this);
}
throw new Error(`'${this.responseType}' responseType is not supported,
only 'token' and 'code' are supported now`);
}
refreshToken(token) {
const module = 'refresh';
const url = this.getActionEndpoint(module);
const requireValidToken = this.getOption(`${module}.requireValidToken`);
return this.http.post(url, this.buildRefreshRequestData(token), { headers: this.getHeaders() }).pipe(map((res) => {
return new NbAuthResult(true, res, this.getOption('redirect.success'), [], this.getOption('defaultMessages'), this.createRefreshedToken(res, token, requireValidToken));
}), catchError((res) => this.handleResponseError(res)));
}
passwordToken(username, password) {
const module = 'token';
const url = this.getActionEndpoint(module);
const requireValidToken = this.getOption(`${module}.requireValidToken`);
return this.http.post(url, this.buildPasswordRequestData(username, password), { headers: this.getHeaders() }).pipe(map((res) => {
return new NbAuthResult(true, res, this.getOption('redirect.success'), [], this.getOption('defaultMessages'), this.createToken(res, requireValidToken));
}), catchError((res) => this.handleResponseError(res)));
}
authorizeRedirect() {
this.window.location.href = this.buildRedirectUrl();
}
isRedirectResult() {
return this.redirectResults[this.responseType].call(this);
}
requestToken(code) {
const module = 'token';
const url = this.getActionEndpoint(module);
const requireValidToken = this.getOption(`${module}.requireValidToken`);
return this.http.post(url, this.buildCodeRequestData(code), { headers: this.getHeaders() }).pipe(map((res) => {
return new NbAuthResult(true, res, this.getOption('redirect.success'), [], this.getOption('defaultMessages'), this.createToken(res, requireValidToken));
}), catchError((res) => this.handleResponseError(res)));
}
buildCodeRequestData(code) {
const params = {
grant_type: this.getOption('token.grantType'),
code: code,
redirect_uri: this.getOption('token.redirectUri'),
client_id: this.getOption('clientId'),
};
return this.urlEncodeParameters(this.cleanParams(this.addCredentialsToParams(params)));
}
buildRefreshRequestData(token) {
const params = {
grant_type: this.getOption('refresh.grantType'),
refresh_token: token.getRefreshToken(),
scope: this.getOption('refresh.scope'),
client_id: this.getOption('clientId'),
};
return this.urlEncodeParameters(this.cleanParams(this.addCredentialsToParams(params)));
}
buildPasswordRequestData(username, password) {
const params = {
grant_type: this.getOption('token.grantType'),
username: username,
password: password,
scope: this.getOption('token.scope'),
};
return this.urlEncodeParameters(this.cleanParams(this.addCredentialsToParams(params)));
}
buildAuthHeader() {
if (this.clientAuthMethod === NbOAuth2ClientAuthMethod.BASIC) {
if (this.getOption('clientId') && this.getOption('clientSecret')) {
return new HttpHeaders({
Authorization: 'Basic ' + btoa(this.getOption('clientId') + ':' + this.getOption('clientSecret')),
});
}
else {
throw Error('For basic client authentication method, please provide both clientId & clientSecret.');
}
}
return undefined;
}
getHeaders() {
let headers = super.getHeaders();
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
const authHeaders = this.buildAuthHeader();
if (authHeaders === undefined) {
return headers;
}
for (const headerKey of authHeaders.keys()) {
for (const headerValue of authHeaders.getAll(headerKey)) {
headers = headers.append(headerKey, headerValue);
}
}
return headers;
}
cleanParams(params) {
Object.entries(params).forEach(([key, val]) => !val && delete params[key]);
return params;
}
addCredentialsToParams(params) {
if (this.clientAuthMethod === NbOAuth2ClientAuthMethod.REQUEST_BODY) {
if (this.getOption('clientId') && this.getOption('clientSecret')) {
return {
...params,
client_id: this.getOption('clientId'),
client_secret: this.getOption('clientSecret'),
};
}
else {
throw Error('For request body client authentication method, please provide both clientId & clientSecret.');
}
}
return params;
}
handleResponseError(res) {
let errors = [];
if (res instanceof HttpErrorResponse) {
if (res.error.error_description) {
errors.push(res.error.error_description);
}
else {
errors = this.getOption('defaultErrors');
}
}
else if (res instanceof NbAuthIllegalTokenError) {
errors.push(res.message);
}
else {
errors.push('Something went wrong.');
}
return observableOf(new NbAuthResult(false, res, this.getOption('redirect.failure'), errors, []));
}
buildRedirectUrl() {
const params = {
response_type: this.getOption('authorize.responseType'),
client_id: this.getOption('clientId'),
redirect_uri: this.getOption('authorize.redirectUri'),
scope: this.getOption('authorize.scope'),
state: this.getOption('authorize.state'),
...this.getOption('authorize.params'),
};
const endpoint = this.getActionEndpoint('authorize');
const query = this.urlEncodeParameters(this.cleanParams(params));
return `${endpoint}?${query}`;
}
parseHashAsQueryParams(hash) {
return hash
? hash.split('&').reduce((acc, part) => {
const item = part.split('=');
acc[item[0]] = decodeURIComponent(item[1]);
return acc;
}, {})
: {};
}
urlEncodeParameters(params) {
return Object.keys(params)
.map((k) => {
return `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`;
})
.join('&');
}
createRefreshedToken(res, existingToken, requireValidToken) {
const refreshedToken = this.createToken(res, requireValidToken);
if (!refreshedToken.getRefreshToken() && existingToken.getRefreshToken()) {
refreshedToken.setRefreshToken(existingToken.getRefreshToken());
}
return refreshedToken;
}
register(data) {
throw new Error('`register` is not supported by `NbOAuth2AuthStrategy`, use `authenticate`.');
}
requestPassword(data) {
throw new Error('`requestPassword` is not supported by `NbOAuth2AuthStrategy`, use `authenticate`.');
}
resetPassword(data = {}) {
throw new Error('`resetPassword` is not supported by `NbOAuth2AuthStrategy`, use `authenticate`.');
}
logout() {
return observableOf(new NbAuthResult(true));
}
}
NbOAuth2AuthStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: NbOAuth2AuthStrategy, deps: [{ token: i1.HttpClient }, { token: i2.ActivatedRoute }, { token: NB_WINDOW }], target: i0.ɵɵFactoryTarget.Injectable });
NbOAuth2AuthStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: NbOAuth2AuthStrategy });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: NbOAuth2AuthStrategy, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: i2.ActivatedRoute }, { type: undefined, decorators: [{
type: Inject,
args: [NB_WINDOW]
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2F1dGgyLXN0cmF0ZWd5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2ZyYW1ld29yay9hdXRoL3N0cmF0ZWdpZXMvb2F1dGgyL29hdXRoMi1zdHJhdGVneS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFjLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRWxGLE9BQU8sRUFBYyxFQUFFLElBQUksWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RELE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbEQsT0FBTyxFQUFFLHVCQUF1QixFQUF1QyxNQUFNLDRCQUE0QixDQUFDO0FBQzFHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRCxPQUFPLEVBRUwsb0JBQW9CLEVBQ3BCLG9CQUFvQixFQUNwQixpQkFBaUIsRUFDakIsd0JBQXdCLEdBQ3pCLE1BQU0sMkJBQTJCLENBQUM7Ozs7QUFHbkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUVHO0FBRUgsTUFBTSxPQUFPLG9CQUFxQixTQUFRLGNBQWM7SUFnRnRELFlBQXNCLElBQWdCLEVBQVksS0FBcUIsRUFBK0IsTUFBVztRQUMvRyxLQUFLLEVBQUUsQ0FBQztRQURZLFNBQUksR0FBSixJQUFJLENBQVk7UUFBWSxVQUFLLEdBQUwsS0FBSyxDQUFnQjtRQUErQixXQUFNLEdBQU4sTUFB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LENBQUM7SUFFRCxNQUFNO1FBQ0osT0FBTyxZQUFZLENBQUMsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUM5QyxDQUFDOztpSEEvVVUsb0JBQW9CLDBFQWdGa0QsU0FBUztxSEFoRi9FLG9CQUFvQjsyRkFBcEIsb0JBQW9CO2tCQURoQyxVQUFVOzswQkFpRmlFLE1BQU07MkJBQUMsU0FBUyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBBa3Zlby4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi9cbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSHR0cENsaWVudCwgSHR0cEVycm9yUmVzcG9uc2UsIEh0dHBIZWFkZXJzIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgb2YgYXMgb2JzZXJ2YWJsZU9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzd2l0Y2hNYXAsIG1hcCwgY2F0Y2hFcnJvciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE5CX1dJTkRPVyB9IGZyb20gJ0BuZWJ1bGFyL3RoZW1lJztcblxuaW1wb3J0IHsgTmJBdXRoU3RyYXRlZ3kgfSBmcm9tICcuLi9hdXRoLXN0cmF0ZWd5JztcbmltcG9ydCB7IE5iQXV0aElsbGVnYWxUb2tlbkVycm9yLCBOYkF1dGhSZWZyZXNoYWJsZVRva2VuLCBOYkF1dGhUb2tlbiB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3Rva2VuL3Rva2VuJztcbmltcG9ydCB7IE5iQXV0aFJlc3VsdCB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2F1dGgtcmVzdWx0JztcbmltcG9ydCB7XG4gIE5iT0F1dGgyQXV0aFN0cmF0ZWd5T3B0aW9ucyxcbiAgTmJPQXV0aDJSZXNwb25zZVR5cGUsXG4gIGF1dGgyU3RyYXRlZ3lPcHRpb25zLFxuICBOYk9BdXRoMkdyYW50VHlwZSxcbiAgTmJPQXV0aDJDbGllbnRBdXRoTWV0aG9kLFxufSBmcm9tICcuL29hdXRoMi1zdHJhdGVneS5vcHRpb25zJztcbmltcG9ydCB7IE5iQXV0aFN0cmF0ZWd5Q2xhc3MgfSBmcm9tICcuLi8uLi9hdXRoLm9wdGlvbnMnO1xuXG4vKipcbiAqIE9BdXRoMiBhdXRoZW50aWNhdGlvbiBzdHJhdGVneS5cbiAqXG4gKiBTdHJhdGVneSBzZXR0aW5nczpcbiAqXG4gKiBgYGB0c1xuICogZXhwb3J0IGVudW0gTmJPQXV0aDJSZXNwb25zZVR5cGUge1xuICogICBDT0RFID0gJ2NvZGUnLFxuICogICBUT0tFTiA9ICd0b2tlbicsXG4gKiB9XG4gKlxuICogZXhwb3J0IGVudW0gTmJPQXV0aDJHcmFudFR5cGUge1xuICogICBBVVRIT1JJWkFUSU9OX0NPREUgPSAnYXV0aG9yaXphdGlvbl9jb2RlJyxcbiAqICAgUEFTU1dPUkQgPSAncGFzc3dvcmQnLFxuICogICBSRUZSRVNIX1RPS0VOID0gJ3JlZnJlc2hfdG9rZW4nLFxuICogfVxuICpcbiAqIGV4cG9ydCBjbGFzcyBOYk9BdXRoMkF1dGhTdHJhdGVneU9wdGlvbnMge1xuICogICBuYW1lOiBzdHJpbmc7XG4gKiAgIGJhc2VFbmRwb2ludD86IHN0cmluZyA9ICcnO1xuICogICBjbGllbnRJZDogc3RyaW5nID0gJyc7XG4gKiAgIGNsaWVudFNlY3JldDogc3RyaW5nID0gJyc7XG4gKiAgIGNsaWVudEF1dGhNZXRob2Q6IHN0cmluZyA9IE5iT0F1dGgyQ2xpZW50QXV0aE1ldGhvZC5OT05FO1xuICogICByZWRpcmVjdD86IHsgc3VjY2Vzcz86IHN0cmluZzsgZmFpbHVyZT86IHN0cmluZyB9ID0ge1xuICogICAgIHN1Y2Nlc3M6ICcvJyxcbiAqICAgICBmYWlsdXJlOiBudWxsLFxuICogICB9O1xuICogICBkZWZhdWx0RXJyb3JzPzogYW55W10gPSBbJ1NvbWV0aGluZyB3ZW50IHdyb25nLCBwbGVhc2UgdHJ5IGFnYWluLiddO1xuICogICBkZWZhdWx0TWVzc2FnZXM/OiBhbnlbXSA9IFsnWW91IGhhdmUgYmVlbiBzdWNjZXNzZnVsbHkgYXV0aGVudGljYXRlZC4nXTtcbiAqICAgYXV0aG9yaXplPzoge1xuICogICAgIGVuZHBvaW50Pzogc3RyaW5nO1xuICogICAgIHJlZGlyZWN0VXJpPzogc3RyaW5nO1xuICogICAgIHJlc3BvbnNlVHlwZT86IHN0cmluZztcbiAqICAgICByZXF1aXJlVmFsaWRUb2tlbjogdHJ1ZSxcbiAqICAgICBzY29wZT86IHN0cmluZztcbiAqICAgICBzdGF0ZT86IHN0cmluZztcbiAqICAgICBwYXJhbXM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICogICB9ID0ge1xuICogICAgIGVuZHBvaW50OiAnYXV0aG9yaXplJyxcbiAqICAgICByZXNwb25zZVR5cGU6IE5iT0F1dGgyUmVzcG9uc2VUeXBlLkNPREUsXG4gKiAgIH07XG4gKiAgIHRva2VuPzoge1xuICogICAgIGVuZHBvaW50Pzogc3RyaW5nO1xuICogICAgIGdyYW50VHlwZT86IHN0cmluZztcbiAqICAgICByZXF1aXJlVmFsaWRUb2tlbjogdHJ1ZSxcbiAqICAgICByZWRpcmVjdFVyaT86IHN0cmluZztcbiAqICAgICBzY29wZT86IHN0cmluZztcbiAqICAgICBjbGFzczogTmJBdXRoVG9rZW5DbGFzcyxcbiAqICAgfSA9IHtcbiAqICAgICBlbmRwb2ludDogJ3Rva2VuJyxcbiAqICAgICBncmFudFR5cGU6IE5iT0F1dGgyR3JhbnRUeXBlLkFVVEhPUklaQVRJT05fQ09ERSxcbiAqICAgICBjbGFzczogTmJBdXRoT0F1dGgyVG9rZW4sXG4gKiAgIH07XG4gKiAgIHJlZnJlc2g/OiB7XG4gKiAgICAgZW5kcG9pbnQ/OiBzdHJpbmc7XG4gKiAgICAgZ3JhbnRUeXBlPzogc3RyaW5nO1xuICogICAgIHNjb3BlPzogc3RyaW5nO1xuICogICAgIHJlcXVpcmVWYWxpZFRva2VuOiB0cnVlLFxuICogICB9ID0ge1xuICogICAgIGVuZHBvaW50OiAndG9rZW4nLFxuICogICAgIGdyYW50VHlwZTogTmJPQXV0aDJHcmFudFR5cGUuUkVGUkVTSF9UT0tFTixcbiAqICAgfTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5iT0F1dGgyQXV0aFN0cmF0ZWd5IGV4dGVuZHMgTmJBdXRoU3RyYXRlZ3kge1xuICBzdGF0aWMgc2V0dXAob3B0aW9uczogTmJPQXV0aDJBdXRoU3RyYXRlZ3lPcHRpb25zKTogW05iQXV0aFN0cmF0ZWd5Q2xhc3MsIE5iT0F1dGgyQXV0aFN0cmF0ZWd5T3B0aW9uc10ge1xuICAgIHJldHVybiBbTmJPQXV0aDJBdXRoU3RyYXRlZ3ksIG9wdGlvbnNdO1xuICB9XG5cbiAgZ2V0IHJlc3BvbnNlVHlwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRPcHRpb24oJ2F1dGhvcml6ZS5yZXNwb25zZVR5cGUnKTtcbiAgfVxuXG4gIGdldCBjbGllbnRBdXRoTWV0aG9kKCkge1xuICAgIHJldHVybiB0aGlzLmdldE9wdGlvbignY2xpZW50QXV0aE1ldGhvZCcpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJlZGlyZWN0UmVzdWx0SGFuZGxlcnM6IHsgW2tleTogc3RyaW5nXTogRnVuY3Rpb24gfSA9IHtcbiAgICBbTmJPQXV0aDJSZXNwb25zZVR5cGUuQ09ERV06ICgpID0+IHtcbiAgICAgIHJldHVybiBvYnNlcnZhYmxlT2YodGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcykucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKChwYXJhbXM6IGFueSkgPT4ge1xuICAgICAgICAgIGlmIChwYXJhbXMuY29kZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVxdWVzdFRva2VuKHBhcmFtcy5jb2RlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gb2JzZXJ2YWJsZU9mKFxuICAgICAgICAgICAgbmV3IE5iQXV0aFJlc3VsdChmYWxzZSwgcGFyYW1zLCB0aGlzLmdldE9wdGlvbigncmVkaXJlY3QuZmFpbHVyZScpLCB0aGlzLmdldE9wdGlvbignZGVmYXVsdEVycm9ycycpLCBbXSksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0sXG4gICAgW05iT0F1dGgyUmVzcG9uc2VUeXBlLlRPS0VOXTogKCkgPT4ge1xuICAgICAgY29uc3QgbW9kdWxlID0gJ2F1dGhvcml6ZSc7XG4gICAgICBjb25zdCByZXF1aXJlVmFsaWRUb2tlbiA9IHRoaXMuZ2V0T3B0aW9uKGAke21vZHVsZX0ucmVxdWlyZVZhbGlkVG9rZW5gKTtcbiAgICAgIHJldHVybiBvYnNlcnZhYmxlT2YodGhpcy5yb3V0ZS5zbmFwc2hvdC5mcmFnbWVudCkucGlwZShcbiAgICAgICAgbWFwKChmcmFnbWVudCkgPT4gdGhpcy5wYXJzZUhhc2hBc1F1ZXJ5UGFyYW1zKGZyYWdtZW50KSksXG4gICAgICAgIG1hcCgocGFyYW1zOiBhbnkpID0+IHtcbiAgICAgICAgICBpZiAoIXBhcmFtcy5lcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBOYkF1dGhSZXN1bHQoXG4gICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgIHBhcmFtcyxcbiAgICAgICAgICAgICAgdGhpcy5nZXRPcHRpb24oJ3JlZGlyZWN0LnN1Y2Nlc3MnKSxcbiAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgIHRoaXMuZ2V0T3B0aW9uKCdkZWZhdWx0TWVzc2FnZXMnKSxcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVUb2tlbihwYXJhbXMsIHJlcXVpcmVWYWxpZFRva2VuKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBuZXcgTmJBdXRoUmVzdWx0KFxuICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICBwYXJhbXMsXG4gICAgICAgICAgICB0aGlzLmdldE9wdGlvbigncmVkaXJlY3QuZmFpbHVyZScpLFxuICAgICAgICAgICAgdGhpcy5nZXRPcHRpb24oJ2RlZmF1bHRFcnJvcnMnKSxcbiAgICAgICAgICAgIFtdLFxuICAgICAgICAgICk7XG4gICAgICAgIH0pLFxuICAgICAgICBjYXRjaEVycm9yKChlcnIpID0+IHtcbiAgICAgICAgICBjb25zdCBlcnJvcnMgPSBbXTtcbiAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgTmJBdXRoSWxsZWdhbFRva2VuRXJyb3IpIHtcbiAgICAgICAgICAgIGVycm9ycy5wdXNoKGVyci5tZXNzYWdlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXJyb3JzLnB1c2goJ1NvbWV0aGluZyB3ZW50IHdyb25nLicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gb2JzZXJ2YWJsZU9mKG5ldyBOYkF1dGhSZXN1bHQoZmFsc2UsIGVyciwgdGhpcy5nZXRPcHRpb24oJ3JlZGlyZWN0LmZhaWx1cmUnKSwgZXJyb3JzKSk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9LFxuICB9O1xuXG4gIHByb3RlY3RlZCByZWRpcmVjdFJlc3VsdHM6IHsgW2tleTogc3RyaW5nXTogRnVuY3Rpb24gfSA9IHtcbiAgICBbTmJPQXV0aDJSZXNwb25zZVR5cGUuQ09ERV06ICgpID0+IHtcbiAgICAgIHJldHVybiBvYnNlcnZhYmxlT2YodGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcykucGlwZShcbiAgICAgICAgbWFwKChwYXJhbXM6IGFueSkgPT4gISEocGFyYW1zICYmIChwYXJhbXMuY29kZSB8fCBwYXJhbXMuZXJyb3IpKSksXG4gICAgICApO1xuICAgIH0sXG4gICAgW05iT0F1dGgyUmVzcG9uc2VUeXBlLlRPS0VOXTogKCkgPT4ge1xuICAgICAgcmV0dXJuIG9ic2VydmFibGVPZih0aGlzLnJvdXRlLnNuYXBzaG90LmZyYWdtZW50KS5waXBlKFxuICAgICAgICBtYXAoKGZyYWdtZW50KSA9PiB0aGlzLnBhcnNlSGFzaEFzUXVlcnlQYXJhbXMoZnJhZ21lbnQpKSxcbiAgICAgICAgbWFwKChwYXJhbXM6IGFueSkgPT4gISEocGFyYW1zICYmIChwYXJhbXMuYWNjZXNzX3Rva2VuIHx8IHBhcmFtcy5lcnJvcikpKSxcbiAgICAgICk7XG4gICAgfSxcbiAgfTtcblxuICBwcm90ZWN0ZWQgZGVmYXVsdE9wdGlvbnM6IE5iT0F1dGgyQXV0aFN0cmF0ZWd5T3B0aW9ucyA9IGF1dGgyU3RyYXRlZ3lPcHRpb25zO1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBodHRwOiBIdHRwQ2xpZW50LCBwcm90ZWN0ZWQgcm91dGU6IEFjdGl2YXRlZFJvdXRlLCBASW5qZWN0KE5CX1dJTkRPVykgcHJvdGVjdGVkIHdpbmRvdzogYW55KSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIGF1dGhlbnRpY2F0ZShkYXRhPzogYW55KTogT2JzZXJ2YWJsZTxOYkF1dGhSZXN1bHQ+IHtcbiAgICBpZiAodGhpcy5nZXRPcHRpb24oJ3Rva2VuLmdyYW50VHlwZScpID09PSBOYk9BdXRoMkdyYW50VHlwZS5QQVNTV09SRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGFzc3dvcmRUb2tlbihkYXRhLmVtYWlsLCBkYXRhLnBhc3N3b3JkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuaXNSZWRpcmVjdFJlc3VsdCgpLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgocmVzdWx0OiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgICAgICAgIHRoaXMuYXV0aG9yaXplUmVkaXJlY3QoKTtcbiAgICAgICAgICAgIHJldHVybiBvYnNlcnZhYmxlT2YobmV3IE5iQXV0aFJlc3VsdCh0cnVlKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0aGlzLmdldEF1dGhvcml6YXRpb25SZXN1bHQoKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGdldEF1dGhvcml6YXRpb25SZXN1bHQoKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBjb25zdCByZWRpcmVjdFJlc3VsdEhhbmRsZXIgPSB0aGlzLnJlZGlyZWN0UmVzdWx0SGFuZGxlcnNbdGhpcy5yZXNwb25zZVR5cGVdO1xuICAgIGlmIChyZWRpcmVjdFJlc3VsdEhhbmRsZXIpIHtcbiAgICAgIHJldHVybiByZWRpcmVjdFJlc3VsdEhhbmRsZXIuY2FsbCh0aGlzKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYCcke3RoaXMucmVzcG9uc2VUeXBlfScgcmVzcG9uc2VUeXBlIGlzIG5vdCBzdXBwb3J0ZWQsXG4gICAgICAgICAgICAgICAgICAgICAgb25seSAndG9rZW4nIGFuZCAnY29kZScgYXJlIHN1cHBvcnRlZCBub3dgKTtcbiAgfVxuXG4gIHJlZnJlc2hUb2tlbih0b2tlbjogTmJBdXRoUmVmcmVzaGFibGVUb2tlbik6IE9ic2VydmFibGU8TmJBdXRoUmVzdWx0PiB7XG4gICAgY29uc3QgbW9kdWxlID0gJ3JlZnJlc2gnO1xuICAgIGNvbnN0IHVybCA9IHRoaXMuZ2V0QWN0aW9uRW5kcG9pbnQobW9kdWxlKTtcbiAgICBjb25zdCByZXF1aXJlVmFsaWRUb2tlbiA9IHRoaXMuZ2V0T3B0aW9uKGAke21vZHVsZX0ucmVxdWlyZVZhbGlkVG9rZW5gKTtcblxuICAgIHJldHVybiB0aGlzLmh0dHAucG9zdCh1cmwsIHRoaXMuYnVpbGRSZWZyZXNoUmVxdWVzdERhdGEodG9rZW4pLCB7IGhlYWRlcnM6IHRoaXMuZ2V0SGVhZGVycygpIH0pLnBpcGUoXG4gICAgICBtYXAoKHJlcykgPT4ge1xuICAgICAgICByZXR1cm4gbmV3IE5iQXV0aFJlc3VsdChcbiAgICAgICAgICB0cnVlLFxuICAgICAgICAgIHJlcyxcbiAgICAgICAgICB0aGlzLmdldE9wdGlvbigncmVkaXJlY3Quc3VjY2VzcycpLFxuICAgICAgICAgIFtdLFxuICAgICAgICAgIHRoaXMuZ2V0T3B0aW9uKCdkZWZhdWx0TWVzc2FnZXMnKSxcbiAgICAgICAgICB0aGlzLmNyZWF0ZVJlZnJlc2hlZFRva2VuKHJlcywgdG9rZW4sIHJlcXVpcmVWYWxpZFRva2VuKSxcbiAgICAgICAgKTtcbiAgICAgIH0pLFxuICAgICAgY2F0Y2hFcnJvcigocmVzKSA9PiB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IocmVzKSksXG4gICAgKTtcbiAgfVxuXG4gIHBhc3N3b3JkVG9rZW4odXNlcm5hbWU6IHN0cmluZywgcGFzc3dvcmQ6IHN0cmluZyk6IE9ic2VydmFibGU8TmJBdXRoUmVzdWx0PiB7XG4gICAgY29uc3QgbW9kdWxlID0gJ3Rva2VuJztcbiAgICBjb25zdCB1cmwgPSB0aGlzLmdldEFjdGlvbkVuZHBvaW50KG1vZHVsZSk7XG4gICAgY29uc3QgcmVxdWlyZVZhbGlkVG9rZW4gPSB0aGlzLmdldE9wdGlvbihgJHttb2R1bGV9LnJlcXVpcmVWYWxpZFRva2VuYCk7XG5cbiAgICByZXR1cm4gdGhpcy5odHRwLnBvc3QodXJsLCB0aGlzLmJ1aWxkUGFzc3dvcmRSZXF1ZXN0RGF0YSh1c2VybmFtZSwgcGFzc3dvcmQpLCB7IGhlYWRlcnM6IHRoaXMuZ2V0SGVhZGVycygpIH0pLnBpcGUoXG4gICAgICBtYXAoKHJlcykgPT4ge1xuICAgICAgICByZXR1cm4gbmV3IE5iQXV0aFJlc3VsdChcbiAgICAgICAgICB0cnVlLFxuICAgICAgICAgIHJlcyxcbiAgICAgICAgICB0aGlzLmdldE9wdGlvbigncmVkaXJlY3Quc3VjY2VzcycpLFxuICAgICAgICAgIFtdLFxuICAgICAgICAgIHRoaXMuZ2V0T3B0aW9uKCdkZWZhdWx0TWVzc2FnZXMnKSxcbiAgICAgICAgICB0aGlzLmNyZWF0ZVRva2VuKHJlcywgcmVxdWlyZVZhbGlkVG9rZW4pLFxuICAgICAgICApO1xuICAgICAgfSksXG4gICAgICBjYXRjaEVycm9yKChyZXMpID0+IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihyZXMpKSxcbiAgICApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGF1dGhvcml6ZVJlZGlyZWN0KCkge1xuICAgIHRoaXMud2luZG93LmxvY2F0aW9uLmhyZWYgPSB0aGlzLmJ1aWxkUmVkaXJlY3RVcmwoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBpc1JlZGlyZWN0UmVzdWx0KCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLnJlZGlyZWN0UmVzdWx0c1t0aGlzLnJlc3BvbnNlVHlwZV0uY2FsbCh0aGlzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCByZXF1ZXN0VG9rZW4oY29kZTogc3RyaW5nKSB7XG4gICAgY29uc3QgbW9kdWxlID0gJ3Rva2VuJztcbiAgICBjb25zdCB1cmwgPSB0aGlzLmdldEFjdGlvbkVuZHBvaW50KG1vZHVsZSk7XG4gICAgY29uc3QgcmVxdWlyZVZhbGlkVG9rZW4gPSB0aGlzLmdldE9wdGlvbihgJHttb2R1bGV9LnJlcXVpcmVWYWxpZFRva2VuYCk7XG5cbiAgICByZXR1cm4gdGhpcy5odHRwLnBvc3QodXJsLCB0aGlzLmJ1aWxkQ29kZVJlcXVlc3REYXRhKGNvZGUpLCB7IGhlYWRlcnM6IHRoaXMuZ2V0SGVhZGVycygpIH0pLnBpcGUoXG4gICAgICBtYXAoKHJlcykgPT4ge1xuICAgICAgICByZXR1cm4gbmV3IE5iQXV0aFJlc3VsdChcbiAgICAgICAgICB0cnVlLFxuICAgICAgICAgIHJlcyxcbiAgICAgICAgICB0aGlzLmdldE9wdGlvbigncmVkaXJlY3Quc3VjY2VzcycpLFxuICAgICAgICAgIFtdLFxuICAgICAgICAgIHRoaXMuZ2V0T3B0aW9uKCdkZWZhdWx0TWVzc2FnZXMnKSxcbiAgICAgICAgICB0aGlzLmNyZWF0ZVRva2VuKHJlcywgcmVxdWlyZVZhbGlkVG9rZW4pLFxuICAgICAgICApO1xuICAgICAgfSksXG4gICAgICBjYXRjaEVycm9yKChyZXMpID0+IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihyZXMpKSxcbiAgICApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGJ1aWxkQ29kZVJlcXVlc3REYXRhKGNvZGU6IHN0cmluZyk6IGFueSB7XG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgZ3JhbnRfdHlwZTogdGhpcy5nZXRPcHRpb24oJ3Rva2VuLmdyYW50VHlwZScpLFxuICAgICAgY29kZTogY29kZSxcbiAgICAgIHJlZGlyZWN0X3VyaTogdGhpcy5nZXRPcHRpb24oJ3Rva2VuLnJlZGlyZWN0VXJpJyksXG4gICAgICBjbGllbnRfaWQ6IHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRJZCcpLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMudXJsRW5jb2RlUGFyYW1ldGVycyh0aGlzLmNsZWFuUGFyYW1zKHRoaXMuYWRkQ3JlZGVudGlhbHNUb1BhcmFtcyhwYXJhbXMpKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYnVpbGRSZWZyZXNoUmVxdWVzdERhdGEodG9rZW46IE5iQXV0aFJlZnJlc2hhYmxlVG9rZW4pOiBhbnkge1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgIGdyYW50X3R5cGU6IHRoaXMuZ2V0T3B0aW9uKCdyZWZyZXNoLmdyYW50VHlwZScpLFxuICAgICAgcmVmcmVzaF90b2tlbjogdG9rZW4uZ2V0UmVmcmVzaFRva2VuKCksXG4gICAgICBzY29wZTogdGhpcy5nZXRPcHRpb24oJ3JlZnJlc2guc2NvcGUnKSxcbiAgICAgIGNsaWVudF9pZDogdGhpcy5nZXRPcHRpb24oJ2NsaWVudElkJyksXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy51cmxFbmNvZGVQYXJhbWV0ZXJzKHRoaXMuY2xlYW5QYXJhbXModGhpcy5hZGRDcmVkZW50aWFsc1RvUGFyYW1zKHBhcmFtcykpKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBidWlsZFBhc3N3b3JkUmVxdWVzdERhdGEodXNlcm5hbWU6IHN0cmluZywgcGFzc3dvcmQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgZ3JhbnRfdHlwZTogdGhpcy5nZXRPcHRpb24oJ3Rva2VuLmdyYW50VHlwZScpLFxuICAgICAgdXNlcm5hbWU6IHVzZXJuYW1lLFxuICAgICAgcGFzc3dvcmQ6IHBhc3N3b3JkLFxuICAgICAgc2NvcGU6IHRoaXMuZ2V0T3B0aW9uKCd0b2tlbi5zY29wZScpLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMudXJsRW5jb2RlUGFyYW1ldGVycyh0aGlzLmNsZWFuUGFyYW1zKHRoaXMuYWRkQ3JlZGVudGlhbHNUb1BhcmFtcyhwYXJhbXMpKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYnVpbGRBdXRoSGVhZGVyKCk6IEh0dHBIZWFkZXJzIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodGhpcy5jbGllbnRBdXRoTWV0aG9kID09PSBOYk9BdXRoMkNsaWVudEF1dGhNZXRob2QuQkFTSUMpIHtcbiAgICAgIGlmICh0aGlzLmdldE9wdGlvbignY2xpZW50SWQnKSAmJiB0aGlzLmdldE9wdGlvbignY2xpZW50U2VjcmV0JykpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBIdHRwSGVhZGVycyh7XG4gICAgICAgICAgQXV0aG9yaXphdGlvbjogJ0Jhc2ljICcgKyBidG9hKHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRJZCcpICsgJzonICsgdGhpcy5nZXRPcHRpb24oJ2NsaWVudFNlY3JldCcpKSxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBFcnJvcignRm9yIGJhc2ljIGNsaWVudCBhdXRoZW50aWNhdGlvbiBtZXRob2QsIHBsZWFzZSBwcm92aWRlIGJvdGggY2xpZW50SWQgJiBjbGllbnRTZWNyZXQuJyk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0SGVhZGVycygpOiBIdHRwSGVhZGVycyB7XG4gICAgbGV0IGhlYWRlcnMgPSBzdXBlci5nZXRIZWFkZXJzKCk7XG4gICAgaGVhZGVycyA9IGhlYWRlcnMuYXBwZW5kKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyk7XG5cbiAgICBjb25zdCBhdXRoSGVhZGVycyA9IHRoaXMuYnVpbGRBdXRoSGVhZGVyKCk7XG4gICAgaWYgKGF1dGhIZWFkZXJzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBoZWFkZXJzO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgaGVhZGVyS2V5IG9mIGF1dGhIZWFkZXJzLmtleXMoKSkge1xuICAgICAgZm9yIChjb25zdCBoZWFkZXJWYWx1ZSBvZiBhdXRoSGVhZGVycy5nZXRBbGwoaGVhZGVyS2V5KSkge1xuICAgICAgICBoZWFkZXJzID0gaGVhZGVycy5hcHBlbmQoaGVhZGVyS2V5LCBoZWFkZXJWYWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGhlYWRlcnM7XG4gIH1cblxuICBwcm90ZWN0ZWQgY2xlYW5QYXJhbXMocGFyYW1zOiBhbnkpOiBhbnkge1xuICAgIE9iamVjdC5lbnRyaWVzKHBhcmFtcykuZm9yRWFjaCgoW2tleSwgdmFsXSkgPT4gIXZhbCAmJiBkZWxldGUgcGFyYW1zW2tleV0pO1xuICAgIHJldHVybiBwYXJhbXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgYWRkQ3JlZGVudGlhbHNUb1BhcmFtcyhwYXJhbXM6IGFueSk6IGFueSB7XG4gICAgaWYgKHRoaXMuY2xpZW50QXV0aE1ldGhvZCA9PT0gTmJPQXV0aDJDbGllbnRBdXRoTWV0aG9kLlJFUVVFU1RfQk9EWSkge1xuICAgICAgaWYgKHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRJZCcpICYmIHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRTZWNyZXQnKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLnBhcmFtcyxcbiAgICAgICAgICBjbGllbnRfaWQ6IHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRJZCcpLFxuICAgICAgICAgIGNsaWVudF9zZWNyZXQ6IHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRTZWNyZXQnKSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IEVycm9yKCdGb3IgcmVxdWVzdCBib2R5IGNsaWVudCBhdXRoZW50aWNhdGlvbiBtZXRob2QsIHBsZWFzZSBwcm92aWRlIGJvdGggY2xpZW50SWQgJiBjbGllbnRTZWNyZXQuJyk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXJhbXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlUmVzcG9uc2VFcnJvcihyZXM6IGFueSk6IE9ic2VydmFibGU8TmJBdXRoUmVzdWx0PiB7XG4gICAgbGV0IGVycm9ycyA9IFtdO1xuICAgIGlmIChyZXMgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSkge1xuICAgICAgaWYgKHJlcy5lcnJvci5lcnJvcl9kZXNjcmlwdGlvbikge1xuICAgICAgICBlcnJvcnMucHVzaChyZXMuZXJyb3IuZXJyb3JfZGVzY3JpcHRpb24pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXJyb3JzID0gdGhpcy5nZXRPcHRpb24oJ2RlZmF1bHRFcnJvcnMnKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHJlcyBpbnN0YW5jZW9mIE5iQXV0aElsbGVnYWxUb2tlbkVycm9yKSB7XG4gICAgICBlcnJvcnMucHVzaChyZXMubWVzc2FnZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVycm9ycy5wdXNoKCdTb21ldGhpbmcgd2VudCB3cm9uZy4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb2JzZXJ2YWJsZU9mKG5ldyBOYkF1dGhSZXN1bHQoZmFsc2UsIHJlcywgdGhpcy5nZXRPcHRpb24oJ3JlZGlyZWN0LmZhaWx1cmUnKSwgZXJyb3JzLCBbXSkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGJ1aWxkUmVkaXJlY3RVcmwoKSB7XG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgcmVzcG9uc2VfdHlwZTogdGhpcy5nZXRPcHRpb24oJ2F1dGhvcml6ZS5yZXNwb25zZVR5cGUnKSxcbiAgICAgIGNsaWVudF9pZDogdGhpcy5nZXRPcHRpb24oJ2NsaWVudElkJyksXG4gICAgICByZWRpcmVjdF91cmk6IHRoaXMuZ2V0T3B0aW9uKCdhdXRob3JpemUucmVkaXJlY3RVcmknKSxcbiAgICAgIHNjb3BlOiB0aGlzLmdldE9wdGlvbignYXV0aG9yaXplLnNjb3BlJyksXG4gICAgICBzdGF0ZTogdGhpcy5nZXRPcHRpb24oJ2F1dGhvcml6ZS5zdGF0ZScpLFxuXG4gICAgICAuLi50aGlzLmdldE9wdGlvbignYXV0aG9yaXplLnBhcmFtcycpLFxuICAgIH07XG5cbiAgICBjb25zdCBlbmRwb2ludCA9IHRoaXMuZ2V0QWN0aW9uRW5kcG9pbnQoJ2F1dGhvcml6ZScpO1xuICAgIGNvbnN0IHF1ZXJ5ID0gdGhpcy51cmxFbmNvZGVQYXJhbWV0ZXJzKHRoaXMuY2xlYW5QYXJhbXMocGFyYW1zKSk7XG5cbiAgICByZXR1cm4gYCR7ZW5kcG9pbnR9PyR7cXVlcnl9YDtcbiAgfVxuXG4gIHByb3RlY3RlZCBwYXJzZUhhc2hBc1F1ZXJ5UGFyYW1zKGhhc2g6IHN0cmluZyk6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0ge1xuICAgIHJldHVybiBoYXNoXG4gICAgICA/IGhhc2guc3BsaXQoJyYnKS5yZWR1Y2UoKGFjYzogYW55LCBwYXJ0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICBjb25zdCBpdGVtID0gcGFydC5zcGxpdCgnPScpO1xuICAgICAgICAgIGFjY1tpdGVtWzBdXSA9IGRlY29kZVVSSUNvbXBvbmVudChpdGVtWzFdKTtcbiAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICB9LCB7fSlcbiAgICAgIDoge307XG4gIH1cblxuICBwcm90ZWN0ZWQgdXJsRW5jb2RlUGFyYW1ldGVycyhwYXJhbXM6IGFueSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHBhcmFtcylcbiAgICAgIC5tYXAoKGspID0+IHtcbiAgICAgICAgcmV0dXJuIGAke2VuY29kZVVSSUNvbXBvbmVudChrKX09JHtlbmNvZGVVUklDb21wb25lbnQocGFyYW1zW2tdKX1gO1xuICAgICAgfSlcbiAgICAgIC5qb2luKCcmJyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlUmVmcmVzaGVkVG9rZW4ocmVzLCBleGlzdGluZ1Rva2VuOiBOYkF1dGhSZWZyZXNoYWJsZVRva2VuLCByZXF1aXJlVmFsaWRUb2tlbjogYm9vbGVhbik6IE5iQXV0aFRva2VuIHtcbiAgICB0eXBlIEF1dGhSZWZyZXNoVG9rZW4gPSBOYkF1dGhSZWZyZXNoYWJsZVRva2VuICYgTmJBdXRoVG9rZW47XG5cbiAgICBjb25zdCByZWZyZXNoZWRUb2tlbjogQXV0aFJlZnJlc2hUb2tlbiA9IHRoaXMuY3JlYXRlVG9rZW48QXV0aFJlZnJlc2hUb2tlbj4ocmVzLCByZXF1aXJlVmFsaWRUb2tlbik7XG4gICAgaWYgKCFyZWZyZXNoZWRUb2tlbi5nZXRSZWZyZXNoVG9rZW4oKSAmJiBleGlzdGluZ1Rva2VuLmdldFJlZnJlc2hUb2tlbigpKSB7XG4gICAgICByZWZyZXNoZWRUb2tlbi5zZXRSZWZyZXNoVG9rZW4oZXhpc3RpbmdUb2tlbi5nZXRSZWZyZXNoVG9rZW4oKSk7XG4gICAgfVxuICAgIHJldHVybiByZWZyZXNoZWRUb2tlbjtcbiAgfVxuXG4gIHJlZ2lzdGVyKGRhdGE/OiBhbnkpOiBPYnNlcnZhYmxlPE5iQXV0aFJlc3VsdD4ge1xuICAgIHRocm93IG5ldyBFcnJvcignYHJlZ2lzdGVyYCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGBOYk9BdXRoMkF1dGhTdHJhdGVneWAsIHVzZSBgYXV0aGVudGljYXRlYC4nKTtcbiAgfVxuXG4gIHJlcXVlc3RQYXNzd29yZChkYXRhPzogYW55KTogT2JzZXJ2YWJsZTxOYkF1dGhSZXN1bHQ+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ByZXF1ZXN0UGFzc3dvcmRgIGlzIG5vdCBzdXBwb3J0ZWQgYnkgYE5iT0F1dGgyQXV0aFN0cmF0ZWd5YCwgdXNlIGBhdXRoZW50aWNhdGVgLicpO1xuICB9XG5cbiAgcmVzZXRQYXNzd29yZChkYXRhOiBhbnkgPSB7fSk6IE9ic2VydmFibGU8TmJBdXRoUmVzdWx0PiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdgcmVzZXRQYXNzd29yZGAgaXMgbm90IHN1cHBvcnRlZCBieSBgTmJPQXV0aDJBdXRoU3RyYXRlZ3lgLCB1c2UgYGF1dGhlbnRpY2F0ZWAuJyk7XG4gIH1cblxuICBsb2dvdXQoKTogT2JzZXJ2YWJsZTxOYkF1dGhSZXN1bHQ+IHtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZU9mKG5ldyBOYkF1dGhSZXN1bHQodHJ1ZSkpO1xuICB9XG59XG4iXX0=