UNPKG

ngx-amplify

Version:

An angular library for integration AWS cloud services (cognito, s3)

811 lines 68.4 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { Injectable, Inject } from '@angular/core'; import { NGX_AMPLIFY_CONFIG } from '../common/interfaces/ngx-amplify.config'; import * as AWS from 'aws-sdk'; import { CognitoUserPool, CognitoUser, AuthenticationDetails, CognitoUserAttribute } from 'amazon-cognito-identity-js'; import { BehaviorSubject } from 'rxjs'; import { CognitoException, CognitoProfile, AuthUser } from '../common/common.resource'; import * as i0 from "@angular/core"; import * as i1 from "../common/interfaces/ngx-amplify.config"; export class AuthService { /** * @param {?} config */ constructor(config) { this.config = config; this.resetting = false; this.authState = new BehaviorSubject({ state: 'signedOut', user: null }); this.authState$ = this.authState.asObservable(); this.authUserState = new BehaviorSubject({ state: 'signedOut', user: null }); this.authUserState$ = this.authUserState.asObservable(); this.cognitoUserSub = new BehaviorSubject(this.cognitoUser); this.cognitoUser$ = this.cognitoUserSub.asObservable(); AWS.config.region = this.config.region; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: this.config.identityPoolId }); this.poolData = { UserPoolId: config.userPoolId, ClientId: this.config.appId }; this.userPool = new CognitoUserPool(this.poolData); this.user = AuthUser.Factory(); // this.authUserState.next({ state: 'signedOut', user: this.user }); // this.refreshOrResetCreds(); // this.currentAuthUser = this.currentAuthUser.bind(this); } /** * @private * @param {?} creds * @return {?} */ authDetails(creds) { return new AuthenticationDetails({ Username: creds.username, Password: creds.password }); } /** * @private * @return {?} */ buildCreds() { /** @type {?} */ let self = this; /** @type {?} */ let json = self.buildLogins(self.session.getIdToken().getJwtToken()); return new AWS.CognitoIdentityCredentials(json); } /** * @private * @param {?} token * @return {?} */ buildLogins(token) { /** @type {?} */ let self = this; /** @type {?} */ let key = `${self.config.idpUrl}/${self.config.userPoolId}`; /** @type {?} */ let json = { IdentityPoolId: self.config.identityPoolId, Logins: {} }; json.Logins[key] = token; return json; } /** * @private * @param {?} error * @param {?} caller * @return {?} */ handleError(error, caller) { /** @type {?} */ let exception = new CognitoException(error); console.error(`AWS Cognito Service::handleError callerMethod::${caller}`, exception); return exception; } /** * @private * @return {?} */ getCurrentUser() { return this.userPool.getCurrentUser(); } /** * @private * @param {?} profile * @return {?} */ getCognitoAttributes(profile) { /** @type {?} */ let cognitoAttributes = []; for (let key in profile) { if (!key.includes("password") && !key.includes("confirmPassword")) { /** @type {?} */ let attribute; if (key.includes("username")) { attribute = new CognitoUserAttribute({ Name: "preferred_username", Value: profile[key] }); } else if (key.endsWith("__c")) { /** @type {?} */ let k = key.substring(0, key.length - 3); /** @type {?} */ let name = `custom:${k}`; attribute = new CognitoUserAttribute({ Name: name, Value: profile[key] }); } else { attribute = new CognitoUserAttribute({ Name: key, Value: profile[key] }); } cognitoAttributes.push(attribute); } } return cognitoAttributes; } /** * @private * @param {?} creds * @return {?} */ getCognitoUser(creds) { /** @type {?} */ let self = this; /** @type {?} */ let result = new CognitoUser({ Username: creds.username, Pool: self.userPool }); return result; } /** * @return {?} */ getJwtToken() { /** @type {?} */ let self = this; /** @type {?} */ let user = self.getCurrentUser(); /** @type {?} */ let token; if (user !== null) { token = user.getSignInUserSession().getAccessToken().getJwtToken(); } return token; } /** * @param {?} attributes * @return {?} */ getCognitoProfile(attributes) { /** @type {?} */ let dynObj = CognitoProfile.Factory(); /** @type {?} */ let values = attributes; ((/** @type {?} */ (values))).forEach((/** * @param {?} attr * @return {?} */ attr => { if (attr.Name.startsWith('custom:')) { /** @type {?} */ let attributeName = attr.Name.substring(7); dynObj[attributeName + '__c'] = attr.Value; } else { dynObj[attr.Name] = attr.Value; } })); /** @type {?} */ let result = new CognitoProfile(dynObj); return result; } /** * @private * @param {?} cognitoUser * @return {?} */ setCognitoProfile(cognitoUser) { /** @type {?} */ let self = this; return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => { if (cognitoUser === null) { reject(null); } else { cognitoUser.getUserData((/** * @param {?} err * @param {?} result * @return {?} */ (err, result) => { if (err) { reject(self.handleError(err, 'setCognitoProfile')); } /** @type {?} */ let dynObj = self.getCognitoProfile(result.UserAttributes); if (dynObj.sub) { self.user.identityId = dynObj.sub; } self.user.cognitoProfile = dynObj; resolve(dynObj); })); } })); } /** * @param {?} attributes * @return {?} */ updateCognitoProfile(attributes) { /** @type {?} */ let self = this; return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () { try { self.cognitoUser.updateAttributes(attributes, (/** * @param {?} err * @param {?} result * @return {?} */ (err, result) => tslib_1.__awaiter(this, void 0, void 0, function* () { if (err) { reject(self.handleError(err, 'updateAttributes')); } self.setCognitoProfile(self.cognitoUser) .then((/** * @param {?} profile * @return {?} */ (profile) => { resolve(profile); })) .catch((/** * @param {?} error * @return {?} */ (error) => { reject(self.handleError(error, 'setCognitoProfile')); })); }))); } catch (error) { reject(self.handleError(error, 'try/catch updateCognitoProfile')); } }))); } /** * @private * @param {?=} clearCache * @return {?} */ resetCreds(clearCache = false) { // console.log('Resetting credentials for unauth access'); this.resetting = true; AWS.config.region = this.config.region; this.cognitoUser = null; this.cognitoUserSub.next(null); this.unauthCreds = this.unauthCreds || new AWS.CognitoIdentityCredentials({ IdentityPoolId: this.config.identityPoolId }); if (clearCache) { this.unauthCreds.clearCachedId(); } this.setCredentials(this.unauthCreds); this.resetting = false; } /** * @return {?} */ currentAuthUser() { return tslib_1.__awaiter(this, void 0, void 0, /** @this {!AuthService} */ function* () { /** @type {?} */ let self = this; /** @type {?} */ let user = this.userPool.getCurrentUser(); // console.log('auth:currentAuthUser', user); if (user !== null) { yield this.refreshSession(user); } /* else { self.authState.next({state: 'signedOut', user: user }); self.cognitoUserSub.next(user); self.authUserState.next({ state: 'signedOut', user: self.user }); } */ return self.user; }); } /** * @return {?} */ refreshOrResetCreds() { return tslib_1.__awaiter(this, void 0, void 0, /** @this {!AuthService} */ function* () { this.cognitoUser = this.userPool.getCurrentUser(); if (this.cognitoUser !== null) { if (this.cognitoUser.getSignInUserSession() === null) { /** @type {?} */ let session = yield this.refreshSession(); } } else { this.resetCreds(); } }); } /** * @private * @param {?=} user * @return {?} */ refreshSession(user) { /** @type {?} */ let self = this; if (user === undefined) { user = this.userPool.getCurrentUser(); } self.cognitoUser = user; // Object.assign({},user, self.cognitoUser); // console.log('self.user on refresh', self.cognitoUser); // self.session = user.; if (self.session && self.session.isValid) { // console.log('using the current session already refreshed..'); self.cognitoUser.setSignInUserSession(self.session); return new Promise((/** * @param {?} resolve * @return {?} */ (resolve) => tslib_1.__awaiter(this, void 0, void 0, function* () { yield self.saveCreds(self.cognitoUser, self.session); resolve(self.session); }))); } else { /* return self.cognitoUser.getSession(async (err, session: CognitoUserSession) => { if (err) { console.log('Error refreshing user session', err); return err; } console.log(`${new Date()} - Refreshed session for ${self.cognitoUser.getUsername()}. Valid?: `, session.isValid()); self.session = session; self.cognitoUser.setSignInUserSession(session); await self.saveCreds(self.cognitoUser, session); return session; }) */ return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () { self.cognitoUser.getSession((/** * @param {?} err * @param {?} session * @return {?} */ (err, session) => tslib_1.__awaiter(this, void 0, void 0, function* () { if (err) { console.log('Error refreshing user session', err); reject(err); } // console.log(`${new Date()} - Refreshed session for ${self.cognitoUser.getUsername()}. Valid?: `, session.isValid()); self.session = session; self.cognitoUser.setSignInUserSession(session); yield self.saveCreds(self.cognitoUser, session); resolve(session); }))); }))); } } /** * @param {?=} cognitoUser * @param {?=} session * @return {?} */ saveCreds(cognitoUser, session) { return tslib_1.__awaiter(this, void 0, void 0, /** @this {!AuthService} */ function* () { /** @type {?} */ let self = this; if (session) { self.session = session; self.user.authenticated = session.isValid(); self.authState.next({ state: 'signedIn', user: cognitoUser }); } if (cognitoUser) { self.cognitoUser = cognitoUser; self.user.cognitoUser = cognitoUser; self.authState.next({ state: 'signedIn', user: cognitoUser }); self.cognitoUserSub.next(cognitoUser); self.user.cognitoProfile = CognitoProfile.Factory(); yield self.setCognitoProfile(cognitoUser); self.authUserState.next({ state: 'signedIn', user: self.user }); } self.setCredentials(self.buildCreds()); return self.user; }); } /** * @private * @param {?} creds * @return {?} */ setCredentials(creds) { AWS.config.credentials = creds; } /** * @param {?} creds * @return {?} */ signIn(creds) { /** @type {?} */ let self = this; /** @type {?} */ let cognitoUser = self.getCognitoUser(creds); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => { try { cognitoUser.authenticateUser(self.authDetails(creds), { onSuccess: (/** * @param {?} session * @return {?} */ (session) => tslib_1.__awaiter(this, void 0, void 0, function* () { // console.log(`Signed in user ${cognitoUser.getUsername()}. Sessiong valid?: `, session.isValid()); /** @type {?} */ let user = yield self.saveCreds(cognitoUser, session); resolve(user); })), onFailure: (/** * @param {?} err * @return {?} */ (err) => { reject(self.handleError(err, 'signIn')); }), newPasswordRequired: (/** * @param {?} userAttributes * @param {?} requiredAttributes * @return {?} */ (userAttributes, requiredAttributes) => { cognitoUser.completeNewPasswordChallenge(creds.password, requiredAttributes, { onSuccess: (/** * @param {?} session * @return {?} */ (session) => tslib_1.__awaiter(this, void 0, void 0, function* () { /** @type {?} */ let aws_creds; aws_creds = new AWS.CognitoIdentityCredentials(self.buildLogins(session.getIdToken().getJwtToken())); /** @type {?} */ let user = yield self.saveCreds(cognitoUser, session); resolve(user); })), onFailure: (/** * @param {?} err * @return {?} */ (err) => { reject(self.handleError(err, 'completeNewPasswordChallenge')); }) }); }), mfaRequired: (/** * @param {?} challengeName * @param {?} challengeParameters * @return {?} */ (challengeName, challengeParameters) => { }), customChallenge: (/** * @param {?} challengeParameters * @return {?} */ (challengeParameters) => { }), }); } catch (error) { reject(error); } })); } /** * @param {?} creds * @return {?} */ signUp(creds) { /** @type {?} */ let self = this; // creds.member_since__c = moment().year().toString(); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => { try { /** @type {?} */ let attributes = []; attributes = self.getCognitoAttributes(creds); return self.userPool.signUp(creds.username, creds.password, attributes, null, (/** * @param {?} err * @param {?} result * @return {?} */ (err, result) => { if (err) { reject(self.handleError(err, 'signUp')); } else { // console.log('signUp registration successful', result); resolve(result); } })); } catch (error) { reject(self.handleError(error, 'try/catch signUp')); } })); } /** * @param {?} username * @param {?} code * @return {?} */ confirmSignUp(username, code) { /** @type {?} */ let self = this; /** @type {?} */ let userData = { Username: username, Pool: self.userPool }; /** @type {?} */ let cognitoUser = new CognitoUser(userData); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => { try { cognitoUser.confirmRegistration(code, true, ((/** * @param {?} err * @param {?} result * @return {?} */ (err, result) => { if (err) { reject(self.handleError(err, 'confirmRegistration')); } else { // console.log('confirm registration successful', result); resolve(result); } }))); } catch (error) { reject(this.handleError(error, 'try/catch confirm signUp')); } })); } /** * @param {?} username * @param {?} verificationCode * @param {?} password * @return {?} */ confirmPassword(username, verificationCode, password) { /** @type {?} */ let self = this; /** @type {?} */ let userData = { Username: username, Pool: this.userPool }; /** @type {?} */ let cognitoUser = new CognitoUser(userData); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => { try { cognitoUser.confirmPassword(verificationCode, password, { onFailure: (/** * @param {?} err * @return {?} */ (err) => { reject(self.handleError(err, 'confirmPassword')); }), onSuccess: (/** * @return {?} */ () => { resolve('Confirm Password SUCCESS'); }) }); } catch (error) { reject(self.handleError(error, 'try/catch confirmPassword')); } })); } /** * @param {?} username * @return {?} */ forgotPassword(username) { /** @type {?} */ let self = this; /** @type {?} */ let userData = { Username: username, Pool: this.userPool }; /** @type {?} */ let cognitoUser = new CognitoUser(userData); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => { try { cognitoUser.forgotPassword({ onFailure: (/** * @param {?} err * @return {?} */ (err) => { reject(self.handleError(err, 'forgotPassword')); }), onSuccess: (/** * @return {?} */ () => { resolve('Verification Code Sent'); }), inputVerificationCode: (/** * @return {?} */ () => { resolve('Verification Code Sent'); }) }); } catch (err) { reject(self.handleError(err, 'try/catch forgotPassword')); } })); } /** * @param {?} username * @return {?} */ resendConfirmationCode(username) { /** @type {?} */ let self = this; /** @type {?} */ let userData = { Username: username, Pool: this.userPool }; /** @type {?} */ let cognitoUser = new CognitoUser(userData); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => { try { cognitoUser.resendConfirmationCode((/** * @param {?} err * @param {?} result * @return {?} */ (err, result) => { if (err) { // let exception: ICognitoException = self.handleError(err,'resendConfirmationCode'); // console.log('error occurred while confirming registration code', exception); reject(self.handleError(err, 'resendConfirmationCode')); } else { // console.log('confirm registration successful', result); resolve(result); } })); } catch (error) { // let exception: ICognitoException = self.handleError(error,'try/catch resendConfirmationCode');//new CognitoException(error); reject(self.handleError(error, 'try/catch resendConfirmationCode')); } })); } /** * @return {?} */ signOut() { /** @type {?} */ let self = this; if (self.cognitoUser) { /** @type {?} */ let username = self.cognitoUser.getUsername(); return new Promise((/** * @param {?} resolve * @param {?} reject * @return {?} */ (resolve, reject) => { try { self.cognitoUser.signOut(); self.cognitoUserSub.next(null); self.authState.next({ state: 'signedOut', user: null }); self.resetCreds(true); self.user = AuthUser.Factory(); self.authUserState.next({ state: 'signedOut', user: null }); resolve('signOut successful'); } catch (error) { reject(self.handleError(error, 'try/catch signOut')); } })); } } } AuthService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ AuthService.ctorParameters = () => [ { type: undefined, decorators: [{ type: Inject, args: [NGX_AMPLIFY_CONFIG,] }] } ]; /** @nocollapse */ AuthService.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: function AuthService_Factory() { return new AuthService(i0.ɵɵinject(i1.NGX_AMPLIFY_CONFIG)); }, token: AuthService, providedIn: "root" }); if (false) { /** * @type {?} * @private */ AuthService.prototype.poolData; /** * @type {?} * @private */ AuthService.prototype.session; /** * @type {?} * @private */ AuthService.prototype.userPool; /** * @type {?} * @private */ AuthService.prototype.unauthCreds; /** * @type {?} * @private */ AuthService.prototype.resetting; /** * @type {?} * @private */ AuthService.prototype.authState; /** @type {?} */ AuthService.prototype.authState$; /** * @type {?} * @private */ AuthService.prototype.authUserState; /** @type {?} */ AuthService.prototype.authUserState$; /** @type {?} */ AuthService.prototype.cognitoUser; /** * @type {?} * @private */ AuthService.prototype.cognitoUserSub; /** @type {?} */ AuthService.prototype.cognitoUser$; /** @type {?} */ AuthService.prototype.user; /** * @type {?} * @private */ AuthService.prototype.config; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWFtcGxpZnkvIiwic291cmNlcyI6WyJsaWIvc2VydmljZXMvYXV0aC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFvQixrQkFBa0IsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQy9GLE9BQU8sS0FBSyxHQUFHLE1BQU0sU0FBUyxDQUFDO0FBQy9CLE9BQU8sRUFBd0IsZUFBZSxFQUFFLFdBQVcsRUFBRSxxQkFBcUIsRUFBc0Isb0JBQW9CLEVBQXNELE1BQU0sNEJBQTRCLENBQUM7QUFDck4sT0FBTyxFQUFFLGVBQWUsRUFBdUIsTUFBTSxNQUFNLENBQUM7QUFDNUQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQzs7O0FBTXZGLE1BQU0sT0FBTyxXQUFXOzs7O0lBbUJ0QixZQUNzQyxNQUF3QjtRQUF4QixXQUFNLEdBQU4sTUFBTSxDQUFrQjtRQWZ0RCxjQUFTLEdBQVksS0FBSyxDQUFDO1FBRTNCLGNBQVMsR0FBZ0MsSUFBSSxlQUFlLENBQUMsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3pHLGVBQVUsR0FBMkIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUUzRCxrQkFBYSxHQUFvQyxJQUFJLGVBQWUsQ0FBQyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDakgsbUJBQWMsR0FBK0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUl2RSxtQkFBYyxHQUFpQyxJQUFJLGVBQWUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFD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QUMsYUFBYSxDQUFDLElBQUksQ0FBQyxFQUFDLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7b0JBQzNELE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO2lCQUMvQjtnQkFDRCxPQUFPLEtBQUssRUFBRTtvQkFDWixNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO2lCQUN0RDtZQUNILENBQUMsRUFBQyxDQUFBO1NBQ0g7SUFDSCxDQUFDOzs7WUE1ZEYsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7OzRDQXFCSSxNQUFNLFNBQUMsa0JBQWtCOzs7Ozs7OztJQW5CNUIsK0JBQXVDOzs7OztJQUN2Qyw4QkFBb0M7Ozs7O0lBQ3BDLCtCQUFrQzs7Ozs7SUFDbEMsa0NBQXlCOzs7OztJQUN6QixnQ0FBbUM7Ozs7O0lBRW5DLGdDQUF5Rzs7SUFDekcsaUNBQW1FOzs7OztJQUVuRSxvQ0FBaUg7O0lBQ2pILHFDQUErRTs7SUFHL0Usa0NBQXlCOzs7OztJQUN6QixxQ0FBNkY7O0lBQzdGLG1DQUEyRTs7SUFDM0UsMkJBQWdCOzs7OztJQUdkLDZCQUE0RCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTmd4QW1wbGlmeUNvbmZpZywgTkdYX0FNUExJRllfQ09ORklHIH0gZnJvbSAnLi4vY29tbW9uL2ludGVyZmFjZXMvbmd4LWFtcGxpZnkuY29uZmlnJztcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbmltcG9ydCB7IElDb2duaXRvVXNlclBvb2xEYXRhLCBDb2duaXRvVXNlclBvb2wsIENvZ25pdG9Vc2VyLCBBdXRoZW50aWNhdGlvbkRldGFpbHMsIENvZ25pdG9Vc2VyU2Vzc2lvbiwgQ29nbml0b1VzZXJBdHRyaWJ1dGUsIElDb2duaXRvVXNlckF0dHJpYnV0ZURhdGEsIFVzZXJEYXRhLCBJU2lnblVwUmVzdWx0IH0gZnJvbSAnYW1hem9uLWNvZ25pdG8taWRlbnRpdHktanMnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBDb2duaXRvRXhjZXB0aW9uLCBDb2duaXRvUHJvZmlsZSwgQXV0aFVzZXIgfSBmcm9tICcuLi9jb21tb24vY29tbW9uLnJlc291cmNlJztcbmltcG9ydCB7IElBdXRoU3RhdGUsIElBdXRoVXNlciwgSUNvZ25pdG9DcmVkZW50aWFscywgSUNvZ25pdG9FeGNlcHRpb24sIElDb2duaXRvU2lnblVwQ3JlZGVudGlhbHMsIElDb2duaXRvUHJvZmlsZSwgSUF1dGhVc2VyU3RhdGUgfSBmcm9tICcuLi9jb21tb24vaW50ZXJmYWNlcy9jb21tb24uaW50ZXJmYWNlJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgQXV0aFNlcnZpY2Uge1xuICBwcml2YXRlIHBvb2xEYXRhOiBJQ29nbml0b1VzZXJQb29sRGF0YTtcbiAgcHJpdmF0ZSBzZXNzaW9uOiBDb2duaXRvVXNlclNlc3Npb247XG4gIHByaXZhdGUgdXNlclBvb2w6IENvZ25pdG9Vc2VyUG9vbDtcbiAgcHJpdmF0ZSB1bmF1dGhDcmVkczogYW55O1xuICBwcml2YXRlIHJlc2V0dGluZzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByaXZhdGUgYXV0aFN0YXRlOiBCZWhhdmlvclN1YmplY3Q8SUF1dGhTdGF0ZT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KHsgc3RhdGU6ICdzaWduZWRPdXQnLCB1c2VyOiBudWxsIH0pO1xuICBhdXRoU3RhdGUkOiBPYnNlcnZhYmxlPElBdXRoU3RhdGU+ID0gdGhpcy5hdXRoU3RhdGUuYXNPYnNlcnZhYmxlKCk7XG5cbiAgcHJpdmF0ZSBhdXRoVXNlclN0YXRlOiBCZWhhdmlvclN1YmplY3Q8SUF1dGhVc2VyU3RhdGU+ID0gbmV3IEJlaGF2aW9yU3ViamVjdCh7IHN0YXRlOiAnc2lnbmVkT3V0JywgdXNlcjogbnVsbCB9KTtcbiAgYXV0aFVzZXJTdGF0ZSQ6IE9ic2VydmFibGU8SUF1dGhVc2VyU3RhdGU+ID0gdGhpcy5hdXRoVXNlclN0YXRlLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIC8vIHByaXZhdGUgY29nbml0b1VzZXJTdWI6IEJlaGF2aW9yU3ViamVjdDxDb2duaXRvVXNlcj4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KG51bGwpO1xuICBjb2duaXRvVXNlcjogQ29nbml0b1VzZXI7XG4gIHByaXZhdGUgY29nbml0b1VzZXJTdWI6IEJlaGF2aW9yU3ViamVjdDxDb2duaXRvVXNlcj4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KHRoaXMuY29nbml0b1VzZXIpO1xuICBjb2duaXRvVXNlciQ6IE9ic2VydmFibGU8Q29nbml0b1VzZXI+ID0gdGhpcy5jb2duaXRvVXNlclN1Yi5hc09ic2VydmFibGUoKTtcbiAgdXNlcjogSUF1dGhVc2VyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoTkdYX0FNUExJRllfQ09ORklHKSBwcml2YXRlIGNvbmZpZzogTmd4QW1wbGlmeUNvbmZpZ1xuICApIHsgXG4gICAgQVdTLmNvbmZpZy5yZWdpb24gPSB0aGlzLmNvbmZpZy5yZWdpb247XG4gICAgQVdTLmNvbmZpZy5jcmVkZW50aWFscyA9IG5ldyBBV1MuQ29nbml0b0lkZW50aXR5Q3JlZGVudGlhbHMoe1xuICAgICAgSWRlbnRpdHlQb29sSWQ6IHRoaXMuY29uZmlnLmlkZW50aXR5UG9vbElkXG4gICAgfSk7XG5cbiAgICB0aGlzLnBvb2xEYXRhID0geyBVc2VyUG9vbElkOiBjb25maWcudXNlclBvb2xJZCwgQ2xpZW50SWQ6IHRoaXMuY29uZmlnLmFwcElkIH07XG4gICAgdGhpcy51c2VyUG9vbCA9IG5ldyBDb2duaXRvVXNlclBvb2wodGhpcy5wb29sRGF0YSk7XG4gICAgdGhpcy51c2VyID0gQXV0aFVzZXIuRmFjdG9yeSgpO1xuICAgIC8vIHRoaXMuYXV0aFVzZXJTdGF0ZS5uZXh0KHsgc3RhdGU6ICdzaWduZWRPdXQnLCB1c2VyOiB0aGlzLnVzZXIgfSk7XG4gICAgLy8gdGhpcy5yZWZyZXNoT3JSZXNldENyZWRzKCk7XG4gICAgLy8gdGhpcy5jdXJyZW50QXV0aFVzZXIgPSB0aGlzLmN1cnJlbnRBdXRoVXNlci5iaW5kKHRoaXMpO1xuICB9XG5cbiAgcHJpdmF0ZSBhdXRoRGV0YWlscyhjcmVkczogSUNvZ25pdG9DcmVkZW50aWFscyk6IEF1dGhlbnRpY2F0aW9uRGV0YWlscyB7XG4gICAgcmV0dXJuIG5ldyBBdXRoZW50aWNhdGlvbkRldGFpbHMoeyBVc2VybmFtZTogY3JlZHMudXNlcm5hbWUsIFBhc3N3b3JkOiBjcmVkcy5wYXNzd29yZCB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRDcmVkcygpIHtcbiAgICBsZXQgc2VsZiA9IHRoaXM7XG4gICAgbGV0IGpzb24gPSBzZWxmLmJ1aWxkTG9naW5zKHNlbGYuc2Vzc2lvbi5nZXRJZFRva2VuKCkuZ2V0Snd0VG9rZW4oKSk7XG4gICAgcmV0dXJuIG5ldyBBV1MuQ29nbml0b0lkZW50aXR5Q3JlZGVudGlhbHMoanNvbik7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkTG9naW5zKHRva2VuKSB7XG4gICAgbGV0IHNlbGYgPSB0aGlzO1xuICAgIGxldCBrZXkgPSBgJHtzZWxmLmNvbmZpZy5pZHBVcmx9LyR7c2VsZi5jb25maWcudXNlclBvb2xJZH1gO1xuICAgIGxldCBqc29uID0geyBJZGVudGl0eVBvb2xJZDogc2VsZi5jb25maWcuaWRlbnRpdHlQb29sSWQsIExvZ2luczoge30gfTtcbiAgICBqc29uLkxvZ2luc1trZXldID0gdG9rZW47XG4gICAgcmV0dXJuIGpzb247XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUVycm9yKGVycm9yOiBhbnksIGNhbGxlcjogc3RyaW5nKSB7XG4gICAgbGV0IGV4Y2VwdGlvbjogSUNvZ25pdG9FeGNlcHRpb24gPSBuZXcgQ29nbml0b0V4Y2VwdGlvbihlcnJvcik7XG4gICAgY29uc29sZS5lcnJvcihgQVdTIENvZ25pdG8gU2VydmljZTo6aGFuZ