UNPKG

ng-smart-on-fhir

Version:

[![SRDC](https://www.srdc.com.tr/wp-content/uploads/2014/12/srdc-wp.png)](https://srdc.com.tr/en)

195 lines 27.6 kB
import { Inject, Injectable } from '@angular/core'; import * as FHIR from "fhirclient"; import { firstValueFrom, Subject } from "rxjs"; import * as i0 from "@angular/core"; /** * SMART Authentication Service * Handles authentication/authorization using the fhirclient library (or offline via SHC/SHL), and stores the state */ export class SmartAuthService { constructor(config = {}) { this.config = config; // selected login method this.method = 'offline'; // selected client this.selectedClient = undefined; // auth enabled (not public) this.enabled = true; this.SAVED_SESSION_KEY = 'SMART_APPS_SESSION'; this.client$ = new Subject(); this.clientPromise = firstValueFrom(this.client$); this.LAUNCHED_URL = 'SMART_APPS_LAUNCHED_URL'; } isLoggedIn() { return !!this.patient || (this.selectedClient?.scope?.includes('launch/patient') ? false : !!this.user); } /** * Login * @param config - selected client's config * @param patient - selected patient, if applicable */ login(config, patient) { this.method = 'login'; this.selectedClient = config; this.enabled = !config.isPublic; this.patient = patient; this.saveSession(); if (!config.isPublic) { FHIR.oauth2.authorize({ iss: config.iss, redirectUri: config.redirectUri, clientId: config.clientId, scope: config.scope, noRedirect: true }).then(redirectUrl => { const [url, params] = redirectUrl.split('?'); let queryParams = params.split('&'); if (config.aud) { queryParams = queryParams.filter(param => !param.startsWith('aud=')); queryParams.push('aud=' + config.aud); } if (config.promptLogin) { queryParams.push('prompt=login'); } window.location.href = [url, queryParams.join('&')].join('?'); }, console.error); } else if (patient) { this.client$.next(FHIR.client(config.iss)); } } // get public client without authentication publicClient(iss) { return FHIR.client(iss); } // launch with selected issuer launch(iss, launch, clientConfig) { const clientId = this.config.clientId || (this.config.clientIds && this.config.clientIds[iss]); this.method = 'launch'; this.selectedClient = clientConfig; this.enabled = true; this.saveSession({ [this.LAUNCHED_URL]: window.location.href }); FHIR.oauth2.authorize({ clientId, iss, launch, redirectUri: this.config.redirectUrl }); } // start auth flow async start() { const sessionContext = this.restoreSession(); if (sessionContext?.method === 'offline') { this.offline(sessionContext.patient, sessionContext.shc || []); } else if (sessionContext?.selectedClient?.isPublic) { this.client$.next(this.publicClient((sessionContext?.selectedClient).iss)); } else { await FHIR.oauth2.ready().then(async (client) => { this.checkPatientInToken(client); this.user = (await client.user.read().catch(() => undefined)); this.patient = await client.patient.read().catch(() => undefined); this.client$.next(client); }); } return sessionContext; } // offline mode with SHCs offline(patient, shc) { this.patient = patient; this.user = undefined; this.method = 'offline'; this.selectedClient = undefined; this.client$.next(undefined); this.saveSession({ shc }); } // store session in the session storage saveSession(params) { sessionStorage.setItem(this.SAVED_SESSION_KEY, JSON.stringify({ patient: this.patient, user: this.user, method: this.method, selectedClient: this.selectedClient, enabled: this.enabled, ...(params || {}) })); } // restore session from the local storage restoreSession() { const saved = sessionStorage.getItem(this.SAVED_SESSION_KEY); if (saved) { const { patient, user, method, selectedClient, enabled, ...rest } = JSON.parse(saved); this.patient = patient; this.user = user; this.method = method; this.selectedClient = selectedClient; this.enabled = enabled; return { patient, user, method, selectedClient, enabled, ...rest }; } return null; } // if the patient is not received properly from the response, but exists in the token, add it to the response checkPatientInToken(client) { const sessionId = sessionStorage['SMART_KEY'] && JSON.parse(sessionStorage['SMART_KEY']); if (sessionId && sessionStorage[sessionId]) { const session = JSON.parse(sessionStorage[sessionId]); const token = session.tokenResponse?.access_token; const id_token = session.tokenResponse?.id_token; const parsed = JSON.parse(atob(token.split('.')[1])); let changed = false; if (!client.user?.id && id_token) { const parts = id_token.split('.'); const parsedIdToken = JSON.parse(atob(parts[1])); parsedIdToken.fhirUser = 'Practitioner/' + parsedIdToken.sub; session.tokenResponse.id_token = [parts[0], btoa(JSON.stringify(parsedIdToken)), parts[2]].join('.'); changed = true; } if (!client.getPatientId() && parsed.patient) { session.tokenResponse.patient = parsed.patient; changed = true; } if (changed) { sessionStorage[sessionId] = JSON.stringify(session); window.location.reload(); } } } getClient() { return this.clientPromise; } logout() { this.clearSession(); this.getClient().then(client => { const loginClient = this.config?.loginClients?.find(lc => lc.iss === client?.state.serverUrl); if (loginClient?.logoutUri) { window.location.href = loginClient.logoutUri; } else { window.location.href = window.location.href.split('#')[0].replace(/shc$/, 'login'); } }, err => window.location.reload()); } clearSession() { sessionStorage.clear(); this.method = 'offline'; this.patient = this.user = undefined; this.selectedClient = undefined; this.enabled = true; } async getPatient() { if (this.patient) return this.patient; await this.getClient(); return this.patient; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SmartAuthService, deps: [{ token: 'sofConfig' }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SmartAuthService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SmartAuthService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: ['sofConfig'] }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnQtYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc21hcnQtb24tZmhpci9zcmMvbGliL3NlcnZpY2VzL3NtYXJ0LWF1dGguc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsTUFBTSxFQUFFLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUtqRCxPQUFPLEtBQUssSUFBSSxNQUFNLFlBQVksQ0FBQztBQUNuQyxPQUFPLEVBQUMsY0FBYyxFQUFFLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQzs7QUFFN0M7OztHQUdHO0FBRUgsTUFBTSxPQUFPLGdCQUFnQjtJQWtCM0IsWUFBd0MsU0FBNEIsRUFBRTtRQUE5QixXQUFNLEdBQU4sTUFBTSxDQUF3QjtRQWhCdEUsd0JBQXdCO1FBQ2hCLFdBQU0sR0FBK0IsU0FBUyxDQUFDO1FBQ3ZELGtCQUFrQjtRQUNWLG1CQUFjLEdBQW1ELFNBQVMsQ0FBQztRQUNuRiw0QkFBNEI7UUFDcEIsWUFBTyxHQUFHLElBQUksQ0FBQztRQU1mLHNCQUFpQixHQUFXLG9CQUFvQixDQUFDO1FBQ2pELFlBQU8sR0FBRyxJQUFJLE9BQU8sRUFBb0IsQ0FBQTtRQUN6QyxrQkFBYSxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDNUMsaUJBQVksR0FBRyx5QkFBeUIsQ0FBQztJQUdqRCxDQUFDO0lBRUQsVUFBVTtRQUNSLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBcUIsSUFBSSxDQUFDLGNBQWUsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxNQUF5QixF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cmUnO1xyXG5pbXBvcnQge0xvZ2luQ2xpZW50Q29uZmlnfSBmcm9tIFwiLi4vbW9kZWwvbG9naW4tY2xpZW50LmNvbmZpZ1wiO1xyXG5pbXBvcnQge0xhdW5jaENsaWVudENvbmZpZ30gZnJvbSBcIi4uL21vZGVsL2xhdW5jaC1jbGllbnQuY29uZmlnXCI7XHJcbmltcG9ydCB7U21hcnRPbkZoaXJDb25maWd9IGZyb20gXCIuLi9tb2RlbC9zbWFydC1vbi1maGlyLmNvbmZpZ1wiO1xyXG5pbXBvcnQgQ2xpZW50IGZyb20gXCJmaGlyY2xpZW50L2xpYi9DbGllbnRcIjtcclxuaW1wb3J0ICogYXMgRkhJUiBmcm9tIFwiZmhpcmNsaWVudFwiO1xyXG5pbXBvcnQge2ZpcnN0VmFsdWVGcm9tLCBTdWJqZWN0fSBmcm9tIFwicnhqc1wiO1xyXG5cclxuLyoqXHJcbiAqIFNNQVJUIEF1dGhlbnRpY2F0aW9uIFNlcnZpY2VcclxuICogSGFuZGxlcyBhdXRoZW50aWNhdGlvbi9hdXRob3JpemF0aW9uIHVzaW5nIHRoZSBmaGlyY2xpZW50IGxpYnJhcnkgKG9yIG9mZmxpbmUgdmlhIFNIQy9TSEwpLCBhbmQgc3RvcmVzIHRoZSBzdGF0ZVxyXG4gKi9cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgU21hcnRBdXRoU2VydmljZSB7XHJcblxyXG4gIC8vIHNlbGVjdGVkIGxvZ2luIG1ldGhvZFxyXG4gIHByaXZhdGUgbWV0aG9kOiAnb2ZmbGluZSd8J2xvZ2luJ3wnbGF1bmNoJyA9ICdvZmZsaW5lJztcclxuICAvLyBzZWxlY3RlZCBjbGllbnRcclxuICBwcml2YXRlIHNlbGVjdGVkQ2xpZW50OiBMb2dpbkNsaWVudENvbmZpZ3xMYXVuY2hDbGllbnRDb25maWd8dW5kZWZpbmVkID0gdW5kZWZpbmVkO1xyXG4gIC8vIGF1dGggZW5hYmxlZCAobm90IHB1YmxpYylcclxuICBwcml2YXRlIGVuYWJsZWQgPSB0cnVlO1xyXG4gIC8vIGF1dGhlbnRpY2F0ZWQgdXNlclxyXG4gIHByaXZhdGUgdXNlcjogZmhpcjQuUHJhY3RpdGlvbmVyfHVuZGVmaW5lZDtcclxuICAvLyBzZWxlY3RlZC9hdXRoZW50aWNhdGVkIHBhdGllbnRcclxuICBwcml2YXRlIHBhdGllbnQ6IGZoaXI0LlBhdGllbnR8dW5kZWZpbmVkO1xyXG5cclxuICBwcml2YXRlIFNBVkVEX1NFU1NJT05fS0VZOiBzdHJpbmcgPSAnU01BUlRfQVBQU19TRVNTSU9OJztcclxuICBwcml2YXRlIGNsaWVudCQgPSBuZXcgU3ViamVjdDxDbGllbnR8dW5kZWZpbmVkPigpXHJcbiAgcHJpdmF0ZSBjbGllbnRQcm9taXNlID0gZmlyc3RWYWx1ZUZyb20odGhpcy5jbGllbnQkKVxyXG4gIHByaXZhdGUgTEFVTkNIRURfVVJMID0gJ1NNQVJUX0FQUFNfTEFVTkNIRURfVVJMJztcclxuXHJcbiAgY29uc3RydWN0b3IoQEluamVjdCgnc29mQ29uZmlnJykgcHVibGljIGNvbmZpZzogU21hcnRPbkZoaXJDb25maWcgPSB7fSkge1xyXG4gIH1cclxuXHJcbiAgaXNMb2dnZWRJbigpIHtcclxuICAgIHJldHVybiAhIXRoaXMucGF0aWVudCB8fCAoKDxMb2dpbkNsaWVudENvbmZpZz50aGlzLnNlbGVjdGVkQ2xpZW50KT8uc2NvcGU/LmluY2x1ZGVzKCdsYXVuY2gvcGF0aWVudCcpID8gZmFsc2UgOiAhIXRoaXMudXNlcik7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBMb2dpblxyXG4gICAqIEBwYXJhbSBjb25maWcgLSBzZWxlY3RlZCBjbGllbnQncyBjb25maWdcclxuICAgKiBAcGFyYW0gcGF0aWVudCAtIHNlbGVjdGVkIHBhdGllbnQsIGlmIGFwcGxpY2FibGVcclxuICAgKi9cclxuICBsb2dpbihjb25maWc6IExvZ2luQ2xpZW50Q29uZmlnLCBwYXRpZW50PzogZmhpcjQuUGF0aWVudCkge1xyXG4gICAgdGhpcy5tZXRob2QgPSAnbG9naW4nXHJcbiAgICB0aGlzLnNlbGVjdGVkQ2xpZW50ID0gY29uZmlnXHJcbiAgICB0aGlzLmVuYWJsZWQgPSAhY29uZmlnLmlzUHVibGljXHJcbiAgICB0aGlzLnBhdGllbnQgPSBwYXRpZW50O1xyXG4gICAgdGhpcy5zYXZlU2Vzc2lvbigpXHJcbiAgICBpZiAoIWNvbmZpZy5pc1B1YmxpYykge1xyXG4gICAgICBGSElSLm9hdXRoMi5hdXRob3JpemUoe1xyXG4gICAgICAgIGlzczogY29uZmlnLmlzcyxcclxuICAgICAgICByZWRpcmVjdFVyaTogY29uZmlnLnJlZGlyZWN0VXJpLFxyXG4gICAgICAgIGNsaWVudElkOiBjb25maWcuY2xpZW50SWQsXHJcbiAgICAgICAgc2NvcGU6IGNvbmZpZy5zY29wZSxcclxuICAgICAgICBub1JlZGlyZWN0OiB0cnVlXHJcbiAgICAgIH0pLnRoZW4ocmVkaXJlY3RVcmwgPT4ge1xyXG4gICAgICAgIGNvbnN0IFt1cmwsIHBhcmFtc10gPSAoPHN0cmluZz5yZWRpcmVjdFVybCkuc3BsaXQoJz8nKVxyXG4gICAgICAgIGxldCBxdWVyeVBhcmFtcyA9IHBhcmFtcy5zcGxpdCgnJicpXHJcbiAgICAgICAgaWYgKGNvbmZpZy5hdWQpIHtcclxuICAgICAgICAgIHF1ZXJ5UGFyYW1zID0gcXVlcnlQYXJhbXMuZmlsdGVyKHBhcmFtID0+ICFwYXJhbS5zdGFydHNXaXRoKCdhdWQ9JykpXHJcbiAgICAgICAgICBxdWVyeVBhcmFtcy5wdXNoKCdhdWQ9JyArIGNvbmZpZy5hdWQpXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChjb25maWcucHJvbXB0TG9naW4pIHtcclxuICAgICAgICAgIHF1ZXJ5UGFyYW1zLnB1c2goJ3Byb21wdD1sb2dpbicpXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gW3VybCwgcXVlcnlQYXJhbXMuam9pbignJicpXS5qb2luKCc/JylcclxuICAgICAgfSwgY29uc29sZS5lcnJvcilcclxuICAgIH0gZWxzZSBpZihwYXRpZW50KSB7XHJcbiAgICAgIHRoaXMuY2xpZW50JC5uZXh0KEZISVIuY2xpZW50KGNvbmZpZy5pc3MpKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gZ2V0IHB1YmxpYyBjbGllbnQgd2l0aG91dCBhdXRoZW50aWNhdGlvblxyXG4gIHB1YmxpY0NsaWVudChpc3M6IHN0cmluZykge1xyXG4gICAgcmV0dXJuIEZISVIuY2xpZW50KGlzcyk7XHJcbiAgfVxyXG5cclxuICAvLyBsYXVuY2ggd2l0aCBzZWxlY3RlZCBpc3N1ZXJcclxuICBsYXVuY2goaXNzOiBzdHJpbmcsIGxhdW5jaDogc3RyaW5nLCBjbGllbnRDb25maWc/OiBMYXVuY2hDbGllbnRDb25maWcpIHtcclxuICAgIGNvbnN0IGNsaWVudElkID0gdGhpcy5jb25maWcuY2xpZW50SWQgfHwgKHRoaXMuY29uZmlnLmNsaWVudElkcyAmJiB0aGlzLmNvbmZpZy5jbGllbnRJZHNbaXNzXSlcclxuICAgIHRoaXMubWV0aG9kID0gJ2xhdW5jaCdcclxuICAgIHRoaXMuc2VsZWN0ZWRDbGllbnQgPSBjbGllbnRDb25maWdcclxuICAgIHRoaXMuZW5hYmxlZCA9IHRydWVcclxuICAgIHRoaXMuc2F2ZVNlc3Npb24oe1xyXG4gICAgICBbdGhpcy5MQVVOQ0hFRF9VUkxdOiB3aW5kb3cubG9jYXRpb24uaHJlZlxyXG4gICAgfSlcclxuICAgIEZISVIub2F1dGgyLmF1dGhvcml6ZSh7XHJcbiAgICAgIGNsaWVudElkLCBpc3MsIGxhdW5jaCxcclxuICAgICAgcmVkaXJlY3RVcmk6IHRoaXMuY29uZmlnLnJlZGlyZWN0VXJsXHJcbiAgICB9KVxyXG4gIH1cclxuXHJcbiAgLy8gc3RhcnQgYXV0aCBmbG93XHJcbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGNvbnN0IHNlc3Npb25Db250ZXh0ID0gdGhpcy5yZXN0b3JlU2Vzc2lvbigpXHJcbiAgICBpZiAoc2Vzc2lvbkNvbnRleHQ/Lm1ldGhvZCA9PT0gJ29mZmxpbmUnKSB7XHJcbiAgICAgIHRoaXMub2ZmbGluZShzZXNzaW9uQ29udGV4dC5wYXRpZW50LCBzZXNzaW9uQ29udGV4dC5zaGMgfHwgW10pXHJcbiAgICB9IGVsc2UgaWYgKCg8TG9naW5DbGllbnRDb25maWc+c2Vzc2lvbkNvbnRleHQ/LnNlbGVjdGVkQ2xpZW50KT8uaXNQdWJsaWMpIHtcclxuICAgICAgdGhpcy5jbGllbnQkLm5leHQodGhpcy5wdWJsaWNDbGllbnQoKDxMb2dpbkNsaWVudENvbmZpZz5zZXNzaW9uQ29udGV4dD8uc2VsZWN0ZWRDbGllbnQpLmlzcykpXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBhd2FpdCBGSElSLm9hdXRoMi5yZWFkeSgpLnRoZW4oYXN5bmMgY2xpZW50ID0+IHtcclxuICAgICAgICB0aGlzLmNoZWNrUGF0aWVudEluVG9rZW4oY2xpZW50KVxyXG4gICAgICAgIHRoaXMudXNlciA9IDxmaGlyNC5QcmFjdGl0aW9uZXJ8dW5kZWZpbmVkPihhd2FpdCBjbGllbnQudXNlci5yZWFkKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKSlcclxuICAgICAgICB0aGlzLnBhdGllbnQgPSBhd2FpdCBjbGllbnQucGF0aWVudC5yZWFkKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKVxyXG4gICAgICAgIHRoaXMuY2xpZW50JC5uZXh0KGNsaWVudCk7XHJcbiAgICAgIH0pXHJcbiAgICB9XHJcbiAgICByZXR1cm4gc2Vzc2lvbkNvbnRleHQ7XHJcbiAgfVxyXG5cclxuICAvLyBvZmZsaW5lIG1vZGUgd2l0aCBTSENzXHJcbiAgb2ZmbGluZShwYXRpZW50OiBmaGlyNC5QYXRpZW50LCBzaGM6IHN0cmluZ1tdKSB7XHJcbiAgICB0aGlzLnBhdGllbnQgPSBwYXRpZW50O1xyXG4gICAgdGhpcy51c2VyID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5tZXRob2QgPSAnb2ZmbGluZSc7XHJcbiAgICB0aGlzLnNlbGVjdGVkQ2xpZW50ID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5jbGllbnQkLm5leHQodW5kZWZpbmVkKVxyXG4gICAgdGhpcy5zYXZlU2Vzc2lvbih7c2hjfSk7XHJcbiAgfVxyXG5cclxuICAvLyBzdG9yZSBzZXNzaW9uIGluIHRoZSBzZXNzaW9uIHN0b3JhZ2VcclxuICBzYXZlU2Vzc2lvbihwYXJhbXM/OiBPYmplY3QpIHtcclxuICAgIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0odGhpcy5TQVZFRF9TRVNTSU9OX0tFWSwgSlNPTi5zdHJpbmdpZnkoe1xyXG4gICAgICBwYXRpZW50OiB0aGlzLnBhdGllbnQsXHJcbiAgICAgIHVzZXI6IHRoaXMudXNlcixcclxuICAgICAgbWV0aG9kOiB0aGlzLm1ldGhvZCxcclxuICAgICAgc2VsZWN0ZWRDbGllbnQ6IHRoaXMuc2VsZWN0ZWRDbGllbnQsXHJcbiAgICAgIGVuYWJsZWQ6IHRoaXMuZW5hYmxlZCxcclxuICAgICAgLi4uKHBhcmFtcyB8fCB7fSlcclxuICAgIH0pKVxyXG4gIH1cclxuXHJcbiAgLy8gcmVzdG9yZSBzZXNzaW9uIGZyb20gdGhlIGxvY2FsIHN0b3JhZ2VcclxuICByZXN0b3JlU2Vzc2lvbigpIHtcclxuICAgIGNvbnN0IHNhdmVkID0gc2Vzc2lvblN0b3JhZ2UuZ2V0SXRlbSh0aGlzLlNBVkVEX1NFU1NJT05fS0VZKTtcclxuICAgIGlmIChzYXZlZCkge1xyXG4gICAgICBjb25zdCB7IHBhdGllbnQsIHVzZXIsIG1ldGhvZCwgc2VsZWN0ZWRDbGllbnQsIGVuYWJsZWQsIC4uLnJlc3QgfSA9IEpTT04ucGFyc2Uoc2F2ZWQpO1xyXG4gICAgICB0aGlzLnBhdGllbnQgPSBwYXRpZW50O1xyXG4gICAgICB0aGlzLnVzZXIgPSB1c2VyO1xyXG4gICAgICB0aGlzLm1ldGhvZCA9IG1ldGhvZDtcclxuICAgICAgdGhpcy5zZWxlY3RlZENsaWVudCA9IHNlbGVjdGVkQ2xpZW50O1xyXG4gICAgICB0aGlzLmVuYWJsZWQgPSBlbmFibGVkO1xyXG4gICAgICByZXR1cm4geyBwYXRpZW50LCB1c2VyLCBtZXRob2QsIHNlbGVjdGVkQ2xpZW50LCBlbmFibGVkLCAuLi5yZXN0IH07XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8vIGlmIHRoZSBwYXRpZW50IGlzIG5vdCByZWNlaXZlZCBwcm9wZXJseSBmcm9tIHRoZSByZXNwb25zZSwgYnV0IGV4aXN0cyBpbiB0aGUgdG9rZW4sIGFkZCBpdCB0byB0aGUgcmVzcG9uc2VcclxuICBwcml2YXRlIGNoZWNrUGF0aWVudEluVG9rZW4oY2xpZW50OiBDbGllbnQpIHtcclxuICAgIGNvbnN0IHNlc3Npb25JZCA9IHNlc3Npb25TdG9yYWdlWydTTUFSVF9LRVknXSAgJiYgSlNPTi5wYXJzZShzZXNzaW9uU3RvcmFnZVsnU01BUlRfS0VZJ10pXHJcbiAgICBpZiAoc2Vzc2lvbklkICYmIHNlc3Npb25TdG9yYWdlW3Nlc3Npb25JZF0pIHtcclxuICAgICAgY29uc3Qgc2Vzc2lvbiA9IEpTT04ucGFyc2Uoc2Vzc2lvblN0b3JhZ2Vbc2Vzc2lvbklkXSlcclxuICAgICAgY29uc3QgdG9rZW4gPSBzZXNzaW9uLnRva2VuUmVzcG9uc2U/LmFjY2Vzc190b2tlblxyXG4gICAgICBjb25zdCBpZF90b2tlbiA9IHNlc3Npb24udG9rZW5SZXNwb25zZT8uaWRfdG9rZW5cclxuICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShhdG9iKHRva2VuLnNwbGl0KCcuJylbMV0pKVxyXG4gICAgICBsZXQgY2hhbmdlZCA9IGZhbHNlO1xyXG4gICAgICBpZiAoIWNsaWVudC51c2VyPy5pZCAmJiBpZF90b2tlbikge1xyXG4gICAgICAgIGNvbnN0IHBhcnRzID0gaWRfdG9rZW4uc3BsaXQoJy4nKVxyXG4gICAgICAgIGNvbnN0IHBhcnNlZElkVG9rZW4gPSBKU09OLnBhcnNlKGF0b2IocGFydHNbMV0pKVxyXG4gICAgICAgIHBhcnNlZElkVG9rZW4uZmhpclVzZXIgPSAnUHJhY3RpdGlvbmVyLycgKyBwYXJzZWRJZFRva2VuLnN1YjtcclxuICAgICAgICBzZXNzaW9uLnRva2VuUmVzcG9uc2UuaWRfdG9rZW4gPSBbcGFydHNbMF0sIGJ0b2EoSlNPTi5zdHJpbmdpZnkocGFyc2VkSWRUb2tlbikpLCBwYXJ0c1syXV0uam9pbignLicpO1xyXG4gICAgICAgIGNoYW5nZWQgPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICghY2xpZW50LmdldFBhdGllbnRJZCgpICYmIHBhcnNlZC5wYXRpZW50KSB7XHJcbiAgICAgICAgc2Vzc2lvbi50b2tlblJlc3BvbnNlLnBhdGllbnQgPSBwYXJzZWQucGF0aWVudFxyXG4gICAgICAgIGNoYW5nZWQgPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChjaGFuZ2VkKSB7XHJcbiAgICAgICAgc2Vzc2lvblN0b3JhZ2Vbc2Vzc2lvbklkXSA9IEpTT04uc3RyaW5naWZ5KHNlc3Npb24pXHJcbiAgICAgICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldENsaWVudCgpIHtcclxuICAgIHJldHVybiB0aGlzLmNsaWVudFByb21pc2U7XHJcbiAgfVxyXG5cclxuICBsb2dvdXQoKSB7XHJcbiAgICB0aGlzLmNsZWFyU2Vzc2lvbigpO1xyXG4gICAgdGhpcy5nZXRDbGllbnQoKS50aGVuKGNsaWVudCA9PiB7XHJcbiAgICAgIGNvbnN0IGxvZ2luQ2xpZW50ID0gdGhpcy5jb25maWc/LmxvZ2luQ2xpZW50cz8uZmluZChsYyA9PiBsYy5pc3MgPT09IGNsaWVudD8uc3RhdGUuc2VydmVyVXJsKTtcclxuICAgICAgaWYgKCg8YW55PmxvZ2luQ2xpZW50KT8ubG9nb3V0VXJpKSB7XHJcbiAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSAoPGFueT5sb2dpbkNsaWVudCkubG9nb3V0VXJpXHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSB3aW5kb3cubG9jYXRpb24uaHJlZi5zcGxpdCgnIycpWzBdLnJlcGxhY2UoL3NoYyQvLCAnbG9naW4nKVxyXG4gICAgICB9XHJcbiAgICB9LCBlcnIgPT4gd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjbGVhclNlc3Npb24oKSB7XHJcbiAgICBzZXNzaW9uU3RvcmFnZS5jbGVhcigpXHJcbiAgICB0aGlzLm1ldGhvZCA9ICdvZmZsaW5lJztcclxuICAgIHRoaXMucGF0aWVudCA9IHRoaXMudXNlciA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuc2VsZWN0ZWRDbGllbnQgPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLmVuYWJsZWQgPSB0cnVlO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZ2V0UGF0aWVudCgpIHtcclxuICAgIGlmICh0aGlzLnBhdGllbnQpIHJldHVybiB0aGlzLnBhdGllbnQ7XHJcbiAgICBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xyXG4gICAgcmV0dXJuIHRoaXMucGF0aWVudDtcclxuICB9XHJcbn1cclxuIl19