UNPKG

@kephas/ngx-oidc

Version:

Provides the integration of the OIDC API with Kephas and Angular 12+.

222 lines 30.4 kB
import { Injectable } from '@angular/core'; import { UserManager, } from 'oidc-client'; import { BehaviorSubject, concat, from } from 'rxjs'; import { filter, map, mergeMap, take, tap } from 'rxjs/operators'; import { AuthenticationSettingsProvider } from './authentication.settings'; import * as i0 from "@angular/core"; import * as i1 from "./authentication.settings"; export var AuthenticationResultStatus; (function (AuthenticationResultStatus) { AuthenticationResultStatus[AuthenticationResultStatus["Success"] = 0] = "Success"; AuthenticationResultStatus[AuthenticationResultStatus["Redirect"] = 1] = "Redirect"; AuthenticationResultStatus[AuthenticationResultStatus["Fail"] = 2] = "Fail"; })(AuthenticationResultStatus || (AuthenticationResultStatus = {})); export class AuthenticationService { /** * Creates an instance of AuthorizeService. * @param {AuthenticationSettingsProvider} settingsProvider The settings provider. * @memberof AuthorizeService */ constructor(settingsProvider) { this.settingsProvider = settingsProvider; this.userSubject = new BehaviorSubject(null); this.rawUserSubject = new BehaviorSubject(null); } /** * Gets the time of user's last activity. * * @readonly * @type {(Date | undefined)} * @memberof AuthorizeService */ get lastActivityTime() { return this._lastActivityTime; } /** * Gets an observable indicating whether the user is authenticated. * * @return {*} {Observable<boolean>} * @memberof AuthorizeService */ isAuthenticated() { return this.getUser().pipe(map(u => !!u)); } /** * Gets an observable retrieving the user. * * @return {*} {(Observable<IUser | null | undefined>)} * @memberof AuthorizeService */ getUser() { return concat(this.userSubject.pipe(take(1), filter(u => !!u)), this.getUserFromStorage().pipe(filter(u => !!u), tap(u => this.setUser(u)), map(u => u?.profile)), this.userSubject.asObservable()); } /** * Gets an observable containing the access token of the signed-in user. * * @return {*} {(Observable<string | undefined>)} * @memberof AuthorizeService */ getAccessToken() { return from(this.ensureUserManagerInitialized()) .pipe(mergeMap(() => from(this.userManager.getUser())), map(user => user?.access_token)); } /** * Notifies the authorization service that the user is active. * * @memberof AuthorizeService */ touch() { this._lastActivityTime = new Date(); } /** * Sign in the user. * We try to authenticate the user in three different ways: * 1) We try to see if we can authenticate the user silently. This happens * when the user is already logged in on the IdP and is done using a hidden iframe * on the client. * 2) We try to authenticate the user using a PopUp Window. This might fail if there is a * Pop-Up blocker or the user has disabled PopUps. * 3) If the two methods above fail, we redirect the browser to the IdP to perform a traditional * redirect flow. * * @param {*} state * @return {*} {Promise<IAuthenticationResult>} * @memberof AuthorizeService */ async signIn(state) { await this.ensureUserManagerInitialized(); let user = null; try { user = await this.userManager.signinSilent(this.createArguments()); this.setUser(user); return this.success(state); } catch (silentError) { // User might not be authenticated, fallback to popup authentication console.log('Silent authentication error: ', silentError); const popUpDisabled = this.settingsProvider.settings.popUpDisabled; try { this.ensurePopupEnabled(); user = await this.userManager.signinPopup(this.createArguments()); this.setUser(user); return this.success(state); } catch (popupError) { if (popupError.message === 'Popup window closed') { // The user explicitly cancelled the login action by closing an opened popup. return this.error('The user closed the window.'); } else if (!popUpDisabled) { console.log('Popup authentication error: ', popupError); } // PopUps might be blocked by the user, fallback to redirect try { await this.userManager.signinRedirect(this.createArguments(state)); return this.redirect(); } catch (redirectError) { console.log('Redirect authentication error: ', redirectError); return this.error(redirectError); } } } } async completeSignIn(url) { try { await this.ensureUserManagerInitialized(); const user = await this.userManager.signinCallback(url); this.setUser(user); return this.success(user?.state); } catch (error) { console.log('There was an error signing in: ', error); return this.error('There was an error signing in.'); } } async signOut(state) { try { this.ensurePopupEnabled(); await this.ensureUserManagerInitialized(); await this.userManager.signoutPopup(this.createArguments()); this.setUser(null); return this.success(state); } catch (popupSignOutError) { console.log('Popup signout error: ', popupSignOutError); try { await this.userManager.signoutRedirect(this.createArguments(state)); return this.redirect(); } catch (redirectSignOutError) { console.log('Redirect signout error: ', popupSignOutError); return this.error(redirectSignOutError); } } } async completeSignOut(url) { await this.ensureUserManagerInitialized(); try { const response = await this.userManager.signoutCallback(url); this.setUser(null); return this.success(response && response.state); } catch (error) { console.log(`There was an error trying to log out '${error}'.`); return this.error(error); } } async ensureUserManagerInitialized() { if (this.userManager !== undefined) { return; } const authSettings = this.settingsProvider.settings; const response = await fetch(authSettings.applicationPaths.ApiAuthorizationClientConfigurationUrl); if (!response.ok) { throw new Error(`Could not load settings for '${authSettings.identityAppId}'`); } const settings = await response.json(); settings.automaticSilentRenew = true; settings.includeIdTokenInSilentRenew = true; this.userManager = new UserManager(settings); this.userManager.events.addUserSignedOut(async () => { await this.userManager.removeUser(); this.setUser(null); }); } ensurePopupEnabled() { if (this.settingsProvider.settings.popUpDisabled) { throw new Error('Popup disabled. Instruct the AuthorizationSettingsProvider service to return false in \'settings.popupDisabled\' to enable it.'); } } createArguments(state) { return { useReplaceToNavigate: true, data: state }; } error(message) { return { status: AuthenticationResultStatus.Fail, message }; } success(state) { return { status: AuthenticationResultStatus.Success, state }; } redirect() { return { status: AuthenticationResultStatus.Redirect }; } getUserFromStorage() { return from(this.ensureUserManagerInitialized()) .pipe(mergeMap(() => this.userManager.getUser())); } setUser(user) { const currentUser = this.rawUserSubject.value; // make sure not to issue a change if the user is not really changed. if (currentUser == user || currentUser?.id_token == user?.id_token) { return; } this.rawUserSubject.next(user); this.userSubject.next(user?.profile || null); } } AuthenticationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AuthenticationService, deps: [{ token: i1.AuthenticationSettingsProvider }], target: i0.ɵɵFactoryTarget.Injectable }); AuthenticationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AuthenticationService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: AuthenticationService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i1.AuthenticationSettingsProvider }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aGVudGljYXRpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2tlcGhhcy9uZ3gtb2lkYy9zcmMvbGliL2F1dGhlbnRpY2F0aW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBQWlCLFdBQVcsR0FBRyxNQUFNLGFBQWEsQ0FBQztBQUMxRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQWMsTUFBTSxNQUFNLENBQUM7QUFDakUsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQzs7O0FBcUIzRSxNQUFNLENBQU4sSUFBWSwwQkFJWDtBQUpELFdBQVksMEJBQTBCO0lBQ3BDLGlGQUFPLENBQUE7SUFDUCxtRkFBUSxDQUFBO0lBQ1IsMkVBQUksQ0FBQTtBQUNOLENBQUMsRUFKVywwQkFBMEIsS0FBMUIsMEJBQTBCLFFBSXJDO0FBT0QsTUFBTSxPQUFPLHFCQUFxQjtJQUdoQzs7OztPQUlHO0lBQ0gsWUFBK0IsZ0JBQWdEO1FBQWhELHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBZ0M7UUFJNUQsZ0JBQVcsR0FBa0MsSUFBSSxlQUFlLENBQUMsSUFBb0IsQ0FBQyxDQUFDO1FBQ3ZGLG1CQUFjLEdBQWlDLElBQUksZUFBZSxDQUFDLElBQW1CLENBQUMsQ0FBQztJQUozRyxDQUFDO0lBTUQ7Ozs7OztPQU1HO0lBQ0gsSUFBVyxnQkFBZ0I7UUFDekIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUM7SUFDaEMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksZUFBZTtRQUNwQixPQUFPLElBQUksQ0FBQyxP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LDBCQUEwQixDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUMvRCxDQUFDO0lBRU8sUUFBUTtRQUNkLE9BQU8sRUFBRSxNQUFNLEVBQUUsMEJBQTBCLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDekQsQ0FBQztJQUVPLGtCQUFrQjtRQUN4QixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsNEJBQTRCLEVBQUUsQ0FBQzthQUM3QyxJQUFJLENBQ0gsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFZLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25ELENBQUM7SUFFTyxPQUFPLENBQUMsSUFBaUI7UUFDL0IsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUM7UUFFOUMscUVBQXFFO1FBQ3JFLElBQUksV0FBVyxJQUFJLElBQUksSUFBSSxXQUFXLEVBQUUsUUFBUSxJQUFJLElBQUksRUFBRSxRQUFRLEVBQUU7WUFDbEUsT0FBTztTQUNSO1FBRUQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQztJQUMvQyxDQUFDOztrSEFuT1UscUJBQXFCO3NIQUFyQixxQkFBcUI7MkZBQXJCLHFCQUFxQjtrQkFEakMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQXBwU2VydmljZSwgU2luZ2xldG9uQXBwU2VydmljZUNvbnRyYWN0IH0gZnJvbSAnQGtlcGhhcy9jb3JlJztcclxuaW1wb3J0IHsgUHJvZmlsZSwgVXNlciwgVXNlck1hbmFnZXIsIH0gZnJvbSAnb2lkYy1jbGllbnQnO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGNvbmNhdCwgZnJvbSwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBmaWx0ZXIsIG1hcCwgbWVyZ2VNYXAsIHRha2UsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgQXV0aGVudGljYXRpb25TZXR0aW5nc1Byb3ZpZGVyIH0gZnJvbSAnLi9hdXRoZW50aWNhdGlvbi5zZXR0aW5ncyc7XHJcblxyXG5leHBvcnQgdHlwZSBJQXV0aGVudGljYXRpb25SZXN1bHQgPVxyXG4gIFN1Y2Nlc3NBdXRoZW50aWNhdGlvblJlc3VsdCB8XHJcbiAgRmFpbHVyZUF1dGhlbnRpY2F0aW9uUmVzdWx0IHxcclxuICBSZWRpcmVjdEF1dGhlbnRpY2F0aW9uUmVzdWx0O1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBTdWNjZXNzQXV0aGVudGljYXRpb25SZXN1bHQge1xyXG4gIHN0YXR1czogQXV0aGVudGljYXRpb25SZXN1bHRTdGF0dXMuU3VjY2VzcztcclxuICBzdGF0ZTogYW55O1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEZhaWx1cmVBdXRoZW50aWNhdGlvblJlc3VsdCB7XHJcbiAgc3RhdHVzOiBBdXRoZW50aWNhdGlvblJlc3VsdFN0YXR1cy5GYWlsO1xyXG4gIG1lc3NhZ2U6IHN0cmluZyB8IEVycm9yO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFJlZGlyZWN0QXV0aGVudGljYXRpb25SZXN1bHQge1xyXG4gIHN0YXR1czogQXV0aGVudGljYXRpb25SZXN1bHRTdGF0dXMuUmVkaXJlY3Q7XHJcbn1cclxuXHJcbmV4cG9ydCBlbnVtIEF1dGhlbnRpY2F0aW9uUmVzdWx0U3RhdHVzIHtcclxuICBTdWNjZXNzLFxyXG4gIFJlZGlyZWN0LFxyXG4gIEZhaWxcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBJVXNlciBleHRlbmRzIFByb2ZpbGUge1xyXG4gIG5hbWU/OiBzdHJpbmc7XHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIEF1dGhlbnRpY2F0aW9uU2VydmljZSB7XHJcbiAgcHJpdmF0ZSBfbGFzdEFjdGl2aXR5VGltZT86IERhdGU7XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgQXV0aG9yaXplU2VydmljZS5cclxuICAgKiBAcGFyYW0ge0F1dGhlbnRpY2F0aW9uU2V0dGluZ3NQcm92aWRlcn0gc2V0dGluZ3NQcm92aWRlciBUaGUgc2V0dGluZ3MgcHJvdmlkZXIuXHJcbiAgICogQG1lbWJlcm9mIEF1dGhvcml6ZVNlcnZpY2VcclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgcmVhZG9ubHkgc2V0dGluZ3NQcm92aWRlcjogQXV0aGVudGljYXRpb25TZXR0aW5nc1Byb3ZpZGVyKSB7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgdXNlck1hbmFnZXI/OiBVc2VyTWFuYWdlcjtcclxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgdXNlclN1YmplY3Q6IEJlaGF2aW9yU3ViamVjdDxJVXNlciB8IG51bGw+ID0gbmV3IEJlaGF2aW9yU3ViamVjdChudWxsIGFzIElVc2VyIHwgbnVsbCk7XHJcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJhd1VzZXJTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8VXNlciB8IG51bGw+ID0gbmV3IEJlaGF2aW9yU3ViamVjdChudWxsIGFzIFVzZXIgfCBudWxsKTtcclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgdGltZSBvZiB1c2VyJ3MgbGFzdCBhY3Rpdml0eS5cclxuICAgKlxyXG4gICAqIEByZWFkb25seVxyXG4gICAqIEB0eXBlIHsoRGF0ZSB8IHVuZGVmaW5lZCl9XHJcbiAgICogQG1lbWJlcm9mIEF1dGhvcml6ZVNlcnZpY2VcclxuICAgKi9cclxuICBwdWJsaWMgZ2V0IGxhc3RBY3Rpdml0eVRpbWUoKTogRGF0ZSB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy5fbGFzdEFjdGl2aXR5VGltZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgYW4gb2JzZXJ2YWJsZSBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIHVzZXIgaXMgYXV0aGVudGljYXRlZC5cclxuICAgKlxyXG4gICAqIEByZXR1cm4geyp9ICB7T2JzZXJ2YWJsZTxib29sZWFuPn1cclxuICAgKiBAbWVtYmVyb2YgQXV0aG9yaXplU2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBpc0F1dGhlbnRpY2F0ZWQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XHJcbiAgICByZXR1cm4gdGhpcy5nZXRVc2VyKCkucGlwZShtYXAodSA9PiAhIXUpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgYW4gb2JzZXJ2YWJsZSByZXRyaWV2aW5nIHRoZSB1c2VyLlxyXG4gICAqXHJcbiAgICogQHJldHVybiB7Kn0gIHsoT2JzZXJ2YWJsZTxJVXNlciB8IG51bGwgfCB1bmRlZmluZWQ+KX1cclxuICAgKiBAbWVtYmVyb2YgQXV0aG9yaXplU2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXRVc2VyKCk6IE9ic2VydmFibGU8SVVzZXIgfCBudWxsIHwgdW5kZWZpbmVkPiB7XHJcbiAgICByZXR1cm4gY29uY2F0KFxyXG4gICAgICB0aGlzLnVzZXJTdWJqZWN0LnBpcGUodGFrZSgxKSwgZmlsdGVyKHUgPT4gISF1KSksXHJcbiAgICAgIHRoaXMuZ2V0VXNlckZyb21TdG9yYWdlKCkucGlwZShmaWx0ZXIodSA9PiAhIXUpLCB0YXAodSA9PiB0aGlzLnNldFVzZXIodSEpKSwgbWFwKHUgPT4gdT8ucHJvZmlsZSkpLFxyXG4gICAgICB0aGlzLnVzZXJTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgYW4gb2JzZXJ2YWJsZSBjb250YWluaW5nIHRoZSBhY2Nlc3MgdG9rZW4gb2YgdGhlIHNpZ25lZC1pbiB1c2VyLlxyXG4gICAqXHJcbiAgICogQHJldHVybiB7Kn0gIHsoT2JzZXJ2YWJsZTxzdHJpbmcgfCB1bmRlZmluZWQ+KX1cclxuICAgKiBAbWVtYmVyb2YgQXV0aG9yaXplU2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXRBY2Nlc3NUb2tlbigpOiBPYnNlcnZhYmxlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xyXG4gICAgcmV0dXJuIGZyb20odGhpcy5lbnN1cmVVc2VyTWFuYWdlckluaXRpYWxpemVkKCkpXHJcbiAgICAgIC5waXBlKG1lcmdlTWFwKCgpID0+IGZyb20odGhpcy51c2VyTWFuYWdlciEuZ2V0VXNlcigpKSksXHJcbiAgICAgICAgbWFwKHVzZXIgPT4gdXNlcj8uYWNjZXNzX3Rva2VuKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBOb3RpZmllcyB0aGUgYXV0aG9yaXphdGlvbiBzZXJ2aWNlIHRoYXQgdGhlIHVzZXIgaXMgYWN0aXZlLlxyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIEF1dGhvcml6ZVNlcnZpY2VcclxuICAgKi9cclxuICBwdWJsaWMgdG91Y2goKSB7XHJcbiAgICB0aGlzLl9sYXN0QWN0aXZpdHlUaW1lID0gbmV3IERhdGUoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNpZ24gaW4gdGhlIHVzZXIuXHJcbiAgICogV2UgdHJ5IHRvIGF1dGhlbnRpY2F0ZSB0aGUgdXNlciBpbiB0aHJlZSBkaWZmZXJlbnQgd2F5czpcclxuICAgKiAxKSBXZSB0cnkgdG8gc2VlIGlmIHdlIGNhbiBhdXRoZW50aWNhdGUgdGhlIHVzZXIgc2lsZW50bHkuIFRoaXMgaGFwcGVuc1xyXG4gICAqICAgIHdoZW4gdGhlIHVzZXIgaXMgYWxyZWFkeSBsb2dnZWQgaW4gb24gdGhlIElkUCBhbmQgaXMgZG9uZSB1c2luZyBhIGhpZGRlbiBpZnJhbWVcclxuICAgKiAgICBvbiB0aGUgY2xpZW50LlxyXG4gICAqIDIpIFdlIHRyeSB0byBhdXRoZW50aWNhdGUgdGhlIHVzZXIgdXNpbmcgYSBQb3BVcCBXaW5kb3cuIFRoaXMgbWlnaHQgZmFpbCBpZiB0aGVyZSBpcyBhXHJcbiAgICogICAgUG9wLVVwIGJsb2NrZXIgb3IgdGhlIHVzZXIgaGFzIGRpc2FibGVkIFBvcFVwcy5cclxuICAgKiAzKSBJZiB0aGUgdHdvIG1ldGhvZHMgYWJvdmUgZmFpbCwgd2UgcmVkaXJlY3QgdGhlIGJyb3dzZXIgdG8gdGhlIElkUCB0byBwZXJmb3JtIGEgdHJhZGl0aW9uYWxcclxuICAgKiAgICByZWRpcmVjdCBmbG93LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHsqfSBzdGF0ZVxyXG4gICAqIEByZXR1cm4geyp9ICB7UHJvbWlzZTxJQXV0aGVudGljYXRpb25SZXN1bHQ+fVxyXG4gICAqIEBtZW1iZXJvZiBBdXRob3JpemVTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIHNpZ25JbihzdGF0ZTogYW55KTogUHJvbWlzZTxJQXV0aGVudGljYXRpb25SZXN1bHQ+IHtcclxuICAgIGF3YWl0IHRoaXMuZW5zdXJlVXNlck1hbmFnZXJJbml0aWFsaXplZCgpO1xyXG4gICAgbGV0IHVzZXI6IFVzZXIgfCBudWxsID0gbnVsbDtcclxuICAgIHRyeSB7XHJcbiAgICAgIHVzZXIgPSBhd2FpdCB0aGlzLnVzZXJNYW5hZ2VyIS5zaWduaW5TaWxlbnQodGhpcy5jcmVhdGVBcmd1bWVudHMoKSk7XHJcbiAgICAgIHRoaXMuc2V0VXNlcih1c2VyKTtcclxuICAgICAgcmV0dXJuIHRoaXMuc3VjY2VzcyhzdGF0ZSk7XHJcbiAgICB9IGNhdGNoIChzaWxlbnRFcnJvcikge1xyXG4gICAgICAvLyBVc2VyIG1pZ2h0IG5vdCBiZSBhdXRoZW50aWNhdGVkLCBmYWxsYmFjayB0byBwb3B1cCBhdXRoZW50aWNhdGlvblxyXG4gICAgICBjb25zb2xlLmxvZygnU2lsZW50IGF1dGhlbnRpY2F0aW9uIGVycm9yOiAnLCBzaWxlbnRFcnJvcik7XHJcblxyXG4gICAgICBjb25zdCBwb3BVcERpc2FibGVkID0gdGhpcy5zZXR0aW5nc1Byb3ZpZGVyLnNldHRpbmdzLnBvcFVwRGlzYWJsZWQ7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgdGhpcy5lbnN1cmVQb3B1cEVuYWJsZWQoKTtcclxuXHJcbiAgICAgICAgdXNlciA9IGF3YWl0IHRoaXMudXNlck1hbmFnZXIhLnNpZ25pblBvcHVwKHRoaXMuY3JlYXRlQXJndW1lbnRzKCkpO1xyXG4gICAgICAgIHRoaXMuc2V0VXNlcih1c2VyKTtcclxuICAgICAgICByZXR1cm4gdGhpcy5zdWNjZXNzKHN0YXRlKTtcclxuICAgICAgfSBjYXRjaCAocG9wdXBFcnJvcikge1xyXG4gICAgICAgIGlmICgocG9wdXBFcnJvciBhcyBFcnJvcikubWVzc2FnZSA9PT0gJ1BvcHVwIHdpbmRvdyBjbG9zZWQnKSB7XHJcbiAgICAgICAgICAvLyBUaGUgdXNlciBleHBsaWNpdGx5IGNhbmNlbGxlZCB0aGUgbG9naW4gYWN0aW9uIGJ5IGNsb3NpbmcgYW4gb3BlbmVkIHBvcHVwLlxyXG4gICAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3IoJ1RoZSB1c2VyIGNsb3NlZCB0aGUgd2luZG93LicpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoIXBvcFVwRGlzYWJsZWQpIHtcclxuICAgICAgICAgIGNvbnNvbGUubG9nKCdQb3B1cCBhdXRoZW50aWNhdGlvbiBlcnJvcjogJywgcG9wdXBFcnJvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBQb3BVcHMgbWlnaHQgYmUgYmxvY2tlZCBieSB0aGUgdXNlciwgZmFsbGJhY2sgdG8gcmVkaXJlY3RcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgYXdhaXQgdGhpcy51c2VyTWFuYWdlciEuc2lnbmluUmVkaXJlY3QodGhpcy5jcmVhdGVBcmd1bWVudHMoc3RhdGUpKTtcclxuICAgICAgICAgIHJldHVybiB0aGlzLnJlZGlyZWN0KCk7XHJcbiAgICAgICAgfSBjYXRjaCAocmVkaXJlY3RFcnJvcikge1xyXG4gICAgICAgICAgY29uc29sZS5sb2coJ1JlZGlyZWN0IGF1dGhlbnRpY2F0aW9uIGVycm9yOiAnLCByZWRpcmVjdEVycm9yKTtcclxuICAgICAgICAgIHJldHVybiB0aGlzLmVycm9yKHJlZGlyZWN0RXJyb3IgYXMgRXJyb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGNvbXBsZXRlU2lnbkluKHVybDogc3RyaW5nKTogUHJvbWlzZTxJQXV0aGVudGljYXRpb25SZXN1bHQ+IHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlVXNlck1hbmFnZXJJbml0aWFsaXplZCgpO1xyXG4gICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy51c2VyTWFuYWdlciEuc2lnbmluQ2FsbGJhY2sodXJsKTtcclxuICAgICAgdGhpcy5zZXRVc2VyKHVzZXIpO1xyXG4gICAgICByZXR1cm4gdGhpcy5zdWNjZXNzKHVzZXI/LnN0YXRlKTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGNvbnNvbGUubG9nKCdUaGVyZSB3YXMgYW4gZXJyb3Igc2lnbmluZyBpbjogJywgZXJyb3IpO1xyXG4gICAgICByZXR1cm4gdGhpcy5lcnJvcignVGhlcmUgd2FzIGFuIGVycm9yIHNpZ25pbmcgaW4uJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgc2lnbk91dChzdGF0ZTogYW55KTogUHJvbWlzZTxJQXV0aGVudGljYXRpb25SZXN1bHQ+IHtcclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMuZW5zdXJlUG9wdXBFbmFibGVkKCk7XHJcblxyXG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZVVzZXJNYW5hZ2VySW5pdGlhbGl6ZWQoKTtcclxuICAgICAgYXdhaXQgdGhpcy51c2VyTWFuYWdlciEuc2lnbm91dFBvcHVwKHRoaXMuY3JlYXRlQXJndW1lbnRzKCkpO1xyXG4gICAgICB0aGlzLnNldFVzZXIobnVsbCk7XHJcbiAgICAgIHJldHVybiB0aGlzLnN1Y2Nlc3Moc3RhdGUpO1xyXG4gICAgfSBjYXRjaCAocG9wdXBTaWduT3V0RXJyb3IpIHtcclxuICAgICAgY29uc29sZS5sb2coJ1BvcHVwIHNpZ25vdXQgZXJyb3I6ICcsIHBvcHVwU2lnbk91dEVycm9yKTtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBhd2FpdCB0aGlzLnVzZXJNYW5hZ2VyIS5zaWdub3V0UmVkaXJlY3QodGhpcy5jcmVhdGVBcmd1bWVudHMoc3RhdGUpKTtcclxuICAgICAgICByZXR1cm4gdGhpcy5yZWRpcmVjdCgpO1xyXG4gICAgICB9IGNhdGNoIChyZWRpcmVjdFNpZ25PdXRFcnJvcikge1xyXG4gICAgICAgIGNvbnNvbGUubG9nKCdSZWRpcmVjdCBzaWdub3V0IGVycm9yOiAnLCBwb3B1cFNpZ25PdXRFcnJvcik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3IocmVkaXJlY3RTaWduT3V0RXJyb3IgYXMgRXJyb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgY29tcGxldGVTaWduT3V0KHVybDogc3RyaW5nKTogUHJvbWlzZTxJQXV0aGVudGljYXRpb25SZXN1bHQ+IHtcclxuICAgIGF3YWl0IHRoaXMuZW5zdXJlVXNlck1hbmFnZXJJbml0aWFsaXplZCgpO1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnVzZXJNYW5hZ2VyIS5zaWdub3V0Q2FsbGJhY2sodXJsKTtcclxuICAgICAgdGhpcy5zZXRVc2VyKG51bGwpO1xyXG4gICAgICByZXR1cm4gdGhpcy5zdWNjZXNzKHJlc3BvbnNlICYmIHJlc3BvbnNlLnN0YXRlKTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGNvbnNvbGUubG9nKGBUaGVyZSB3YXMgYW4gZXJyb3IgdHJ5aW5nIHRvIGxvZyBvdXQgJyR7ZXJyb3J9Jy5gKTtcclxuICAgICAgcmV0dXJuIHRoaXMuZXJyb3IoZXJyb3IgYXMgRXJyb3IpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJvdGVjdGVkIGFzeW5jIGVuc3VyZVVzZXJNYW5hZ2VySW5pdGlhbGl6ZWQoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBpZiAodGhpcy51c2VyTWFuYWdlciAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBhdXRoU2V0dGluZ3MgPSB0aGlzLnNldHRpbmdzUHJvdmlkZXIuc2V0dGluZ3M7XHJcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGF1dGhTZXR0aW5ncy5hcHBsaWNhdGlvblBhdGhzLkFwaUF1dGhvcml6YXRpb25DbGllbnRDb25maWd1cmF0aW9uVXJsKTtcclxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgbG9hZCBzZXR0aW5ncyBmb3IgJyR7YXV0aFNldHRpbmdzLmlkZW50aXR5QXBwSWR9J2ApO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHNldHRpbmdzOiBhbnkgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XHJcbiAgICBzZXR0aW5ncy5hdXRvbWF0aWNTaWxlbnRSZW5ldyA9IHRydWU7XHJcbiAgICBzZXR0aW5ncy5pbmNsdWRlSWRUb2tlbkluU2lsZW50UmVuZXcgPSB0cnVlO1xyXG4gICAgdGhpcy51c2VyTWFuYWdlciA9IG5ldyBVc2VyTWFuYWdlcihzZXR0aW5ncyk7XHJcblxyXG4gICAgdGhpcy51c2VyTWFuYWdlci5ldmVudHMuYWRkVXNlclNpZ25lZE91dChhc3luYyAoKSA9PiB7XHJcbiAgICAgIGF3YWl0IHRoaXMudXNlck1hbmFnZXIhLnJlbW92ZVVzZXIoKTtcclxuICAgICAgdGhpcy5zZXRVc2VyKG51bGwpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGVuc3VyZVBvcHVwRW5hYmxlZCgpIHtcclxuICAgIGlmICh0aGlzLnNldHRpbmdzUHJvdmlkZXIuc2V0dGluZ3MucG9wVXBEaXNhYmxlZCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BvcHVwIGRpc2FibGVkLiBJbnN0cnVjdCB0aGUgQXV0aG9yaXphdGlvblNldHRpbmdzUHJvdmlkZXIgc2VydmljZSB0byByZXR1cm4gZmFsc2UgaW4gXFwnc2V0dGluZ3MucG9wdXBEaXNhYmxlZFxcJyB0byBlbmFibGUgaXQuJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUFyZ3VtZW50cyhzdGF0ZT86IGFueSk6IGFueSB7XHJcbiAgICByZXR1cm4geyB1c2VSZXBsYWNlVG9OYXZpZ2F0ZTogdHJ1ZSwgZGF0YTogc3RhdGUgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZXJyb3IobWVzc2FnZTogc3RyaW5nIHwgRXJyb3IpOiBJQXV0aGVudGljYXRpb25SZXN1bHQge1xyXG4gICAgcmV0dXJuIHsgc3RhdHVzOiBBdXRoZW50aWNhdGlvblJlc3VsdFN0YXR1cy5GYWlsLCBtZXNzYWdlIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN1Y2Nlc3Moc3RhdGU6IGFueSk6IElBdXRoZW50aWNhdGlvblJlc3VsdCB7XHJcbiAgICByZXR1cm4geyBzdGF0dXM6IEF1dGhlbnRpY2F0aW9uUmVzdWx0U3RhdHVzLlN1Y2Nlc3MsIHN0YXRlIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlZGlyZWN0KCk6IElBdXRoZW50aWNhdGlvblJlc3VsdCB7XHJcbiAgICByZXR1cm4geyBzdGF0dXM6IEF1dGhlbnRpY2F0aW9uUmVzdWx0U3RhdHVzLlJlZGlyZWN0IH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldFVzZXJGcm9tU3RvcmFnZSgpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XHJcbiAgICByZXR1cm4gZnJvbSh0aGlzLmVuc3VyZVVzZXJNYW5hZ2VySW5pdGlhbGl6ZWQoKSlcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgbWVyZ2VNYXAoKCkgPT4gdGhpcy51c2VyTWFuYWdlciEuZ2V0VXNlcigpKSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldFVzZXIodXNlcjogVXNlciB8IG51bGwpIHtcclxuICAgIGNvbnN0IGN1cnJlbnRVc2VyID0gdGhpcy5yYXdVc2VyU3ViamVjdC52YWx1ZTtcclxuXHJcbiAgICAvLyBtYWtlIHN1cmUgbm90IHRvIGlzc3VlIGEgY2hhbmdlIGlmIHRoZSB1c2VyIGlzIG5vdCByZWFsbHkgY2hhbmdlZC5cclxuICAgIGlmIChjdXJyZW50VXNlciA9PSB1c2VyIHx8IGN1cnJlbnRVc2VyPy5pZF90b2tlbiA9PSB1c2VyPy5pZF90b2tlbikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5yYXdVc2VyU3ViamVjdC5uZXh0KHVzZXIpO1xyXG4gICAgdGhpcy51c2VyU3ViamVjdC5uZXh0KHVzZXI/LnByb2ZpbGUgfHwgbnVsbCk7XHJcbiAgfVxyXG59XHJcbiJdfQ==