UNPKG

@alauda-fe/common

Version:

Alauda frontend team common codes.

174 lines 27.2 kB
/** * @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