ngx-amplify
Version:
An angular library for integration AWS cloud services (cognito, s3)
811 lines • 68.4 kB
JavaScript
/**
* @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