@asgardeo/auth-angular
Version:
Asgardeo Auth Angular SDK for Angular Applications.
245 lines • 30.8 kB
JavaScript
import { __awaiter } from "tslib";
/**
* Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import { from, Subject } from "rxjs";
import { Inject, Injectable } from "@angular/core";
import { AsgardeoSPAClient, SPAUtils, } from "@asgardeo/auth-spa";
import { ASGARDEO_CONFIG } from "../configs/asgardeo-config";
import { Hooks } from "../models/asgardeo-spa.models";
import { AsgardeoNavigatorService } from "./asgardeo-navigator.service";
import { AsgardeoAuthStateStoreService } from "./asgardeo-auth-state-store.service";
import { takeUntil } from "rxjs/operators";
import * as i0 from "@angular/core";
import * as i1 from "../configs/asgardeo-config";
import * as i2 from "./asgardeo-navigator.service";
import * as i3 from "./asgardeo-auth-state-store.service";
export class AsgardeoAuthService {
constructor(authConfig, navigator, stateStore) {
this.authConfig = authConfig;
this.navigator = navigator;
this.stateStore = stateStore;
this.state$ = this.stateStore.state$;
this.auth = AsgardeoSPAClient.getInstance();
this.subscriptionDestroyer$ = new Subject();
/**
* This method allows you to sign in silently.
* First, this method sends a prompt none request to see if there is an active user session in the identity server.
* If there is one, then it requests the access token and stores it. Else, it returns false.
*
* @return {Promise<BasicUserInfo | boolean>} - A Promise that resolves with the user information after signing in
* or with `false` if the user is not signed in.
*
* @example
*```
* this.auth.trySignInSilently()
*```
*/
this.trySignInSilently = () => __awaiter(this, void 0, void 0, function* () {
this.stateStore.setIsLoading(true);
return this.auth
.trySignInSilently()
.then((response) => __awaiter(this, void 0, void 0, function* () {
if (!response) {
return false;
}
if (yield this.auth.isAuthenticated()) {
const basicUserInfo = response;
this.stateStore.state = {
allowedScopes: basicUserInfo.allowedScopes,
displayName: basicUserInfo.displayName,
email: basicUserInfo.email,
isAuthenticated: true,
isLoading: false,
sub: basicUserInfo.sub,
username: basicUserInfo.username
};
}
return response;
}))
.catch((error) => Promise.reject(error))
.finally(() => {
this.stateStore.setIsLoading(false);
});
});
this.config = authConfig;
this.auth = AsgardeoSPAClient.getInstance();
this.initializeHooks();
(() => __awaiter(this, void 0, void 0, function* () {
yield this.auth.initialize(this.authConfig);
yield this.handleSingleLogoutOnRedirect();
this.handleAutoLogin()
.pipe(takeUntil(this.subscriptionDestroyer$))
.subscribe();
}))();
}
/**
* Runs on service unmount.
* @remarks Housekeeping logic such as un-subscribing should go here.
*/
ngOnDestroy() {
this.subscriptionDestroyer$.next(true);
this.subscriptionDestroyer$.unsubscribe();
}
/**
* Registering a sign-out hook clears user session data internally if there was a successful logout.
*/
initializeHooks() {
this.auth.on(Hooks.SignOut, () => { });
}
signIn(config, authorizationCode, sessionState) {
this.stateStore.setIsLoading(true);
return this.auth
.signIn(config, authorizationCode, sessionState)
.then((response) => __awaiter(this, void 0, void 0, function* () {
if (!response) {
return;
}
if (yield this.auth.isAuthenticated()) {
this.stateStore.state = {
allowedScopes: response.allowedScopes,
displayName: response.displayName,
email: response.email,
isAuthenticated: true,
isLoading: false,
sub: response.sub,
username: response.username
};
}
return response;
}))
.catch((error) => Promise.reject(error))
.finally(() => {
this.stateStore.setIsLoading(false);
});
}
signInWithRedirect() {
this.navigator.setRedirectUrl();
const redirectRoute = this.navigator.getRouteWithoutParams(this.authConfig.signInRedirectURL);
return this.navigator.navigateByUrl(redirectRoute);
}
signOut() {
this.stateStore.setIsLoading(true);
return this.auth
.signOut()
.then((response) => {
// Reset the state.
this.stateStore.reset();
return response;
})
.catch((error) => Promise.reject(error))
.finally(() => {
this.stateStore.setIsLoading(false);
});
}
isAuthenticated() {
return this.auth.isAuthenticated();
}
getBasicUserInfo() {
return this.auth.getBasicUserInfo();
}
getAccessToken() {
return this.auth.getAccessToken();
}
getIDToken() {
return this.auth.getIDToken();
}
getDecodedIDToken() {
return this.auth.getDecodedIDToken();
}
getOIDCServiceEndpoints() {
return this.auth.getOIDCServiceEndpoints();
}
refreshAccessToken() {
return this.auth.refreshAccessToken();
}
revokeAccessToken() {
return this.auth
.revokeAccessToken()
.then(() => {
// Reset the state.
this.stateStore.reset();
return true;
})
.catch((error) => Promise.reject(error))
.finally(() => {
this.stateStore.setIsLoading(false);
});
}
on(hook, callback, id) {
if (hook === Hooks.CustomGrant) {
return this.auth.on(hook, callback, id);
}
return this.auth.on(hook, callback);
}
requestCustomGrant(config) {
return this.auth.requestCustomGrant(config);
}
httpRequest(config) {
return this.auth.httpRequest(config);
}
httpRequestAll(config) {
return this.auth.httpRequestAll(config);
}
/**
* Handles auto login by trying to exchange tokens if auth params i.e `code` and `session_state` is
* available in the URL or else, tries to silently login.
*
* @private
* @return {Observable<BasicUserInfo | boolean>}
*/
handleAutoLogin() {
this.stateStore.setIsLoading(true);
// If `skipRedirectCallback` is not true, check if the URL has `code` and `session_state` params.
// If so, initiate the sign in. If not, try to login silently.
if (!this.config.skipRedirectCallback &&
SPAUtils.hasAuthSearchParamsInURL()) {
return from(this.signIn());
}
// This uses the RP iframe to get the session. Hence, will not work if 3rd party cookies are disabled.
// If the browser has these cookies disabled, we'll not be able to retrieve the session on refreshes.
return from(this.trySignInSilently());
}
/**
* Handles single logout if a prompt none sign in response is received with an error parameter on the URL.
*
* @private
* @return {Promise<BasicUserInfo | void>}
*/
handleSingleLogoutOnRedirect() {
return __awaiter(this, void 0, void 0, function* () {
if (SPAUtils.hasErrorInURL()) {
// The signIn method call will call receivePromptNoneResponse method internally to handle the prompt none
// response in the single logout flow.
return this.signIn({ callOnlyOnRedirect: true });
}
});
}
}
AsgardeoAuthService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AsgardeoAuthService_Factory() { return new AsgardeoAuthService(i0.ɵɵinject(i1.ASGARDEO_CONFIG), i0.ɵɵinject(i2.AsgardeoNavigatorService), i0.ɵɵinject(i3.AsgardeoAuthStateStoreService)); }, token: AsgardeoAuthService, providedIn: "root" });
AsgardeoAuthService.decorators = [
{ type: Injectable, args: [{
providedIn: "root"
},] }
];
AsgardeoAuthService.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Inject, args: [ASGARDEO_CONFIG,] }] },
{ type: AsgardeoNavigatorService },
{ type: AsgardeoAuthStateStoreService }
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNnYXJkZW8tYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Ii9ob21lL3J1bm5lci93b3JrL2FzZ2FyZGVvLWF1dGgtYW5ndWxhci1zZGsvYXNnYXJkZW8tYXV0aC1hbmd1bGFyLXNkay9saWIvc3JjLyIsInNvdXJjZXMiOlsic2VydmljZXMvYXNnYXJkZW8tYXV0aC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFFSCxPQUFPLEVBQUUsSUFBSSxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNqRCxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBYSxNQUFNLGVBQWUsQ0FBQztBQUM5RCxPQUFPLEVBQ0gsaUJBQWlCLEVBRWpCLFFBQVEsR0FFWCxNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUU3RCxPQUFPLEVBSUgsS0FBSyxFQUtSLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDeEUsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDcEYsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7OztBQUszQyxNQUFNLE9BQU8sbUJBQW1CO0lBTTVCLFlBRVksVUFBK0MsRUFDL0MsU0FBbUMsRUFDbkMsVUFBeUM7UUFGekMsZUFBVSxHQUFWLFVBQVUsQ0FBcUM7UUFDL0MsY0FBUyxHQUFULFNBQVMsQ0FBMEI7UUFDbkMsZUFBVSxHQUFWLFVBQVUsQ0FBK0I7UUFUckMsV0FBTSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO1FBQ3hDLFNBQUksR0FBc0IsaUJBQWlCLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFMUQsMkJBQXNCLEdBQXFCLElBQUksT0FBTyxFQUFXLENBQUM7UUFxSzFF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SUFDMUMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ1csNEJBQTRCOztZQUV0QyxJQUFJLFFBQVEsQ0FBQyxhQUFhLEVBQUUsRUFBRTtnQkFDMUIseUdBQXlHO2dCQUN6RyxzQ0FBc0M7Z0JBQ3RDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFDLGtCQUFrQixFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7YUFDbEQ7UUFDTCxDQUFDO0tBQUE7Ozs7WUEvUEosVUFBVSxTQUFDO2dCQUNSLFVBQVUsRUFBRSxNQUFNO2FBQ3JCOzs7NENBUVEsTUFBTSxTQUFDLGVBQWU7WUFkdEIsd0JBQXdCO1lBQ3hCLDZCQUE2QiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDIxLCBXU08yIEluYy4gKGh0dHA6Ly93d3cud3NvMi5vcmcpIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogV1NPMiBJbmMuIGxpY2Vuc2VzIHRoaXMgZmlsZSB0byB5b3UgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLFxuICogVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0XG4gKiBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLFxuICogc29mdHdhcmUgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW5cbiAqIFwiQVMgSVNcIiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXG4gKiBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IGZyb20sIE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBPbkRlc3Ryb3kgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHtcbiAgICBBc2dhcmRlb1NQQUNsaWVudCxcbiAgICBBdXRoQ2xpZW50Q29uZmlnLFxuICAgIFNQQVV0aWxzLFxuICAgIEZldGNoUmVzcG9uc2UsXG59IGZyb20gXCJAYXNnYXJkZW8vYXV0aC1zcGFcIjtcbmltcG9ydCB7IEFTR0FSREVPX0NPTkZJRyB9IGZyb20gXCIuLi9jb25maWdzL2FzZ2FyZGVvLWNvbmZpZ1wiO1xuaW1wb3J0IHsgQXV0aEFuZ3VsYXJDb25maWcsIEF1dGhTdGF0ZUludGVyZmFjZSB9IGZyb20gXCIuLi9tb2RlbHNcIjtcbmltcG9ydCB7XG4gICAgQmFzaWNVc2VySW5mbyxcbiAgICBDdXN0b21HcmFudENvbmZpZyxcbiAgICBEZWNvZGVkSURUb2tlblBheWxvYWQsXG4gICAgSG9va3MsXG4gICAgSHR0cFJlcXVlc3RDb25maWcsXG4gICAgSHR0cFJlc3BvbnNlLFxuICAgIE9JRENFbmRwb2ludHMsXG4gICAgU2lnbkluQ29uZmlnXG59IGZyb20gXCIuLi9tb2RlbHMvYXNnYXJkZW8tc3BhLm1vZGVsc1wiO1xuaW1wb3J0IHsgQXNnYXJkZW9OYXZpZ2F0b3JTZXJ2aWNlIH0gZnJvbSBcIi4vYXNnYXJkZW8tbmF2aWdhdG9yLnNlcnZpY2VcIjtcbmltcG9ydCB7IEFzZ2FyZGVvQXV0aFN0YXRlU3RvcmVTZXJ2aWNlIH0gZnJvbSBcIi4vYXNnYXJkZW8tYXV0aC1zdGF0ZS1zdG9yZS5zZXJ2aWNlXCI7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcblxuQEluamVjdGFibGUoe1xuICAgIHByb3ZpZGVkSW46IFwicm9vdFwiXG59KVxuZXhwb3J0IGNsYXNzIEFzZ2FyZGVvQXV0aFNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAgIHB1YmxpYyByZWFkb25seSBzdGF0ZSQgPSB0aGlzLnN0YXRlU3RvcmUuc3RhdGUkO1xuICAgIHByaXZhdGUgYXV0aDogQXNnYXJkZW9TUEFDbGllbnQgPSBBc2dhcmRlb1NQQUNsaWVudC5nZXRJbnN0YW5jZSgpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBBdXRoQ2xpZW50Q29uZmlnPEF1dGhBbmd1bGFyQ29uZmlnPjtcbiAgICBwcml2YXRlIHN1YnNjcmlwdGlvbkRlc3Ryb3llciQ6IFN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIEBJbmplY3QoQVNHQVJERU9fQ09ORklHKVxuICAgICAgICBwcml2YXRlIGF1dGhDb25maWc6IEF1dGhDbGllbnRDb25maWc8QXV0aEFuZ3VsYXJDb25maWc+LFxuICAgICAgICBwcml2YXRlIG5hdmlnYXRvcjogQXNnYXJkZW9OYXZpZ2F0b3JTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHN0YXRlU3RvcmU6IEFzZ2FyZGVvQXV0aFN0YXRlU3RvcmVTZXJ2aWNlXG4gICAgKSB7XG4gICAgICAgIHRoaXMuY29uZmlnID0gYXV0aENvbmZpZztcbiAgICAgICAgdGhpcy5hdXRoID0gQXNnYXJkZW9TUEFDbGllbnQuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplSG9va3MoKTtcbiAgICAgICAgKGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuYXV0aC5pbml0aWFsaXplKHRoaXMuYXV0aENvbmZpZyk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZVNpbmdsZUxvZ291dE9uUmVkaXJlY3QoKTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlQXV0b0xvZ2luKClcbiAgICAgICAgICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5zdWJzY3JpcHRpb25EZXN0cm95ZXIkKSlcbiAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKCk7XG4gICAgICAgIH0pKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUnVucyBvbiBzZXJ2aWNlIHVubW91bnQuXG4gICAgICogQHJlbWFya3MgSG91c2VrZWVwaW5nIGxvZ2ljIHN1Y2ggYXMgdW4tc3Vic2NyaWJpbmcgc2hvdWxkIGdvIGhlcmUuXG4gICAgICovXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9uRGVzdHJveWVyJC5uZXh0KHRydWUpO1xuICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbkRlc3Ryb3llciQudW5zdWJzY3JpYmUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcmluZyBhIHNpZ24tb3V0IGhvb2sgY2xlYXJzIHVzZXIgc2Vzc2lvbiBkYXRhIGludGVybmFsbHkgaWYgdGhlcmUgd2FzIGEgc3VjY2Vzc2Z1bCBsb2dvdXQuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZUhvb2tzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmF1dGgub24oSG9va3MuU2lnbk91dCwgKCk9Pnt9KTtcbiAgICB9XG5cbiAgICBzaWduSW4oXG4gICAgICAgIGNvbmZpZz86IFNpZ25JbkNvbmZpZyxcbiAgICAgICAgYXV0aG9yaXphdGlvbkNvZGU/OiBzdHJpbmcsXG4gICAgICAgIHNlc3Npb25TdGF0ZT86IHN0cmluZ1xuICAgICk6IFByb21pc2U8QmFzaWNVc2VySW5mbz4ge1xuICAgICAgICB0aGlzLnN0YXRlU3RvcmUuc2V0SXNMb2FkaW5nKHRydWUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhcbiAgICAgICAgICAgIC5zaWduSW4oY29uZmlnLCBhdXRob3JpemF0aW9uQ29kZSwgc2Vzc2lvblN0YXRlKVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgKHJlc3BvbnNlOiBCYXNpY1VzZXJJbmZvKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFyZXNwb25zZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGF3YWl0IHRoaXMuYXV0aC5pc0F1dGhlbnRpY2F0ZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlU3RvcmUuc3RhdGUgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbGxvd2VkU2NvcGVzOiByZXNwb25zZS5hbGxvd2VkU2NvcGVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheU5hbWU6IHJlc3BvbnNlLmRpc3BsYXlOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW1haWw6IHJlc3BvbnNlLmVtYWlsLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNBdXRoZW50aWNhdGVkOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgaXNMb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YjogcmVzcG9uc2Uuc3ViLFxuICAgICAgICAgICAgICAgICAgICAgICAgdXNlcm5hbWU6IHJlc3BvbnNlLnVzZXJuYW1lXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IFByb21pc2UucmVqZWN0KGVycm9yKSlcbiAgICAgICAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlU3RvcmUuc2V0SXNMb2FkaW5nKGZhbHNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHNpZ25JbldpdGhSZWRpcmVjdCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgdGhpcy5uYXZpZ2F0b3Iuc2V0UmVkaXJlY3RVcmwoKTtcbiAgICAgICAgY29uc3QgcmVkaXJlY3RSb3V0ZSA9IHRoaXMubmF2aWdhdG9yLmdldFJvdXRlV2l0aG91dFBhcmFtcyhcbiAgICAgICAgICAgIHRoaXMuYXV0aENvbmZpZy5zaWduSW5SZWRpcmVjdFVSTFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiB0aGlzLm5hdmlnYXRvci5uYXZpZ2F0ZUJ5VXJsKHJlZGlyZWN0Um91dGUpO1xuICAgIH1cblxuICAgIHNpZ25PdXQoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHRoaXMuc3RhdGVTdG9yZS5zZXRJc0xvYWRpbmcodHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aFxuICAgICAgICAgICAgLnNpZ25PdXQoKVxuICAgICAgICAgICAgLnRoZW4oKHJlc3BvbnNlOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gUmVzZXQgdGhlIHN0YXRlLlxuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGVTdG9yZS5yZXNldCgpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IFByb21pc2UucmVqZWN0KGVycm9yKSlcbiAgICAgICAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlU3RvcmUuc2V0SXNMb2FkaW5nKGZhbHNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlzQXV0aGVudGljYXRlZCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5pc0F1dGhlbnRpY2F0ZWQoKTtcbiAgICB9XG5cbiAgICBnZXRCYXNpY1VzZXJJbmZvKCk6IFByb21pc2U8QmFzaWNVc2VySW5mbz4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLmdldEJhc2ljVXNlckluZm8oKTtcbiAgICB9XG5cbiAgICBnZXRBY2Nlc3NUb2tlbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLmdldEFjY2Vzc1Rva2VuKCk7XG4gICAgfVxuXG4gICAgZ2V0SURUb2tlbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLmdldElEVG9rZW4oKTtcbiAgICB9XG5cbiAgICBnZXREZWNvZGVkSURUb2tlbigpOiBQcm9taXNlPERlY29kZWRJRFRva2VuUGF5bG9hZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLmdldERlY29kZWRJRFRva2VuKCk7XG4gICAgfVxuXG4gICAgZ2V0T0lEQ1NlcnZpY2VFbmRwb2ludHMoKTogUHJvbWlzZTxPSURDRW5kcG9pbnRzPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGguZ2V0T0lEQ1NlcnZpY2VFbmRwb2ludHMoKTtcbiAgICB9XG5cbiAgICByZWZyZXNoQWNjZXNzVG9rZW4oKTogUHJvbWlzZTxCYXNpY1VzZXJJbmZvPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGgucmVmcmVzaEFjY2Vzc1Rva2VuKCk7XG4gICAgfVxuXG4gICAgcmV2b2tlQWNjZXNzVG9rZW4oKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhcbiAgICAgICAgICAgIC5yZXZva2VBY2Nlc3NUb2tlbigpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gUmVzZXQgdGhlIHN0YXRlLlxuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGVTdG9yZS5yZXNldCgpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKChlcnJvcikgPT4gUHJvbWlzZS5yZWplY3QoZXJyb3IpKVxuICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGVTdG9yZS5zZXRJc0xvYWRpbmcoZmFsc2UpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgb24oXG4gICAgICAgIGhvb2s6IEhvb2tzLFxuICAgICAgICBjYWxsYmFjazogKHJlc3BvbnNlPzogYW55KSA9PiB2b2lkLFxuICAgICAgICBpZD86IHN0cmluZ1xuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoaG9vayA9PT0gSG9va3MuQ3VzdG9tR3JhbnQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmF1dGgub24oaG9vaywgY2FsbGJhY2ssIGlkIGFzIHN0cmluZyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLm9uKGhvb2ssIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICByZXF1ZXN0Q3VzdG9tR3JhbnQoXG4gICAgICAgIGNvbmZpZzogQ3VzdG9tR3JhbnRDb25maWdcbiAgICApOiBQcm9taXNlPEZldGNoUmVzcG9uc2U8YW55PiB8IEJhc2ljVXNlckluZm8+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5yZXF1ZXN0Q3VzdG9tR3JhbnQoY29uZmlnKTtcbiAgICB9XG5cbiAgICBodHRwUmVxdWVzdChjb25maWc6IEh0dHBSZXF1ZXN0Q29uZmlnKTogUHJvbWlzZTxIdHRwUmVzcG9uc2U8YW55Pj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLmh0dHBSZXF1ZXN0KGNvbmZpZyk7XG4gICAgfVxuXG4gICAgaHR0cFJlcXVlc3RBbGwoY29uZmlnOiBIdHRwUmVxdWVzdENvbmZpZ1tdKTogUHJvbWlzZTxIdHRwUmVzcG9uc2U8YW55PltdPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGguaHR0cFJlcXVlc3RBbGwoY29uZmlnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBhbGxvd3MgeW91IHRvIHNpZ24gaW4gc2lsZW50bHkuXG4gICAgICogRmlyc3QsIHRoaXMgbWV0aG9kIHNlbmRzIGEgcHJvbXB0IG5vbmUgcmVxdWVzdCB0byBzZWUgaWYgdGhlcmUgaXMgYW4gYWN0aXZlIHVzZXIgc2Vzc2lvbiBpbiB0aGUgaWRlbnRpdHkgc2VydmVyLlxuICAgICAqIElmIHRoZXJlIGlzIG9uZSwgdGhlbiBpdCByZXF1ZXN0cyB0aGUgYWNjZXNzIHRva2VuIGFuZCBzdG9yZXMgaXQuIEVsc2UsIGl0IHJldHVybnMgZmFsc2UuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPEJhc2ljVXNlckluZm8gfCBib29sZWFuPn0gLSBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSB1c2VyIGluZm9ybWF0aW9uIGFmdGVyIHNpZ25pbmcgaW5cbiAgICAgKiBvciB3aXRoIGBmYWxzZWAgaWYgdGhlIHVzZXIgaXMgbm90IHNpZ25lZCBpbi5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpgYGBcbiAgICAgKiB0aGlzLmF1dGgudHJ5U2lnbkluU2lsZW50bHkoKVxuICAgICAqYGBgXG4gICAgICovXG4gICAgcHVibGljIHRyeVNpZ25JblNpbGVudGx5ID0gYXN5bmMgKCk6IFByb21pc2U8QmFzaWNVc2VySW5mbyB8IGJvb2xlYW4+ID0+IHtcbiAgICAgICAgdGhpcy5zdGF0ZVN0b3JlLnNldElzTG9hZGluZyh0cnVlKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5hdXRoXG4gICAgICAgICAgICAudHJ5U2lnbkluU2lsZW50bHkoKVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgKHJlc3BvbnNlOiBCYXNpY1VzZXJJbmZvIHwgYm9vbGVhbikgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhd2FpdCB0aGlzLmF1dGguaXNBdXRoZW50aWNhdGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmFzaWNVc2VySW5mbzogQmFzaWNVc2VySW5mbyA9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZSBhcyBCYXNpY1VzZXJJbmZvO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGVTdG9yZS5zdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93ZWRTY29wZXM6IGJhc2ljVXNlckluZm8uYWxsb3dlZFNjb3BlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lOiBiYXNpY1VzZXJJbmZvLmRpc3BsYXlOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW1haWw6IGJhc2ljVXNlckluZm8uZW1haWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0F1dGhlbnRpY2F0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0xvYWRpbmc6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3ViOiBiYXNpY1VzZXJJbmZvLnN1YixcbiAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJuYW1lOiBiYXNpY1VzZXJJbmZvLnVzZXJuYW1lXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IFByb21pc2UucmVqZWN0KGVycm9yKSlcbiAgICAgICAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlU3RvcmUuc2V0SXNMb2FkaW5nKGZhbHNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGF1dG8gbG9naW4gYnkgdHJ5aW5nIHRvIGV4Y2hhbmdlIHRva2VucyBpZiBhdXRoIHBhcmFtcyBpLmUgYGNvZGVgIGFuZCBgc2Vzc2lvbl9zdGF0ZWAgaXNcbiAgICAgKiBhdmFpbGFibGUgaW4gdGhlIFVSTCBvciBlbHNlLCB0cmllcyB0byBzaWxlbnRseSBsb2dpbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHJldHVybiB7T2JzZXJ2YWJsZTxCYXNpY1VzZXJJbmZvIHwgYm9vbGVhbj59XG4gICAgICovXG4gICAgcHJpdmF0ZSBoYW5kbGVBdXRvTG9naW4oKTogT2JzZXJ2YWJsZTxCYXNpY1VzZXJJbmZvIHwgYm9vbGVhbj4ge1xuICAgICAgICB0aGlzLnN0YXRlU3RvcmUuc2V0SXNMb2FkaW5nKHRydWUpO1xuXG4gICAgICAgIC8vIElmIGBza2lwUmVkaXJlY3RDYWxsYmFja2AgaXMgbm90IHRydWUsIGNoZWNrIGlmIHRoZSBVUkwgaGFzIGBjb2RlYCBhbmQgYHNlc3Npb25fc3RhdGVgIHBhcmFtcy5cbiAgICAgICAgLy8gSWYgc28sIGluaXRpYXRlIHRoZSBzaWduIGluLiBJZiBub3QsIHRyeSB0byBsb2dpbiBzaWxlbnRseS5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgIXRoaXMuY29uZmlnLnNraXBSZWRpcmVjdENhbGxiYWNrICYmXG4gICAgICAgICAgICBTUEFVdGlscy5oYXNBdXRoU2VhcmNoUGFyYW1zSW5VUkwoKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBmcm9tKHRoaXMuc2lnbkluKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhpcyB1c2VzIHRoZSBSUCBpZnJhbWUgdG8gZ2V0IHRoZSBzZXNzaW9uLiBIZW5jZSwgd2lsbCBub3Qgd29yayBpZiAzcmQgcGFydHkgY29va2llcyBhcmUgZGlzYWJsZWQuXG4gICAgICAgIC8vIElmIHRoZSBicm93c2VyIGhhcyB0aGVzZSBjb29raWVzIGRpc2FibGVkLCB3ZSdsbCBub3QgYmUgYWJsZSB0byByZXRyaWV2ZSB0aGUgc2Vzc2lvbiBvbiByZWZyZXNoZXMuXG4gICAgICAgIHJldHVybiBmcm9tKHRoaXMudHJ5U2lnbkluU2lsZW50bHkoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyBzaW5nbGUgbG9nb3V0IGlmIGEgcHJvbXB0IG5vbmUgc2lnbiBpbiByZXNwb25zZSBpcyByZWNlaXZlZCB3aXRoIGFuIGVycm9yIHBhcmFtZXRlciBvbiB0aGUgVVJMLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPEJhc2ljVXNlckluZm8gfCB2b2lkPn1cbiAgICAgKi9cbiAgICBwcml2YXRlIGFzeW5jIGhhbmRsZVNpbmdsZUxvZ291dE9uUmVkaXJlY3QoKTogUHJvbWlzZTxCYXNpY1VzZXJJbmZvIHwgdm9pZD4ge1xuXG4gICAgICAgIGlmIChTUEFVdGlscy5oYXNFcnJvckluVVJMKCkpIHtcbiAgICAgICAgICAgIC8vIFRoZSBzaWduSW4gbWV0aG9kIGNhbGwgd2lsbCBjYWxsIHJlY2VpdmVQcm9tcHROb25lUmVzcG9uc2UgbWV0aG9kIGludGVybmFsbHkgdG8gaGFuZGxlIHRoZSBwcm9tcHQgbm9uZVxuICAgICAgICAgICAgLy8gcmVzcG9uc2UgaW4gdGhlIHNpbmdsZSBsb2dvdXQgZmxvdy5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNpZ25Jbih7Y2FsbE9ubHlPblJlZGlyZWN0OiB0cnVlfSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=