@nebular/auth
Version:
@nebular/auth
338 lines • 48.6 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 {
static setup(options) {
return [NbOAuth2AuthStrategy, options];
}
get responseType() {
return this.getOption('authorize.responseType');
}
get clientAuthMethod() {
return this.getOption('clientAuthMethod');
}
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;
}
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));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.0", ngImport: i0, type: NbOAuth2AuthStrategy, deps: [{ token: i1.HttpClient }, { token: i2.ActivatedRoute }, { token: NB_WINDOW }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.0", ngImport: i0, type: NbOAuth2AuthStrategy }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.0", ngImport: i0, type: NbOAuth2AuthStrategy, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.ActivatedRoute }, { type: undefined, decorators: [{
type: Inject,
args: [NB_WINDOW]
}] }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2F1dGgyLXN0cmF0ZWd5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2ZyYW1ld29yay9hdXRoL3N0cmF0ZWdpZXMvb2F1dGgyL29hdXRoMi1zdHJhdGVneS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFjLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRWxGLE9BQU8sRUFBYyxFQUFFLElBQUksWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RELE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbEQsT0FBTyxFQUFFLHVCQUF1QixFQUF1QyxNQUFNLDRCQUE0QixDQUFDO0FBQzFHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRCxPQUFPLEVBRUwsb0JBQW9CLEVBQ3BCLG9CQUFvQixFQUNwQixpQkFBaUIsRUFDakIsd0JBQXdCLEdBQ3pCLE1BQU0sMkJBQTJCLENBQUM7Ozs7QUFHbkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUVHO0FBRUgsTUFBTSxPQUFPLG9CQUFxQixTQUFRLGNBQWM7SUFDdEQsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFvQztRQUMvQyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVELElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyx3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eEIsQ0FBQztJQUVELFFBQVEsQ0FBQyxJQUFVO1FBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsNEVBQTRFLENBQUMsQ0FBQztJQUNoRyxDQUFDO0lBRUQsZUFBZSxDQUFDLElBQVU7UUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRkFBbUYsQ0FBQyxDQUFDO0lBQ3ZHLENBQUM7SUFFRCxhQUFhLENBQUMsT0FBWSxFQUFFO1FBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsaUZBQWlGLENBQUMsQ0FBQztJQUNyRyxDQUFDO0lBRUQsTUFBTTtRQUNKLE9BQU8sWUFBWSxDQUFDLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDOUMsQ0FBQzs4R0EvVVUsb0JBQW9CLDBFQWdGa0QsU0FBUztrSEFoRi9FLG9CQUFvQjs7MkZBQXBCLG9CQUFvQjtrQkFEaEMsVUFBVTs7MEJBaUZpRSxNQUFNOzJCQUFDLFNBQVMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgQWt2ZW8uIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSBMaWNlbnNlLnR4dCBpbiB0aGUgcHJvamVjdCByb290IGZvciBsaWNlbnNlIGluZm9ybWF0aW9uLlxuICovXG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlLCBIdHRwSGVhZGVycyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IE9ic2VydmFibGUsIG9mIGFzIG9ic2VydmFibGVPZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgc3dpdGNoTWFwLCBtYXAsIGNhdGNoRXJyb3IgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBOQl9XSU5ET1cgfSBmcm9tICdAbmVidWxhci90aGVtZSc7XG5cbmltcG9ydCB7IE5iQXV0aFN0cmF0ZWd5IH0gZnJvbSAnLi4vYXV0aC1zdHJhdGVneSc7XG5pbXBvcnQgeyBOYkF1dGhJbGxlZ2FsVG9rZW5FcnJvciwgTmJBdXRoUmVmcmVzaGFibGVUb2tlbiwgTmJBdXRoVG9rZW4gfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy90b2tlbi90b2tlbic7XG5pbXBvcnQgeyBOYkF1dGhSZXN1bHQgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9hdXRoLXJlc3VsdCc7XG5pbXBvcnQge1xuICBOYk9BdXRoMkF1dGhTdHJhdGVneU9wdGlvbnMsXG4gIE5iT0F1dGgyUmVzcG9uc2VUeXBlLFxuICBhdXRoMlN0cmF0ZWd5T3B0aW9ucyxcbiAgTmJPQXV0aDJHcmFudFR5cGUsXG4gIE5iT0F1dGgyQ2xpZW50QXV0aE1ldGhvZCxcbn0gZnJvbSAnLi9vYXV0aDItc3RyYXRlZ3kub3B0aW9ucyc7XG5pbXBvcnQgeyBOYkF1dGhTdHJhdGVneUNsYXNzIH0gZnJvbSAnLi4vLi4vYXV0aC5vcHRpb25zJztcblxuLyoqXG4gKiBPQXV0aDIgYXV0aGVudGljYXRpb24gc3RyYXRlZ3kuXG4gKlxuICogU3RyYXRlZ3kgc2V0dGluZ3M6XG4gKlxuICogYGBgdHNcbiAqIGV4cG9ydCBlbnVtIE5iT0F1dGgyUmVzcG9uc2VUeXBlIHtcbiAqICAgQ09ERSA9ICdjb2RlJyxcbiAqICAgVE9LRU4gPSAndG9rZW4nLFxuICogfVxuICpcbiAqIGV4cG9ydCBlbnVtIE5iT0F1dGgyR3JhbnRUeXBlIHtcbiAqICAgQVVUSE9SSVpBVElPTl9DT0RFID0gJ2F1dGhvcml6YXRpb25fY29kZScsXG4gKiAgIFBBU1NXT1JEID0gJ3Bhc3N3b3JkJyxcbiAqICAgUkVGUkVTSF9UT0tFTiA9ICdyZWZyZXNoX3Rva2VuJyxcbiAqIH1cbiAqXG4gKiBleHBvcnQgY2xhc3MgTmJPQXV0aDJBdXRoU3RyYXRlZ3lPcHRpb25zIHtcbiAqICAgbmFtZTogc3RyaW5nO1xuICogICBiYXNlRW5kcG9pbnQ/OiBzdHJpbmcgPSAnJztcbiAqICAgY2xpZW50SWQ6IHN0cmluZyA9ICcnO1xuICogICBjbGllbnRTZWNyZXQ6IHN0cmluZyA9ICcnO1xuICogICBjbGllbnRBdXRoTWV0aG9kOiBzdHJpbmcgPSBOYk9BdXRoMkNsaWVudEF1dGhNZXRob2QuTk9ORTtcbiAqICAgcmVkaXJlY3Q/OiB7IHN1Y2Nlc3M/OiBzdHJpbmc7IGZhaWx1cmU/OiBzdHJpbmcgfSA9IHtcbiAqICAgICBzdWNjZXNzOiAnLycsXG4gKiAgICAgZmFpbHVyZTogbnVsbCxcbiAqICAgfTtcbiAqICAgZGVmYXVsdEVycm9ycz86IGFueVtdID0gWydTb21ldGhpbmcgd2VudCB3cm9uZywgcGxlYXNlIHRyeSBhZ2Fpbi4nXTtcbiAqICAgZGVmYXVsdE1lc3NhZ2VzPzogYW55W10gPSBbJ1lvdSBoYXZlIGJlZW4gc3VjY2Vzc2Z1bGx5IGF1dGhlbnRpY2F0ZWQuJ107XG4gKiAgIGF1dGhvcml6ZT86IHtcbiAqICAgICBlbmRwb2ludD86IHN0cmluZztcbiAqICAgICByZWRpcmVjdFVyaT86IHN0cmluZztcbiAqICAgICByZXNwb25zZVR5cGU/OiBzdHJpbmc7XG4gKiAgICAgcmVxdWlyZVZhbGlkVG9rZW46IHRydWUsXG4gKiAgICAgc2NvcGU/OiBzdHJpbmc7XG4gKiAgICAgc3RhdGU/OiBzdHJpbmc7XG4gKiAgICAgcGFyYW1zPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcbiAqICAgfSA9IHtcbiAqICAgICBlbmRwb2ludDogJ2F1dGhvcml6ZScsXG4gKiAgICAgcmVzcG9uc2VUeXBlOiBOYk9BdXRoMlJlc3BvbnNlVHlwZS5DT0RFLFxuICogICB9O1xuICogICB0b2tlbj86IHtcbiAqICAgICBlbmRwb2ludD86IHN0cmluZztcbiAqICAgICBncmFudFR5cGU/OiBzdHJpbmc7XG4gKiAgICAgcmVxdWlyZVZhbGlkVG9rZW46IHRydWUsXG4gKiAgICAgcmVkaXJlY3RVcmk/OiBzdHJpbmc7XG4gKiAgICAgc2NvcGU/OiBzdHJpbmc7XG4gKiAgICAgY2xhc3M6IE5iQXV0aFRva2VuQ2xhc3MsXG4gKiAgIH0gPSB7XG4gKiAgICAgZW5kcG9pbnQ6ICd0b2tlbicsXG4gKiAgICAgZ3JhbnRUeXBlOiBOYk9BdXRoMkdyYW50VHlwZS5BVVRIT1JJWkFUSU9OX0NPREUsXG4gKiAgICAgY2xhc3M6IE5iQXV0aE9BdXRoMlRva2VuLFxuICogICB9O1xuICogICByZWZyZXNoPzoge1xuICogICAgIGVuZHBvaW50Pzogc3RyaW5nO1xuICogICAgIGdyYW50VHlwZT86IHN0cmluZztcbiAqICAgICBzY29wZT86IHN0cmluZztcbiAqICAgICByZXF1aXJlVmFsaWRUb2tlbjogdHJ1ZSxcbiAqICAgfSA9IHtcbiAqICAgICBlbmRwb2ludDogJ3Rva2VuJyxcbiAqICAgICBncmFudFR5cGU6IE5iT0F1dGgyR3JhbnRUeXBlLlJFRlJFU0hfVE9LRU4sXG4gKiAgIH07XG4gKiB9XG4gKiBgYGBcbiAqXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBOYk9BdXRoMkF1dGhTdHJhdGVneSBleHRlbmRzIE5iQXV0aFN0cmF0ZWd5IHtcbiAgc3RhdGljIHNldHVwKG9wdGlvbnM6IE5iT0F1dGgyQXV0aFN0cmF0ZWd5T3B0aW9ucyk6IFtOYkF1dGhTdHJhdGVneUNsYXNzLCBOYk9BdXRoMkF1dGhTdHJhdGVneU9wdGlvbnNdIHtcbiAgICByZXR1cm4gW05iT0F1dGgyQXV0aFN0cmF0ZWd5LCBvcHRpb25zXTtcbiAgfVxuXG4gIGdldCByZXNwb25zZVR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0T3B0aW9uKCdhdXRob3JpemUucmVzcG9uc2VUeXBlJyk7XG4gIH1cblxuICBnZXQgY2xpZW50QXV0aE1ldGhvZCgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRPcHRpb24oJ2NsaWVudEF1dGhNZXRob2QnKTtcbiAgfVxuXG4gIHByb3RlY3RlZCByZWRpcmVjdFJlc3VsdEhhbmRsZXJzOiB7IFtrZXk6IHN0cmluZ106IEZ1bmN0aW9uIH0gPSB7XG4gICAgW05iT0F1dGgyUmVzcG9uc2VUeXBlLkNPREVdOiAoKSA9PiB7XG4gICAgICByZXR1cm4gb2JzZXJ2YWJsZU9mKHRoaXMucm91dGUuc25hcHNob3QucXVlcnlQYXJhbXMpLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgocGFyYW1zOiBhbnkpID0+IHtcbiAgICAgICAgICBpZiAocGFyYW1zLmNvZGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlcXVlc3RUb2tlbihwYXJhbXMuY29kZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIG9ic2VydmFibGVPZihcbiAgICAgICAgICAgIG5ldyBOYkF1dGhSZXN1bHQoZmFsc2UsIHBhcmFtcywgdGhpcy5nZXRPcHRpb24oJ3JlZGlyZWN0LmZhaWx1cmUnKSwgdGhpcy5nZXRPcHRpb24oJ2RlZmF1bHRFcnJvcnMnKSwgW10pLFxuICAgICAgICAgICk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtOYk9BdXRoMlJlc3BvbnNlVHlwZS5UT0tFTl06ICgpID0+IHtcbiAgICAgIGNvbnN0IG1vZHVsZSA9ICdhdXRob3JpemUnO1xuICAgICAgY29uc3QgcmVxdWlyZVZhbGlkVG9rZW4gPSB0aGlzLmdldE9wdGlvbihgJHttb2R1bGV9LnJlcXVpcmVWYWxpZFRva2VuYCk7XG4gICAgICByZXR1cm4gb2JzZXJ2YWJsZU9mKHRoaXMucm91dGUuc25hcHNob3QuZnJhZ21lbnQpLnBpcGUoXG4gICAgICAgIG1hcCgoZnJhZ21lbnQpID0+IHRoaXMucGFyc2VIYXNoQXNRdWVyeVBhcmFtcyhmcmFnbWVudCkpLFxuICAgICAgICBtYXAoKHBhcmFtczogYW55KSA9PiB7XG4gICAgICAgICAgaWYgKCFwYXJhbXMuZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTmJBdXRoUmVzdWx0KFxuICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICBwYXJhbXMsXG4gICAgICAgICAgICAgIHRoaXMuZ2V0T3B0aW9uKCdyZWRpcmVjdC5zdWNjZXNzJyksXG4gICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICB0aGlzLmdldE9wdGlvbignZGVmYXVsdE1lc3NhZ2VzJyksXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlVG9rZW4ocGFyYW1zLCByZXF1aXJlVmFsaWRUb2tlbiksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IE5iQXV0aFJlc3VsdChcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgcGFyYW1zLFxuICAgICAgICAgICAgdGhpcy5nZXRPcHRpb24oJ3JlZGlyZWN0LmZhaWx1cmUnKSxcbiAgICAgICAgICAgIHRoaXMuZ2V0T3B0aW9uKCdkZWZhdWx0RXJyb3JzJyksXG4gICAgICAgICAgICBbXSxcbiAgICAgICAgICApO1xuICAgICAgICB9KSxcbiAgICAgICAgY2F0Y2hFcnJvcigoZXJyKSA9PiB7XG4gICAgICAgICAgY29uc3QgZXJyb3JzID0gW107XG4gICAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIE5iQXV0aElsbGVnYWxUb2tlbkVycm9yKSB7XG4gICAgICAgICAgICBlcnJvcnMucHVzaChlcnIubWVzc2FnZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVycm9ycy5wdXNoKCdTb21ldGhpbmcgd2VudCB3cm9uZy4nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG9ic2VydmFibGVPZihuZXcgTmJBdXRoUmVzdWx0KGZhbHNlLCBlcnIsIHRoaXMuZ2V0T3B0aW9uKCdyZWRpcmVjdC5mYWlsdXJlJyksIGVycm9ycykpO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfSxcbiAgfTtcblxuICBwcm90ZWN0ZWQgcmVkaXJlY3RSZXN1bHRzOiB7IFtrZXk6IHN0cmluZ106IEZ1bmN0aW9uIH0gPSB7XG4gICAgW05iT0F1dGgyUmVzcG9uc2VUeXBlLkNPREVdOiAoKSA9PiB7XG4gICAgICByZXR1cm4gb2JzZXJ2YWJsZU9mKHRoaXMucm91dGUuc25hcHNob3QucXVlcnlQYXJhbXMpLnBpcGUoXG4gICAgICAgIG1hcCgocGFyYW1zOiBhbnkpID0+ICEhKHBhcmFtcyAmJiAocGFyYW1zLmNvZGUgfHwgcGFyYW1zLmVycm9yKSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtOYk9BdXRoMlJlc3BvbnNlVHlwZS5UT0tFTl06ICgpID0+IHtcbiAgICAgIHJldHVybiBvYnNlcnZhYmxlT2YodGhpcy5yb3V0ZS5zbmFwc2hvdC5mcmFnbWVudCkucGlwZShcbiAgICAgICAgbWFwKChmcmFnbWVudCkgPT4gdGhpcy5wYXJzZUhhc2hBc1F1ZXJ5UGFyYW1zKGZyYWdtZW50KSksXG4gICAgICAgIG1hcCgocGFyYW1zOiBhbnkpID0+ICEhKHBhcmFtcyAmJiAocGFyYW1zLmFjY2Vzc190b2tlbiB8fCBwYXJhbXMuZXJyb3IpKSksXG4gICAgICApO1xuICAgIH0sXG4gIH07XG5cbiAgcHJvdGVjdGVkIGRlZmF1bHRPcHRpb25zOiBOYk9BdXRoMkF1dGhTdHJhdGVneU9wdGlvbnMgPSBhdXRoMlN0cmF0ZWd5T3B0aW9ucztcblxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgaHR0cDogSHR0cENsaWVudCwgcHJvdGVjdGVkIHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSwgQEluamVjdChOQl9XSU5ET1cpIHByb3RlY3RlZCB3aW5kb3c6IGFueSkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICBhdXRoZW50aWNhdGUoZGF0YT86IGFueSk6IE9ic2VydmFibGU8TmJBdXRoUmVzdWx0PiB7XG4gICAgaWYgKHRoaXMuZ2V0T3B0aW9uKCd0b2tlbi5ncmFudFR5cGUnKSA9PT0gTmJPQXV0aDJHcmFudFR5cGUuUEFTU1dPUkQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBhc3N3b3JkVG9rZW4oZGF0YS5lbWFpbCwgZGF0YS5wYXNzd29yZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmlzUmVkaXJlY3RSZXN1bHQoKS5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKHJlc3VsdDogYm9vbGVhbikgPT4ge1xuICAgICAgICAgIGlmICghcmVzdWx0KSB7XG4gICAgICAgICAgICB0aGlzLmF1dGhvcml6ZVJlZGlyZWN0KCk7XG4gICAgICAgICAgICByZXR1cm4gb2JzZXJ2YWJsZU9mKG5ldyBOYkF1dGhSZXN1bHQodHJ1ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdGhpcy5nZXRBdXRob3JpemF0aW9uUmVzdWx0KCk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBnZXRBdXRob3JpemF0aW9uUmVzdWx0KCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgY29uc3QgcmVkaXJlY3RSZXN1bHRIYW5kbGVyID0gdGhpcy5yZWRpcmVjdFJlc3VsdEhhbmRsZXJzW3RoaXMucmVzcG9uc2VUeXBlXTtcbiAgICBpZiAocmVkaXJlY3RSZXN1bHRIYW5kbGVyKSB7XG4gICAgICByZXR1cm4gcmVkaXJlY3RSZXN1bHRIYW5kbGVyLmNhbGwodGhpcyk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGAnJHt0aGlzLnJlc3BvbnNlVHlwZX0nIHJlc3BvbnNlVHlwZSBpcyBub3Qgc3VwcG9ydGVkLFxuICAgICAgICAgICAgICAgICAgICAgIG9ubHkgJ3Rva2VuJyBhbmQgJ2NvZGUnIGFyZSBzdXBwb3J0ZWQgbm93YCk7XG4gIH1cblxuICByZWZyZXNoVG9rZW4odG9rZW46IE5iQXV0aFJlZnJlc2hhYmxlVG9rZW4pOiBPYnNlcnZhYmxlPE5iQXV0aFJlc3VsdD4ge1xuICAgIGNvbnN0IG1vZHVsZSA9ICdyZWZyZXNoJztcbiAgICBjb25zdCB1cmwgPSB0aGlzLmdldEFjdGlvbkVuZHBvaW50KG1vZHVsZSk7XG4gICAgY29uc3QgcmVxdWlyZVZhbGlkVG9rZW4gPSB0aGlzLmdldE9wdGlvbihgJHttb2R1bGV9LnJlcXVpcmVWYWxpZFRva2VuYCk7XG5cbiAgICByZXR1cm4gdGhpcy5odHRwLnBvc3QodXJsLCB0aGlzLmJ1aWxkUmVmcmVzaFJlcXVlc3REYXRhKHRva2VuKSwgeyBoZWFkZXJzOiB0aGlzLmdldEhlYWRlcnMoKSB9KS5waXBlKFxuICAgICAgbWFwKChyZXMpID0+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBOYkF1dGhSZXN1bHQoXG4gICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICByZXMsXG4gICAgICAgICAgdGhpcy5nZXRPcHRpb24oJ3JlZGlyZWN0LnN1Y2Nlc3MnKSxcbiAgICAgICAgICBbXSxcbiAgICAgICAgICB0aGlzLmdldE9wdGlvbignZGVmYXVsdE1lc3NhZ2VzJyksXG4gICAgICAgICAgdGhpcy5jcmVhdGVSZWZyZXNoZWRUb2tlbihyZXMsIHRva2VuLCByZXF1aXJlVmFsaWRUb2tlbiksXG4gICAgICAgICk7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoKHJlcykgPT4gdGhpcy5oYW5kbGVSZXNwb25zZUVycm9yKHJlcykpLFxuICAgICk7XG4gIH1cblxuICBwYXNzd29yZFRva2VuKHVzZXJuYW1lOiBzdHJpbmcsIHBhc3N3b3JkOiBzdHJpbmcpOiBPYnNlcnZhYmxlPE5iQXV0aFJlc3VsdD4ge1xuICAgIGNvbnN0IG1vZHVsZSA9ICd0b2tlbic7XG4gICAgY29uc3QgdXJsID0gdGhpcy5nZXRBY3Rpb25FbmRwb2ludChtb2R1bGUpO1xuICAgIGNvbnN0IHJlcXVpcmVWYWxpZFRva2VuID0gdGhpcy5nZXRPcHRpb24oYCR7bW9kdWxlfS5yZXF1aXJlVmFsaWRUb2tlbmApO1xuXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0KHVybCwgdGhpcy5idWlsZFBhc3N3b3JkUmVxdWVzdERhdGEodXNlcm5hbWUsIHBhc3N3b3JkKSwgeyBoZWFkZXJzOiB0aGlzLmdldEhlYWRlcnMoKSB9KS5waXBlKFxuICAgICAgbWFwKChyZXMpID0+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBOYkF1dGhSZXN1bHQoXG4gICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICByZXMsXG4gICAgICAgICAgdGhpcy5nZXRPcHRpb24oJ3JlZGlyZWN0LnN1Y2Nlc3MnKSxcbiAgICAgICAgICBbXSxcbiAgICAgICAgICB0aGlzLmdldE9wdGlvbignZGVmYXVsdE1lc3NhZ2VzJyksXG4gICAgICAgICAgdGhpcy5jcmVhdGVUb2tlbihyZXMsIHJlcXVpcmVWYWxpZFRva2VuKSxcbiAgICAgICAgKTtcbiAgICAgIH0pLFxuICAgICAgY2F0Y2hFcnJvcigocmVzKSA9PiB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IocmVzKSksXG4gICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhdXRob3JpemVSZWRpcmVjdCgpIHtcbiAgICB0aGlzLndpbmRvdy5sb2NhdGlvbi5ocmVmID0gdGhpcy5idWlsZFJlZGlyZWN0VXJsKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaXNSZWRpcmVjdFJlc3VsdCgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5yZWRpcmVjdFJlc3VsdHNbdGhpcy5yZXNwb25zZVR5cGVdLmNhbGwodGhpcyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVxdWVzdFRva2VuKGNvZGU6IHN0cmluZykge1xuICAgIGNvbnN0IG1vZHVsZSA9ICd0b2tlbic7XG4gICAgY29uc3QgdXJsID0gdGhpcy5nZXRBY3Rpb25FbmRwb2ludChtb2R1bGUpO1xuICAgIGNvbnN0IHJlcXVpcmVWYWxpZFRva2VuID0gdGhpcy5nZXRPcHRpb24oYCR7bW9kdWxlfS5yZXF1aXJlVmFsaWRUb2tlbmApO1xuXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0KHVybCwgdGhpcy5idWlsZENvZGVSZXF1ZXN0RGF0YShjb2RlKSwgeyBoZWFkZXJzOiB0aGlzLmdldEhlYWRlcnMoKSB9KS5waXBlKFxuICAgICAgbWFwKChyZXMpID0+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBOYkF1dGhSZXN1bHQoXG4gICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICByZXMsXG4gICAgICAgICAgdGhpcy5nZXRPcHRpb24oJ3JlZGlyZWN0LnN1Y2Nlc3MnKSxcbiAgICAgICAgICBbXSxcbiAgICAgICAgICB0aGlzLmdldE9wdGlvbignZGVmYXVsdE1lc3NhZ2VzJyksXG4gICAgICAgICAgdGhpcy5jcmVhdGVUb2tlbihyZXMsIHJlcXVpcmVWYWxpZFRva2VuKSxcbiAgICAgICAgKTtcbiAgICAgIH0pLFxuICAgICAgY2F0Y2hFcnJvcigocmVzKSA9PiB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IocmVzKSksXG4gICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBidWlsZENvZGVSZXF1ZXN0RGF0YShjb2RlOiBzdHJpbmcpOiBhbnkge1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgIGdyYW50X3R5cGU6IHRoaXMuZ2V0T3B0aW9uKCd0b2tlbi5ncmFudFR5cGUnKSxcbiAgICAgIGNvZGU6IGNvZGUsXG4gICAgICByZWRpcmVjdF91cmk6IHRoaXMuZ2V0T3B0aW9uKCd0b2tlbi5yZWRpcmVjdFVyaScpLFxuICAgICAgY2xpZW50X2lkOiB0aGlzLmdldE9wdGlvbignY2xpZW50SWQnKSxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLnVybEVuY29kZVBhcmFtZXRlcnModGhpcy5jbGVhblBhcmFtcyh0aGlzLmFkZENyZWRlbnRpYWxzVG9QYXJhbXMocGFyYW1zKSkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGJ1aWxkUmVmcmVzaFJlcXVlc3REYXRhKHRva2VuOiBOYkF1dGhSZWZyZXNoYWJsZVRva2VuKTogYW55IHtcbiAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICBncmFudF90eXBlOiB0aGlzLmdldE9wdGlvbigncmVmcmVzaC5ncmFudFR5cGUnKSxcbiAgICAgIHJlZnJlc2hfdG9rZW46IHRva2VuLmdldFJlZnJlc2hUb2tlbigpLFxuICAgICAgc2NvcGU6IHRoaXMuZ2V0T3B0aW9uKCdyZWZyZXNoLnNjb3BlJyksXG4gICAgICBjbGllbnRfaWQ6IHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRJZCcpLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMudXJsRW5jb2RlUGFyYW1ldGVycyh0aGlzLmNsZWFuUGFyYW1zKHRoaXMuYWRkQ3JlZGVudGlhbHNUb1BhcmFtcyhwYXJhbXMpKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYnVpbGRQYXNzd29yZFJlcXVlc3REYXRhKHVzZXJuYW1lOiBzdHJpbmcsIHBhc3N3b3JkOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgIGdyYW50X3R5cGU6IHRoaXMuZ2V0T3B0aW9uKCd0b2tlbi5ncmFudFR5cGUnKSxcbiAgICAgIHVzZXJuYW1lOiB1c2VybmFtZSxcbiAgICAgIHBhc3N3b3JkOiBwYXNzd29yZCxcbiAgICAgIHNjb3BlOiB0aGlzLmdldE9wdGlvbigndG9rZW4uc2NvcGUnKSxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLnVybEVuY29kZVBhcmFtZXRlcnModGhpcy5jbGVhblBhcmFtcyh0aGlzLmFkZENyZWRlbnRpYWxzVG9QYXJhbXMocGFyYW1zKSkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGJ1aWxkQXV0aEhlYWRlcigpOiBIdHRwSGVhZGVycyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMuY2xpZW50QXV0aE1ldGhvZCA9PT0gTmJPQXV0aDJDbGllbnRBdXRoTWV0aG9kLkJBU0lDKSB7XG4gICAgICBpZiAodGhpcy5nZXRPcHRpb24oJ2NsaWVudElkJykgJiYgdGhpcy5nZXRPcHRpb24oJ2NsaWVudFNlY3JldCcpKSB7XG4gICAgICAgIHJldHVybiBuZXcgSHR0cEhlYWRlcnMoe1xuICAgICAgICAgIEF1dGhvcml6YXRpb246ICdCYXNpYyAnICsgYnRvYSh0aGlzLmdldE9wdGlvbignY2xpZW50SWQnKSArICc6JyArIHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRTZWNyZXQnKSksXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ0ZvciBiYXNpYyBjbGllbnQgYXV0aGVudGljYXRpb24gbWV0aG9kLCBwbGVhc2UgcHJvdmlkZSBib3RoIGNsaWVudElkICYgY2xpZW50U2VjcmV0LicpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldEhlYWRlcnMoKTogSHR0cEhlYWRlcnMge1xuICAgIGxldCBoZWFkZXJzID0gc3VwZXIuZ2V0SGVhZGVycygpO1xuICAgIGhlYWRlcnMgPSBoZWFkZXJzLmFwcGVuZCgnQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpO1xuXG4gICAgY29uc3QgYXV0aEhlYWRlcnMgPSB0aGlzLmJ1aWxkQXV0aEhlYWRlcigpO1xuICAgIGlmIChhdXRoSGVhZGVycyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gaGVhZGVycztcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGhlYWRlcktleSBvZiBhdXRoSGVhZGVycy5rZXlzKCkpIHtcbiAgICAgIGZvciAoY29uc3QgaGVhZGVyVmFsdWUgb2YgYXV0aEhlYWRlcnMuZ2V0QWxsKGhlYWRlcktleSkpIHtcbiAgICAgICAgaGVhZGVycyA9IGhlYWRlcnMuYXBwZW5kKGhlYWRlcktleSwgaGVhZGVyVmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBoZWFkZXJzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNsZWFuUGFyYW1zKHBhcmFtczogYW55KTogYW55IHtcbiAgICBPYmplY3QuZW50cmllcyhwYXJhbXMpLmZvckVhY2goKFtrZXksIHZhbF0pID0+ICF2YWwgJiYgZGVsZXRlIHBhcmFtc1trZXldKTtcbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFkZENyZWRlbnRpYWxzVG9QYXJhbXMocGFyYW1zOiBhbnkpOiBhbnkge1xuICAgIGlmICh0aGlzLmNsaWVudEF1dGhNZXRob2QgPT09IE5iT0F1dGgyQ2xpZW50QXV0aE1ldGhvZC5SRVFVRVNUX0JPRFkpIHtcbiAgICAgIGlmICh0aGlzLmdldE9wdGlvbignY2xpZW50SWQnKSAmJiB0aGlzLmdldE9wdGlvbignY2xpZW50U2VjcmV0JykpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5wYXJhbXMsXG4gICAgICAgICAgY2xpZW50X2lkOiB0aGlzLmdldE9wdGlvbignY2xpZW50SWQnKSxcbiAgICAgICAgICBjbGllbnRfc2VjcmV0OiB0aGlzLmdldE9wdGlvbignY2xpZW50U2VjcmV0JyksXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBFcnJvcignRm9yIHJlcXVlc3QgYm9keSBjbGllbnQgYXV0aGVudGljYXRpb24gbWV0aG9kLCBwbGVhc2UgcHJvdmlkZSBib3RoIGNsaWVudElkICYgY2xpZW50U2VjcmV0LicpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhbmRsZVJlc3BvbnNlRXJyb3IocmVzOiBhbnkpOiBPYnNlcnZhYmxlPE5iQXV0aFJlc3VsdD4ge1xuICAgIGxldCBlcnJvcnMgPSBbXTtcbiAgICBpZiAocmVzIGluc3RhbmNlb2YgSHR0cEVycm9yUmVzcG9uc2UpIHtcbiAgICAgIGlmIChyZXMuZXJyb3IuZXJyb3JfZGVzY3JpcHRpb24pIHtcbiAgICAgICAgZXJyb3JzLnB1c2gocmVzLmVycm9yLmVycm9yX2Rlc2NyaXB0aW9uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVycm9ycyA9IHRoaXMuZ2V0T3B0aW9uKCdkZWZhdWx0RXJyb3JzJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChyZXMgaW5zdGFuY2VvZiBOYkF1dGhJbGxlZ2FsVG9rZW5FcnJvcikge1xuICAgICAgZXJyb3JzLnB1c2gocmVzLm1lc3NhZ2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICBlcnJvcnMucHVzaCgnU29tZXRoaW5nIHdlbnQgd3JvbmcuJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9ic2VydmFibGVPZihuZXcgTmJBdXRoUmVzdWx0KGZhbHNlLCByZXMsIHRoaXMuZ2V0T3B0aW9uKCdyZWRpcmVjdC5mYWlsdXJlJyksIGVycm9ycywgW10pKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBidWlsZFJlZGlyZWN0VXJsKCkge1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgIHJlc3BvbnNlX3R5cGU6IHRoaXMuZ2V0T3B0aW9uKCdhdXRob3JpemUucmVzcG9uc2VUeXBlJyksXG4gICAgICBjbGllbnRfaWQ6IHRoaXMuZ2V0T3B0aW9uKCdjbGllbnRJZCcpLFxuICAgICAgcmVkaXJlY3RfdXJpOiB0aGlzLmdldE9wdGlvbignYXV0aG9yaXplLnJlZGlyZWN0VXJpJyksXG4gICAgICBzY29wZTogdGhpcy5nZXRPcHRpb24oJ2F1dGhvcml6ZS5zY29wZScpLFxuICAgICAgc3RhdGU6IHRoaXMuZ2V0T3B0aW9uKCdhdXRob3JpemUuc3RhdGUnKSxcblxuICAgICAgLi4udGhpcy5nZXRPcHRpb24oJ2F1dGhvcml6ZS5wYXJhbXMnKSxcbiAgICB9O1xuXG4gICAgY29uc3QgZW5kcG9pbnQgPSB0aGlzLmdldEFjdGlvbkVuZHBvaW50KCdhdXRob3JpemUnKTtcbiAgICBjb25zdCBxdWVyeSA9IHRoaXMudXJsRW5jb2RlUGFyYW1ldGVycyh0aGlzLmNsZWFuUGFyYW1zKHBhcmFtcykpO1xuXG4gICAgcmV0dXJuIGAke2VuZHBvaW50fT8ke3F1ZXJ5fWA7XG4gIH1cblxuICBwcm90ZWN0ZWQgcGFyc2VIYXNoQXNRdWVyeVBhcmFtcyhoYXNoOiBzdHJpbmcpOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9IHtcbiAgICByZXR1cm4gaGFzaFxuICAgICAgPyBoYXNoLnNwbGl0KCcmJykucmVkdWNlKChhY2M6IGFueSwgcGFydDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgY29uc3QgaXRlbSA9IHBhcnQuc3BsaXQoJz0nKTtcbiAgICAgICAgICBhY2NbaXRlbVswXV0gPSBkZWNvZGVVUklDb21wb25lbnQoaXRlbVsxXSk7XG4gICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgfSwge30pXG4gICAgICA6IHt9O1xuICB9XG5cbiAgcHJvdGVjdGVkIHVybEVuY29kZVBhcmFtZXRlcnMocGFyYW1zOiBhbnkpOiBzdHJpbmcge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhwYXJhbXMpXG4gICAgICAubWFwKChrKSA9PiB7XG4gICAgICAgIHJldHVybiBgJHtlbmNvZGVVUklDb21wb25lbnQoayl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHBhcmFtc1trXSl9YDtcbiAgICAgIH0pXG4gICAgICAuam9pbignJicpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNyZWF0ZVJlZnJlc2hlZFRva2VuKHJlcywgZXhpc3RpbmdUb2tlbjogTmJBdXRoUmVmcmVzaGFibGVUb2tlbiwgcmVxdWlyZVZhbGlkVG9rZW46IGJvb2xlYW4pOiBOYkF1dGhUb2tlbiB7XG4gICAgdHlwZSBBdXRoUmVmcmVzaFRva2VuID0gTmJBdXRoUmVmcmVzaGFibGVUb2tlbiAmIE5iQXV0aFRva2VuO1xuXG4gICAgY29uc3QgcmVmcmVzaGVkVG9rZW46IEF1dGhSZWZyZXNoVG9rZW4gPSB0aGlzLmNyZWF0ZVRva2VuPEF1dGhSZWZyZXNoVG9rZW4+KHJlcywgcmVxdWlyZVZhbGlkVG9rZW4pO1xuICAgIGlmICghcmVmcmVzaGVkVG9rZW4uZ2V0UmVmcmVzaFRva2VuKCkgJiYgZXhpc3RpbmdUb2tlbi5nZXRSZWZyZXNoVG9rZW4oKSkge1xuICAgICAgcmVmcmVzaGVkVG9rZW4uc2V0UmVmcmVzaFRva2VuKGV4aXN0aW5nVG9rZW4uZ2V0UmVmcmVzaFRva2VuKCkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVmcmVzaGVkVG9rZW47XG4gIH1cblxuICByZWdpc3RlcihkYXRhPzogYW55KTogT2JzZXJ2YWJsZTxOYkF1dGhSZXN1bHQ+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ByZWdpc3RlcmAgaXMgbm90IHN1cHBvcnRlZCBieSBgTmJPQXV0aDJBdXRoU3RyYXRlZ3lgLCB1c2UgYGF1dGhlbnRpY2F0ZWAuJyk7XG4gIH1cblxuICByZXF1ZXN0UGFzc3dvcmQoZGF0YT86IGFueSk6IE9ic2VydmFibGU8TmJBdXRoUmVzdWx0PiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdgcmVxdWVzdFBhc3N3b3JkYCBpcyBub3Qgc3VwcG9ydGVkIGJ5IGBOYk9BdXRoMkF1dGhTdHJhdGVneWAsIHVzZSBgYXV0aGVudGljYXRlYC4nKTtcbiAgfVxuXG4gIHJlc2V0UGFzc3dvcmQoZGF0YTogYW55ID0ge30pOiBPYnNlcnZhYmxlPE5iQXV0aFJlc3VsdD4ge1xuICAgIHRocm93IG5ldyBFcnJvcignYHJlc2V0UGFzc3dvcmRgIGlzIG5vdCBzdXBwb3J0ZWQgYnkgYE5iT0F1dGgyQXV0aFN0cmF0ZWd5YCwgdXNlIGBhdXRoZW50aWNhdGVgLicpO1xuICB9XG5cbiAgbG9nb3V0KCk6IE9ic2VydmFibGU8TmJBdXRoUmVzdWx0PiB7XG4gICAgcmV0dXJuIG9ic2VydmFibGVPZihuZXcgTmJBdXRoUmVzdWx0KHRydWUpKTtcbiAgfVxufVxuIl19