@alauda-fe/common
Version:
Alauda frontend team common codes.
174 lines • 27.2 kB
JavaScript
/**
* @packageDocumentation
* @module authorization
*/
import { DialogService } from '@alauda/ui';
import { Inject, Injectable, Injector } from '@angular/core';
import { NEVER, from, throwError, catchError, concatMap, take, map, of, switchMap, } from 'rxjs';
import { ApiGatewayService } from '../api/public-api';
import { ANONYMOUS_APIS, catchPromise } from '../core/public-api';
import { TranslateService } from '../translate/public-api';
import { checkAuthorizationToken, logout, refreshAuthorizationToken, } from './authorization';
import { SESSION_MANAGE_KEY } from './constants';
import { SessionManageService } from './session-manage.service';
import { readStorageToken } from './storage-token';
import * as i0 from "@angular/core";
import * as i1 from "../api/public-api";
import * as i2 from "@alauda/ui";
import * as i3 from "./session-manage.service";
const AUTHORIZATION_API_PREFIX = '/console/api/v2/token/';
// Interceptor must provide with correct order, not provide in root here
// https://angular.cn/guide/http#interceptor-order
export class AuthorizationInterceptorService {
constructor(anonymousApis, apiGateway, injector, dialog, sessionManage) {
this.anonymousApis = anonymousApis;
this.apiGateway = apiGateway;
this.injector = injector;
this.dialog = dialog;
this.sessionManage = sessionManage;
this.sessionInvalidConfirm = false;
}
intercept(req, next) {
if (this.isRelativeUrl(req.url)) {
if (!this.isConsoleApi(req.url) || !this.needConsoleAuthorization(req)) {
return next.handle(req);
}
return this.handleAuthorizedRequest(next, req, null);
}
return this.apiGateway.getApiAddress().pipe(take(1), concatMap(apiAddress => {
if (!this.needAuthorization(apiAddress, req)) {
return next.handle(req);
}
return this.handleAuthorizedRequest(next, req, apiAddress);
}));
}
// A relative URL shares the same origin as the console (no http(s):// or // prefix)
isRelativeUrl(url) {
const lowerCaseUrl = (url || '').toLowerCase();
return (!lowerCaseUrl.startsWith('http://') &&
!lowerCaseUrl.startsWith('https://') &&
!lowerCaseUrl.startsWith('//'));
}
isConsoleApi(url) {
return this.isRelativeUrl(url) && url.startsWith('/console/api/');
}
isAuthorizationApi(url) {
return url.startsWith(AUTHORIZATION_API_PREFIX);
}
cloneReq(req, idToken) {
return idToken && !req.headers.get('Authorization')
? req.clone({
setHeaders: {
Authorization: `Bearer ${idToken}`,
},
})
: req;
}
handleAuthorizedRequest(next, req, apiAddress) {
const isConsoleApi = this.isConsoleApi(req.url);
const isAuthorizationApi = this.isAuthorizationApi(req.url);
const idToken = readStorageToken();
const authReq = this.cloneReq(req, idToken);
return next.handle(authReq).pipe(catchError((error) => {
if (this.isSessionInvalid(error)) {
this.handleSessionInvalid();
return NEVER;
}
// 当用户被禁用自动登出
if (this.isInvalidUser(error)) {
return from(logout(true));
}
if (!this.isUnauthorized(error)) {
return throwError(() => error);
}
if (isAuthorizationApi) {
return throwError(() => error);
}
if (!isConsoleApi && this.isWatchReq(apiAddress, authReq)) {
return NEVER;
}
return from(checkAuthorizationToken()).pipe(map(() => false), catchError(() => of(true)), switchMap(expired => expired || (isConsoleApi && !idToken)
? this.retryAuth(next, authReq)
: throwError(() => error)));
}));
}
retryAuth(next, req) {
return from(refreshAuthorizationToken()).pipe(catchError(() => from(logout(true))), concatMap(({ id_token: idToken }) => {
const authReq = this.cloneReq(req, idToken);
return next.handle(authReq).pipe(catchError((error) => {
if (this.isUnauthorized(error)) {
return from(logout(true)).pipe(catchError(() => throwError(() => error)), switchMap(() => throwError(() => error)));
}
return throwError(() => error);
}));
}));
}
needAuthorization(apiAddress, req) {
if (req.headers.get('Authorization') ||
(!this.isConsoleApi(req.url) && !req.url.startsWith(apiAddress))) {
return false;
}
return !this.anonymousApis.some(api => api instanceof RegExp ? api.test(req.url) : req.url.includes(api));
}
needConsoleAuthorization(req) {
if (req.headers.get('Authorization')) {
return false;
}
return !this.anonymousApis.some(api => api instanceof RegExp ? api.test(req.url) : req.url.includes(api));
}
is401({ error }) {
return this.isStatus(error) && error.code === 401;
}
isSessionInvalid(errorRes) {
const { error } = errorRes;
return this.is401(errorRes) && error.reason === 'SessionInvalid';
}
handleSessionInvalid() {
this.sessionManage.complete();
if (Date.now() - parseInt(sessionStorage.getItem(SESSION_MANAGE_KEY)) <
5000) {
sessionStorage.removeItem(SESSION_MANAGE_KEY);
logout(true);
return;
}
if (this.sessionInvalidConfirm) {
return;
}
this.sessionInvalidConfirm = true;
// fix circle dependency error
const translate = this.injector.get(TranslateService);
catchPromise(this.dialog.confirm({
title: translate.get('session_invalid_hint'),
confirmText: translate.get('i_know'),
cancelButton: false,
})).subscribe(() => {
this.sessionInvalidConfirm = false;
logout(true);
});
}
isUnauthorized(errorRes) {
return this.is401(errorRes) && errorRes.error.reason === 'Unauthorized';
}
isInvalidUser(errorRes) {
return this.is401(errorRes) && errorRes.error.reason === 'InvalidUser';
}
isStatus(error) {
return error && typeof error !== 'string' && 'code' in error;
}
isWatchReq(apiAddress, { url, params }) {
const isStandardApi = url.startsWith(apiAddress + '/api/') ||
url.startsWith(apiAddress + '/apis/') ||
url.startsWith(apiAddress + '/kubernetes/');
const isWatchOn = params.get('watch')?.toLowerCase() === 'true';
return isStandardApi && isWatchOn;
}
static { this.ɵfac = function AuthorizationInterceptorService_Factory(t) { return new (t || AuthorizationInterceptorService)(i0.ɵɵinject(ANONYMOUS_APIS), i0.ɵɵinject(i1.ApiGatewayService), i0.ɵɵinject(i0.Injector), i0.ɵɵinject(i2.DialogService), i0.ɵɵinject(i3.SessionManageService)); }; }
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: AuthorizationInterceptorService, factory: AuthorizationInterceptorService.ɵfac }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AuthorizationInterceptorService, [{
type: Injectable
}], () => [{ type: Array, decorators: [{
type: Inject,
args: [ANONYMOUS_APIS]
}] }, { type: i1.ApiGatewayService }, { type: i0.Injector }, { type: i2.DialogService }, { type: i3.SessionManageService }], null); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJjZXB0b3Iuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2xpYnMvY29tbW9uL3NyYy9hdXRob3JpemF0aW9uL2ludGVyY2VwdG9yLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQU8zQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0QsT0FBTyxFQUNMLEtBQUssRUFDTCxJQUFJLEVBQ0osVUFBVSxFQUNWLFVBQVUsRUFDVixTQUFTLEVBQ1QsSUFBSSxFQUNKLEdBQUcsRUFDSCxFQUFFLEVBQ0YsU0FBUyxHQUNWLE1BQU0sTUFBTSxDQUFDO0FBRWQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQVUsTUFBTSxvQkFBb0IsQ0FBQztBQUMxRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUzRCxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLE1BQU0sRUFDTix5QkFBeUIsR0FDMUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDakQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7O0FBRW5ELE1BQU0sd0JBQXdCLEdBQUcsd0JBQXdCLENBQUM7QUFFMUQsd0VBQXdFO0FBQ3hFLGtEQUFrRDtBQUVsRCxNQUFNLE9BQU8sK0JBQStCO0lBRzFDLFlBRW1CLGFBQXFDLEVBQ3JDLFVBQTZCLEVBQzdCLFFBQWtCLEVBQ2xCLE1BQXFCLEVBQ3JCLGFBQW1DO1FB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QUFLLENBQUMsUUFBUSxDQUFDLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssY0FBYyxDQUFDO0lBQzFFLENBQUM7SUFFTyxhQUFhLENBQUMsUUFBMkI7UUFDL0MsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLGFBQWEsQ0FBQztJQUN6RSxDQUFDO0lBRU8sUUFBUSxDQUFDLEtBQXNCO1FBQ3JDLE9BQU8sS0FBSyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxNQUFNLElBQUksS0FBSyxDQUFDO0lBQy9ELENBQUM7SUFFTyxVQUFVLENBQ2hCLFVBQWtCLEVBQ2xCLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBd0I7UUFFckMsTUFBTSxhQUFhLEdBQ2pCLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQztZQUNwQyxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsR0FBRyxRQUFRLENBQUM7WUFDckMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLEdBQUcsY0FBYyxDQUFDLENBQUM7UUFDOUMsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxXQUFXLEVBQUUsS0FBSyxNQUFNLENBQUM7UUFDaEUsT0FBTyxhQUFhLElBQUksU0FBUyxDQUFDO0lBQ3BDLENBQUM7Z0dBek5VLCtCQUErQixjQUloQyxjQUFjO3VFQUpiLCtCQUErQixXQUEvQiwrQkFBK0I7O2lGQUEvQiwrQkFBK0I7Y0FEM0MsVUFBVTs7c0JBS04sTUFBTTt1QkFBQyxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqIEBtb2R1bGUgYXV0aG9yaXphdGlvblxuICovXG5cbmltcG9ydCB7IERpYWxvZ1NlcnZpY2UgfSBmcm9tICdAYWxhdWRhL3VpJztcbmltcG9ydCB7XG4gIEh0dHBFcnJvclJlc3BvbnNlLFxuICBIdHRwSGFuZGxlcixcbiAgSHR0cEludGVyY2VwdG9yLFxuICBIdHRwUmVxdWVzdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3RvciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgTkVWRVIsXG4gIGZyb20sXG4gIHRocm93RXJyb3IsXG4gIGNhdGNoRXJyb3IsXG4gIGNvbmNhdE1hcCxcbiAgdGFrZSxcbiAgbWFwLFxuICBvZixcbiAgc3dpdGNoTWFwLFxufSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgQXBpR2F0ZXdheVNlcnZpY2UgfSBmcm9tICcuLi9hcGkvcHVibGljLWFwaSc7XG5pbXBvcnQgeyBBTk9OWU1PVVNfQVBJUywgY2F0Y2hQcm9taXNlLCBTdGF0dXMgfSBmcm9tICcuLi9jb3JlL3B1YmxpYy1hcGknO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJy4uL3RyYW5zbGF0ZS9wdWJsaWMtYXBpJztcblxuaW1wb3J0IHtcbiAgY2hlY2tBdXRob3JpemF0aW9uVG9rZW4sXG4gIGxvZ291dCxcbiAgcmVmcmVzaEF1dGhvcml6YXRpb25Ub2tlbixcbn0gZnJvbSAnLi9hdXRob3JpemF0aW9uJztcbmltcG9ydCB7IFNFU1NJT05fTUFOQUdFX0tFWSB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IFNlc3Npb25NYW5hZ2VTZXJ2aWNlIH0gZnJvbSAnLi9zZXNzaW9uLW1hbmFnZS5zZXJ2aWNlJztcbmltcG9ydCB7IHJlYWRTdG9yYWdlVG9rZW4gfSBmcm9tICcuL3N0b3JhZ2UtdG9rZW4nO1xuXG5jb25zdCBBVVRIT1JJWkFUSU9OX0FQSV9QUkVGSVggPSAnL2NvbnNvbGUvYXBpL3YyL3Rva2VuLyc7XG5cbi8vIEludGVyY2VwdG9yIG11c3QgcHJvdmlkZSB3aXRoIGNvcnJlY3Qgb3JkZXIsIG5vdCBwcm92aWRlIGluIHJvb3QgaGVyZVxuLy8gaHR0cHM6Ly9hbmd1bGFyLmNuL2d1aWRlL2h0dHAjaW50ZXJjZXB0b3Itb3JkZXJcbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBdXRob3JpemF0aW9uSW50ZXJjZXB0b3JTZXJ2aWNlIGltcGxlbWVudHMgSHR0cEludGVyY2VwdG9yIHtcbiAgcHJpdmF0ZSBzZXNzaW9uSW52YWxpZENvbmZpcm0gPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KEFOT05ZTU9VU19BUElTKVxuICAgIHByaXZhdGUgcmVhZG9ubHkgYW5vbnltb3VzQXBpczogQXJyYXk8c3RyaW5nIHwgUmVnRXhwPixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFwaUdhdGV3YXk6IEFwaUdhdGV3YXlTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZGlhbG9nOiBEaWFsb2dTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2Vzc2lvbk1hbmFnZTogU2Vzc2lvbk1hbmFnZVNlcnZpY2UsXG4gICkge31cblxuICBpbnRlcmNlcHQocmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPiwgbmV4dDogSHR0cEhhbmRsZXIpIHtcbiAgICBpZiAodGhpcy5pc1JlbGF0aXZlVXJsKHJlcS51cmwpKSB7XG4gICAgICBpZiAoIXRoaXMuaXNDb25zb2xlQXBpKHJlcS51cmwpIHx8ICF0aGlzLm5lZWRDb25zb2xlQXV0aG9yaXphdGlvbihyZXEpKSB7XG4gICAgICAgIHJldHVybiBuZXh0LmhhbmRsZShyZXEpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVBdXRob3JpemVkUmVxdWVzdChuZXh0LCByZXEsIG51bGwpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmFwaUdhdGV3YXkuZ2V0QXBpQWRkcmVzcygpLnBpcGUoXG4gICAgICB0YWtlKDEpLFxuICAgICAgY29uY2F0TWFwKGFwaUFkZHJlc3MgPT4ge1xuICAgICAgICBpZiAoIXRoaXMubmVlZEF1dGhvcml6YXRpb24oYXBpQWRkcmVzcywgcmVxKSkge1xuICAgICAgICAgIHJldHVybiBuZXh0LmhhbmRsZShyZXEpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlQXV0aG9yaXplZFJlcXVlc3QobmV4dCwgcmVxLCBhcGlBZGRyZXNzKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICAvLyBBIHJlbGF0aXZlIFVSTCBzaGFyZXMgdGhlIHNhbWUgb3JpZ2luIGFzIHRoZSBjb25zb2xlIChubyBodHRwKHMpOi8vIG9yIC8vIHByZWZpeClcbiAgcHJpdmF0ZSBpc1JlbGF0aXZlVXJsKHVybDogc3RyaW5nKSB7XG4gICAgY29uc3QgbG93ZXJDYXNlVXJsID0gKHVybCB8fCAnJykudG9Mb3dlckNhc2UoKTtcblxuICAgIHJldHVybiAoXG4gICAgICAhbG93ZXJDYXNlVXJsLnN0YXJ0c1dpdGgoJ2h0dHA6Ly8nKSAmJlxuICAgICAgIWxvd2VyQ2FzZVVybC5zdGFydHNXaXRoKCdodHRwczovLycpICYmXG4gICAgICAhbG93ZXJDYXNlVXJsLnN0YXJ0c1dpdGgoJy8vJylcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0NvbnNvbGVBcGkodXJsOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5pc1JlbGF0aXZlVXJsKHVybCkgJiYgdXJsLnN0YXJ0c1dpdGgoJy9jb25zb2xlL2FwaS8nKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNBdXRob3JpemF0aW9uQXBpKHVybDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHVybC5zdGFydHNXaXRoKEFVVEhPUklaQVRJT05fQVBJX1BSRUZJWCk7XG4gIH1cblxuICBwcml2YXRlIGNsb25lUmVxKHJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4sIGlkVG9rZW46IHN0cmluZykge1xuICAgIHJldHVybiBpZFRva2VuICYmICFyZXEuaGVhZGVycy5nZXQoJ0F1dGhvcml6YXRpb24nKVxuICAgICAgPyByZXEuY2xvbmUoe1xuICAgICAgICAgIHNldEhlYWRlcnM6IHtcbiAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtpZFRva2VufWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgIDogcmVxO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVBdXRob3JpemVkUmVxdWVzdChcbiAgICBuZXh0OiBIdHRwSGFuZGxlcixcbiAgICByZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LFxuICAgIGFwaUFkZHJlc3M6IHN0cmluZyB8IG51bGwsXG4gICkge1xuICAgIGNvbnN0IGlzQ29uc29sZUFwaSA9IHRoaXMuaXNDb25zb2xlQXBpKHJlcS51cmwpO1xuICAgIGNvbnN0IGlzQXV0aG9yaXphdGlvbkFwaSA9IHRoaXMuaXNBdXRob3JpemF0aW9uQXBpKHJlcS51cmwpO1xuICAgIGNvbnN0IGlkVG9rZW4gPSByZWFkU3RvcmFnZVRva2VuKCk7XG4gICAgY29uc3QgYXV0aFJlcSA9IHRoaXMuY2xvbmVSZXEocmVxLCBpZFRva2VuKTtcblxuICAgIHJldHVybiBuZXh0LmhhbmRsZShhdXRoUmVxKS5waXBlKFxuICAgICAgY2F0Y2hFcnJvcigoZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmlzU2Vzc2lvbkludmFsaWQoZXJyb3IpKSB7XG4gICAgICAgICAgdGhpcy5oYW5kbGVTZXNzaW9uSW52YWxpZCgpO1xuICAgICAgICAgIHJldHVybiBORVZFUjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIOW9k+eUqOaIt+iiq+emgeeUqOiHquWKqOeZu+WHulxuICAgICAgICBpZiAodGhpcy5pc0ludmFsaWRVc2VyKGVycm9yKSkge1xuICAgICAgICAgIHJldHVybiBmcm9tKGxvZ291dCh0cnVlKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuaXNVbmF1dGhvcml6ZWQoZXJyb3IpKSB7XG4gICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyb3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzQXV0aG9yaXphdGlvbkFwaSkge1xuICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNDb25zb2xlQXBpICYmIHRoaXMuaXNXYXRjaFJlcShhcGlBZGRyZXNzLCBhdXRoUmVxKSkge1xuICAgICAgICAgIHJldHVybiBORVZFUjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmcm9tKGNoZWNrQXV0aG9yaXphdGlvblRva2VuKCkpLnBpcGUoXG4gICAgICAgICAgbWFwKCgpID0+IGZhbHNlKSxcbiAgICAgICAgICBjYXRjaEVycm9yKCgpID0+IG9mKHRydWUpKSxcbiAgICAgICAgICBzd2l0Y2hNYXAoZXhwaXJlZCA9PlxuICAgICAgICAgICAgZXhwaXJlZCB8fCAoaXNDb25zb2xlQXBpICYmICFpZFRva2VuKVxuICAgICAgICAgICAgICA/IHRoaXMucmV0cnlBdXRoKG5leHQsIGF1dGhSZXEpXG4gICAgICAgICAgICAgIDogdGhyb3dFcnJvcigoKSA9PiBlcnJvciksXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHJldHJ5QXV0aChuZXh0OiBIdHRwSGFuZGxlciwgcmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPikge1xuICAgIHJldHVybiBmcm9tKHJlZnJlc2hBdXRob3JpemF0aW9uVG9rZW4oKSkucGlwZShcbiAgICAgIGNhdGNoRXJyb3IoKCkgPT4gZnJvbShsb2dvdXQodHJ1ZSkpKSxcbiAgICAgIGNvbmNhdE1hcCgoeyBpZF90b2tlbjogaWRUb2tlbiB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGF1dGhSZXEgPSB0aGlzLmNsb25lUmVxKHJlcSwgaWRUb2tlbik7XG4gICAgICAgIHJldHVybiBuZXh0LmhhbmRsZShhdXRoUmVxKS5waXBlKFxuICAgICAgICAgIGNhdGNoRXJyb3IoKGVycm9yOiBIdHRwRXJyb3JSZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNVbmF1dGhvcml6ZWQoZXJyb3IpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBmcm9tKGxvZ291dCh0cnVlKSkucGlwZShcbiAgICAgICAgICAgICAgICBjYXRjaEVycm9yKCgpID0+IHRocm93RXJyb3IoKCkgPT4gZXJyb3IpKSxcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcikpLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBuZWVkQXV0aG9yaXphdGlvbihcbiAgICBhcGlBZGRyZXNzOiBzdHJpbmcsXG4gICAgcmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgKTogYm9vbGVhbiB7XG4gICAgaWYgKFxuICAgICAgcmVxLmhlYWRlcnMuZ2V0KCdBdXRob3JpemF0aW9uJykgfHxcbiAgICAgICghdGhpcy5pc0NvbnNvbGVBcGkocmVxLnVybCkgJiYgIXJlcS51cmwuc3RhcnRzV2l0aChhcGlBZGRyZXNzKSlcbiAgICApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gIXRoaXMuYW5vbnltb3VzQXBpcy5zb21lKGFwaSA9PlxuICAgICAgYXBpIGluc3RhbmNlb2YgUmVnRXhwID8gYXBpLnRlc3QocmVxLnVybCkgOiByZXEudXJsLmluY2x1ZGVzKGFwaSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgbmVlZENvbnNvbGVBdXRob3JpemF0aW9uKHJlcTogSHR0cFJlcXVlc3Q8dW5rbm93bj4pIHtcbiAgICBpZiAocmVxLmhlYWRlcnMuZ2V0KCdBdXRob3JpemF0aW9uJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gIXRoaXMuYW5vbnltb3VzQXBpcy5zb21lKGFwaSA9PlxuICAgICAgYXBpIGluc3RhbmNlb2YgUmVnRXhwID8gYXBpLnRlc3QocmVxLnVybCkgOiByZXEudXJsLmluY2x1ZGVzKGFwaSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgaXM0MDEoeyBlcnJvciB9OiBIdHRwRXJyb3JSZXNwb25zZSkge1xuICAgIHJldHVybiB0aGlzLmlzU3RhdHVzKGVycm9yKSAmJiBlcnJvci5jb2RlID09PSA0MDE7XG4gIH1cblxuICBwcml2YXRlIGlzU2Vzc2lvbkludmFsaWQoZXJyb3JSZXM6IEh0dHBFcnJvclJlc3BvbnNlKSB7XG4gICAgY29uc3QgeyBlcnJvciB9ID0gZXJyb3JSZXM7XG4gICAgcmV0dXJuIHRoaXMuaXM0MDEoZXJyb3JSZXMpICYmIGVycm9yLnJlYXNvbiA9PT0gJ1Nlc3Npb25JbnZhbGlkJztcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlU2Vzc2lvbkludmFsaWQoKSB7XG4gICAgdGhpcy5zZXNzaW9uTWFuYWdlLmNvbXBsZXRlKCk7XG4gICAgaWYgKFxuICAgICAgRGF0ZS5ub3coKSAtIHBhcnNlSW50KHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oU0VTU0lPTl9NQU5BR0VfS0VZKSkgPFxuICAgICAgNTAwMFxuICAgICkge1xuICAgICAgc2Vzc2lvblN0b3JhZ2UucmVtb3ZlSXRlbShTRVNTSU9OX01BTkFHRV9LRVkpO1xuICAgICAgbG9nb3V0KHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNlc3Npb25JbnZhbGlkQ29uZmlybSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2Vzc2lvbkludmFsaWRDb25maXJtID0gdHJ1ZTtcbiAgICAvLyBmaXggY2lyY2xlIGRlcGVuZGVuY3kgZXJyb3JcbiAgICBjb25zdCB0cmFuc2xhdGUgPSB0aGlzLmluamVjdG9yLmdldChUcmFuc2xhdGVTZXJ2aWNlKTtcbiAgICBjYXRjaFByb21pc2UoXG4gICAgICB0aGlzLmRpYWxvZy5jb25maXJtKHtcbiAgICAgICAgdGl0bGU6IHRyYW5zbGF0ZS5nZXQoJ3Nlc3Npb25faW52YWxpZF9oaW50JyksXG4gICAgICAgIGNvbmZpcm1UZXh0OiB0cmFuc2xhdGUuZ2V0KCdpX2tub3cnKSxcbiAgICAgICAgY2FuY2VsQnV0dG9uOiBmYWxzZSxcbiAgICAgIH0pLFxuICAgICkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIHRoaXMuc2Vzc2lvbkludmFsaWRDb25maXJtID0gZmFsc2U7XG4gICAgICBsb2dvdXQodHJ1ZSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGlzVW5hdXRob3JpemVkKGVycm9yUmVzOiBIdHRwRXJyb3JSZXNwb25zZSkge1xuICAgIHJldHVybiB0aGlzLmlzNDAxKGVycm9yUmVzKSAmJiBlcnJvclJlcy5lcnJvci5yZWFzb24gPT09ICdVbmF1dGhvcml6ZWQnO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0ludmFsaWRVc2VyKGVycm9yUmVzOiBIdHRwRXJyb3JSZXNwb25zZSkge1xuICAgIHJldHVybiB0aGlzLmlzNDAxKGVycm9yUmVzKSAmJiBlcnJvclJlcy5lcnJvci5yZWFzb24gPT09ICdJbnZhbGlkVXNlcic7XG4gIH1cblxuICBwcml2YXRlIGlzU3RhdHVzKGVycm9yOiBzdHJpbmcgfCBTdGF0dXMpOiBlcnJvciBpcyBTdGF0dXMge1xuICAgIHJldHVybiBlcnJvciAmJiB0eXBlb2YgZXJyb3IgIT09ICdzdHJpbmcnICYmICdjb2RlJyBpbiBlcnJvcjtcbiAgfVxuXG4gIHByaXZhdGUgaXNXYXRjaFJlcShcbiAgICBhcGlBZGRyZXNzOiBzdHJpbmcsXG4gICAgeyB1cmwsIHBhcmFtcyB9OiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgKSB7XG4gICAgY29uc3QgaXNTdGFuZGFyZEFwaSA9XG4gICAgICB1cmwuc3RhcnRzV2l0aChhcGlBZGRyZXNzICsgJy9hcGkvJykgfHxcbiAgICAgIHVybC5zdGFydHNXaXRoKGFwaUFkZHJlc3MgKyAnL2FwaXMvJykgfHxcbiAgICAgIHVybC5zdGFydHNXaXRoKGFwaUFkZHJlc3MgKyAnL2t1YmVybmV0ZXMvJyk7XG4gICAgY29uc3QgaXNXYXRjaE9uID0gcGFyYW1zLmdldCgnd2F0Y2gnKT8udG9Mb3dlckNhc2UoKSA9PT0gJ3RydWUnO1xuICAgIHJldHVybiBpc1N0YW5kYXJkQXBpICYmIGlzV2F0Y2hPbjtcbiAgfVxufVxuIl19