@nowzoo/ngx-firebase-auth
Version:
Angular components for Firebase email-first sign in and out-of-band (oob) actions (reset password, etc).
265 lines (258 loc) • 23.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { AngularFireAuth } from 'angularfire2/auth';
import { NgxFirebaseAuthFormHelper } from '../../form-helper';
import { NgxFirebaseAuthService } from '../../ngx-firebase-auth.service';
import { screenAnimation } from '../../shared';
export class OobResetPasswordComponent {
/**
* @param {?} _afAuth
* @param {?} _authService
*/
constructor(_afAuth, _authService) {
this._afAuth = _afAuth;
this._authService = _authService;
this.success = new EventEmitter();
this.screen = 'wait';
this.submitting = false;
this.formId = 'ngx-firebase-auth-oob-reset-password-';
this.unhandledError = null;
this.cred = null;
}
/**
* @return {?}
*/
get auth() {
return this._afAuth.auth;
}
/**
* @return {?}
*/
get authService() {
return this._authService;
}
/**
* @return {?}
*/
ngOnInit() {
/** @type {?} */
const remembered = this.authService.getRemembered();
this.emailFc = new FormControl('');
this.passwordFc = new FormControl('', { validators: [Validators.required] });
this.rememberFc = new FormControl(remembered.remember);
this.fg = new FormGroup({ email: this.emailFc, password: this.passwordFc, remember: this.rememberFc });
this.auth.checkActionCode(this.oobCode)
.then((result) => {
this.info = result;
this.emailFc.setValue(result.data.email);
this.screen = 'form';
})
.catch((error) => {
this.unhandledError = error;
this.screen = 'error';
});
}
/**
* @return {?}
*/
submit() {
this.submitting = true;
this.auth.confirmPasswordReset(this.oobCode, this.passwordFc.value)
.then(() => {
return this.auth.signInWithEmailAndPassword(this.info.data.email, this.passwordFc.value);
})
.then((cred) => {
this.cred = cred;
return this.authService.setRemembered(this.rememberFc.value === true, this.info.data.email);
})
.then(() => {
this.screen = 'success';
this.success.emit({
mode: 'resetPassword',
info: this.info,
cred: this.cred,
user: this.cred.user
});
})
.catch((error) => {
this.submitting = false;
this.passwordFc.markAsDirty();
this.passwordFc.markAsTouched();
switch (error.code) {
case 'auth/weak-password':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code);
break;
default:
this.unhandledError = error;
this.screen = 'error';
break;
}
});
}
}
OobResetPasswordComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-oob-reset-password',
template: `<div *ngIf="'wait' === screen" []="'in'">
<div class="alert alert-secondary">
<i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
Please wait...
</div>
</div>
<div *ngIf="'success' === screen" []="'in'">
<div class="alert alert-success">
<i class="fas fa-check fa-fw" aria-hidden="true"></i>
Welcome, {{cred.user.displayName}}!
Your new password has been saved and you are signed in.
</div>
</div>
<div *ngIf="screen === 'error'" []="'in'">
<div class="alert alert-danger">
<p>
<i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
Woops! An error occurred.
</p>
<div [ngSwitch]="unhandledError.code">
<p class="mb-0" *ngSwitchCase="'auth/expired-action-code'">
The reset password link you used has expired.
</p>
<p class="mb-0" *ngSwitchCase="'auth/invalid-action-code'">
The reset password link you used is not valid. This may be because it
has already been used.
</p>
<p class="mb-0" *ngSwitchCase="'auth/user-disabled'">
The account associated with the reset password link you used has been disabled.
</p>
<p class="mb-0" *ngSwitchCase="'auth/user-not-found'">
The account associated with the reset password link you used has been removed.
</p>
<div *ngSwitchDefault>
<p>Code: {{unhandledError.code}}</p>
<p class="mb-0">
Message: {{unhandledError.message}}
</p>
</div>
</div>
</div>
</div>
<div *ngIf="'form' === screen" []="'in'">
<form [formGroup]="fg" (ngSubmit)="submit()">
<div class="form-group">
<label [attr.for]="formId + 'email'">Email Address</label>
<input
readonly
#emailInput
[attr.id]="formId + 'email'"
[attr.aria-describedby]="formId + 'email'"
type="email"
autocomplete="email"
placeholder="Email Address"
formControlName="email"
class="form-control">
<small class="text-muted form-text" [attr.id]="formId + 'email'" >
You are resetting the password for {{emailFc.value}}.
</small>
</div>
<div class="form-group">
<div class="d-flex justify-content-between align-items-end">
<label [attr.for]="formId + 'password'">Password</label>
<small>
<a (click)="$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type ? 'text' : 'password'"
href="#" tabindex="-1" class="d-inline-block">
<span *ngIf="'password' === passwordInput.type">Show</span>
<span *ngIf="'text' === passwordInput.type">Hide</span>
</a>
</small>
</div>
<input
#passwordInput
[attr.id]="formId + 'password'"
[attr.aria-describedby]="formId + 'password-help'"
type="password"
formControlName="password"
placeholder="Password"
autocomplete="password"
class="form-control"
[class.is-invalid]="passwordFc.touched && passwordFc.invalid">
<div class="invalid-feedback" *ngIf="passwordFc.touched && passwordFc.hasError('required')">
Required.
</div>
<div class="invalid-feedback" *ngIf="passwordFc.touched && passwordFc.hasError('auth/weak-password')">
That password is too weak.
</div>
<small [attr.id]="formId + 'password-help'" class="form-text text-muted">
Please choose a strong password.
</small>
</div>
<div class="form-group">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
[value]="true"
formControlName="remember"
[attr.id]="formId + 'remember'">
<label class="form-check-label" [attr.for]="formId + 'remember'">
Remember me on this device.
</label>
</div>
</div>
<div class="form-group">
<button type="submit"
class="btn btn-success btn-block"
[disabled]="fg.invalid || submitting">
<i class="fas fa-save fa-fw" aria-hidden="true"></i>
Save Password and Sign In
</button>
</div>
</form>
</div>
`,
styles: [``],
animations: [screenAnimation]
},] },
];
/** @nocollapse */
OobResetPasswordComponent.ctorParameters = () => [
{ type: AngularFireAuth },
{ type: NgxFirebaseAuthService }
];
OobResetPasswordComponent.propDecorators = {
oobCode: [{ type: Input }],
success: [{ type: Output }]
};
if (false) {
/** @type {?} */
OobResetPasswordComponent.prototype.oobCode;
/** @type {?} */
OobResetPasswordComponent.prototype.success;
/** @type {?} */
OobResetPasswordComponent.prototype.screen;
/** @type {?} */
OobResetPasswordComponent.prototype.info;
/** @type {?} */
OobResetPasswordComponent.prototype.submitting;
/** @type {?} */
OobResetPasswordComponent.prototype.formId;
/** @type {?} */
OobResetPasswordComponent.prototype.fg;
/** @type {?} */
OobResetPasswordComponent.prototype.emailFc;
/** @type {?} */
OobResetPasswordComponent.prototype.passwordFc;
/** @type {?} */
OobResetPasswordComponent.prototype.rememberFc;
/** @type {?} */
OobResetPasswordComponent.prototype.unhandledError;
/** @type {?} */
OobResetPasswordComponent.prototype.cred;
/** @type {?} */
OobResetPasswordComponent.prototype._afAuth;
/** @type {?} */
OobResetPasswordComponent.prototype._authService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib29iLXJlc2V0LXBhc3N3b3JkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvIiwic291cmNlcyI6WyJsaWIvb29iL29vYi1yZXNldC1wYXNzd29yZC9vb2ItcmVzZXQtcGFzc3dvcmQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9FLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUdwRCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBZ0kvQyxNQUFNOzs7OztJQWVKLFlBQ1UsU0FDRTtRQURGLFlBQU8sR0FBUCxPQUFPO1FBQ0wsaUJBQVksR0FBWixZQUFZO3VCQWRzQyxJQUFJLFlBQVksRUFBRTtzQkFFaEMsTUFBTTswQkFFekMsS0FBSztzQkFDVCx1Q0FBdUM7OEJBS25CLElBQUk7b0JBQ0wsSUFBSTtLQUkzQjs7OztJQUVMLElBQUksSUFBSTtRQUNOLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztLQUMxQjs7OztJQUNELElBQUksV0FBVztRQUNiLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0tBQzFCOzs7O0lBRUQsUUFBUTs7UUFDTixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3BELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxXQUFX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LElBQUksQ0FBQyxjQUFjLEdBQUcsS0FBSyxDQUFDO29CQUM1QixJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQztvQkFDdEIsS0FBSyxDQUFDO2FBQ1Q7U0FDRixDQUFDLENBQUM7S0FDTjs7O1lBNU1GLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsc0NBQXNDO2dCQUNoRCxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXdIWDtnQkFDQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ1osVUFBVSxFQUFFLENBQUMsZUFBZSxDQUFDO2FBQzlCOzs7O1lBcElRLGVBQWU7WUFJZixzQkFBc0I7OztzQkFtSTVCLEtBQUs7c0JBQ0wsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIgfSBmcm9tICcuLi8uLi9mb3JtLWhlbHBlcic7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbmd4LWZpcmViYXNlLWF1dGguc2VydmljZSc7XG5pbXBvcnQgeyBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1vb2ItcmVzZXQtcGFzc3dvcmQnLFxuICB0ZW1wbGF0ZTogYDxkaXYgKm5nSWY9XCInd2FpdCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXNlY29uZGFyeVwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNwaW4gZmEtc3Bpbm5lciBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBQbGVhc2Ugd2FpdC4uLlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3N1Y2Nlc3MnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1zdWNjZXNzXCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgV2VsY29tZSwge3tjcmVkLnVzZXIuZGlzcGxheU5hbWV9fSFcbiAgICBZb3VyIG5ldyBwYXNzd29yZCBoYXMgYmVlbiBzYXZlZCBhbmQgeW91IGFyZSBzaWduZWQgaW4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdlcnJvcidcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8cD5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgV29vcHMhIEFuIGVycm9yIG9jY3VycmVkLlxuICAgIDwvcD5cbiAgICA8ZGl2IFtuZ1N3aXRjaF09XCJ1bmhhbmRsZWRFcnJvci5jb2RlXCI+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvZXhwaXJlZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHJlc2V0IHBhc3N3b3JkIGxpbmsgeW91IHVzZWQgaGFzIGV4cGlyZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvaW52YWxpZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHJlc2V0IHBhc3N3b3JkIGxpbmsgeW91IHVzZWQgaXMgbm90IHZhbGlkLiBUaGlzIG1heSBiZSBiZWNhdXNlIGl0XG4gICAgICAgIGhhcyBhbHJlYWR5IGJlZW4gdXNlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC91c2VyLWRpc2FibGVkJ1wiPlxuICAgICAgICBUaGUgYWNjb3VudCBhc3NvY2lhdGVkIHdpdGggdGhlIHJlc2V0IHBhc3N3b3JkIGxpbmsgeW91IHVzZWQgaGFzIGJlZW4gZGlzYWJsZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1ub3QtZm91bmQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBoYXMgYmVlbiByZW1vdmVkLlxuICAgICAgPC9wPlxuICAgICAgPGRpdiAqbmdTd2l0Y2hEZWZhdWx0PlxuICAgICAgICA8cD5Db2RlOiB7e3VuaGFuZGxlZEVycm9yLmNvZGV9fTwvcD5cbiAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+XG4gICAgICAgICAgTWVzc2FnZToge3t1bmhhbmRsZWRFcnJvci5tZXNzYWdlfX1cbiAgICAgICAgPC9wPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuPGRpdiAqbmdJZj1cIidmb3JtJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCIgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCI+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiPkVtYWlsIEFkZHJlc3M8L2xhYmVsPlxuXG4gICAgICA8aW5wdXRcbiAgICAgICAgcmVhZG9ubHlcbiAgICAgICAgI2VtYWlsSW5wdXRcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICAgIGF1dG9jb21wbGV0ZT1cImVtYWlsXCJcbiAgICAgICAgcGxhY2Vob2xkZXI9XCJFbWFpbCBBZGRyZXNzXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiPlxuICAgICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBmb3JtLXRleHRcIiBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCIgPlxuICAgICAgICBZb3UgYXJlIHJlc2V0dGluZyB0aGUgcGFzc3dvcmQgZm9yIHt7ZW1haWxGYy52YWx1ZX19LlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWVuZFwiPlxuICAgICAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICdwYXNzd29yZCdcIj5QYXNzd29yZDwvbGFiZWw+XG4gICAgICAgIDxzbWFsbD5cbiAgICAgICAgICA8YSAoY2xpY2spPVwiJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IHBhc3N3b3JkSW5wdXQudHlwZSA9ICdwYXNzd29yZCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZSAgPyAndGV4dCcgOiAncGFzc3dvcmQnXCJcbiAgICAgICAgICAgIGhyZWY9XCIjXCIgdGFiaW5kZXg9XCItMVwiIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2tcIj5cbiAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+U2hvdzwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3RleHQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5IaWRlPC9zcGFuPlxuICAgICAgICAgIDwvYT5cbiAgICAgICAgPC9zbWFsbD5cbiAgICAgIDwvZGl2PlxuICAgICAgPGlucHV0XG4gICAgICAgICNwYXNzd29yZElucHV0XG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdwYXNzd29yZCdcIlxuICAgICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiXG4gICAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInBhc3N3b3JkXCJcbiAgICAgICAgcGxhY2Vob2xkZXI9XCJQYXNzd29yZFwiXG4gICAgICAgIGF1dG9jb21wbGV0ZT1cInBhc3N3b3JkXCJcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5pbnZhbGlkXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiICpuZ0lmPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgICAgUmVxdWlyZWQuXG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcignYXV0aC93ZWFrLXBhc3N3b3JkJylcIj5cbiAgICAgICAgVGhhdCBwYXNzd29yZCBpcyB0b28gd2Vhay5cbiAgICAgIDwvZGl2PlxuICAgICAgPHNtYWxsIFthdHRyLmlkXT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiIGNsYXNzPVwiZm9ybS10ZXh0IHRleHQtbXV0ZWRcIj5cbiAgICAgICAgUGxlYXNlIGNob29zZSBhIHN0cm9uZyBwYXNzd29yZC5cbiAgICAgIDwvc21hbGw+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiXG4gICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICBbdmFsdWVdPVwidHJ1ZVwiXG4gICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVtZW1iZXJcIlxuICAgICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgICAgUmVtZW1iZXIgbWUgb24gdGhpcyBkZXZpY2UuXG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXN1Y2Nlc3MgYnRuLWJsb2NrXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1zYXZlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICBTYXZlIFBhc3N3b3JkIGFuZCBTaWduIEluXG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9mb3JtPlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIE9vYlJlc2V0UGFzc3dvcmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIEBJbnB1dCgpIG9vYkNvZGU6IHN0cmluZztcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxJTmd4RmlyZWJhc2VBdXRoT29iU3VjY2Vzcz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgc2NyZWVuOiAnd2FpdCcgfCAnZm9ybScgfCAnZXJyb3InIHwgJ3N1Y2Nlc3MnID0gJ3dhaXQnO1xuICBpbmZvOiBhdXRoLkFjdGlvbkNvZGVJbmZvO1xuICBzdWJtaXR0aW5nID0gZmFsc2U7XG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1vb2ItcmVzZXQtcGFzc3dvcmQtJztcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHBhc3N3b3JkRmM6IEZvcm1Db250cm9sO1xuICByZW1lbWJlckZjOiBGb3JtQ29udHJvbDtcbiAgdW5oYW5kbGVkRXJyb3I6IGF1dGguRXJyb3IgPSBudWxsO1xuICBjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsID0gbnVsbDtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSxcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuICBnZXQgYXV0aFNlcnZpY2UoKTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSB7XG4gICAgcmV0dXJuIHRoaXMuX2F1dGhTZXJ2aWNlO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgY29uc3QgcmVtZW1iZXJlZCA9IHRoaXMuYXV0aFNlcnZpY2UuZ2V0UmVtZW1iZXJlZCgpO1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbCgnJyk7XG4gICAgdGhpcy5wYXNzd29yZEZjID0gbmV3IEZvcm1Db250cm9sKCcnLCB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWRdfSk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHJlbWVtYmVyZWQucmVtZW1iZXIpO1xuICAgIHRoaXMuZmcgPSBuZXcgRm9ybUdyb3VwKHtlbWFpbDogdGhpcy5lbWFpbEZjLCBwYXNzd29yZDogdGhpcy5wYXNzd29yZEZjLCByZW1lbWJlcjogdGhpcy5yZW1lbWJlckZjfSk7XG4gICAgdGhpcy5hdXRoLmNoZWNrQWN0aW9uQ29kZSh0aGlzLm9vYkNvZGUpXG4gICAgICAudGhlbigocmVzdWx0OiBhdXRoLkFjdGlvbkNvZGVJbmZvKSA9PiB7XG4gICAgICAgIHRoaXMuaW5mbyA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5lbWFpbEZjLnNldFZhbHVlKHJlc3VsdC5kYXRhLmVtYWlsKTtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZm9ybSc7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnVuaGFuZGxlZEVycm9yID0gZXJyb3I7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgIH0pO1xuICB9XG5cbiAgc3VibWl0KCkge1xuICAgIHRoaXMuc3VibWl0dGluZyA9IHRydWU7XG4gICAgdGhpcy5hdXRoLmNvbmZpcm1QYXNzd29yZFJlc2V0KHRoaXMub29iQ29kZSwgdGhpcy5wYXNzd29yZEZjLnZhbHVlKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLnNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkKHRoaXMuaW5mby5kYXRhLmVtYWlsLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKChjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsKSA9PiB7XG4gICAgICAgIHRoaXMuY3JlZCA9IGNyZWQ7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCB0aGlzLmluZm8uZGF0YS5lbWFpbCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdzdWNjZXNzJztcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoe1xuICAgICAgICAgIG1vZGU6ICdyZXNldFBhc3N3b3JkJyxcbiAgICAgICAgICBpbmZvOiB0aGlzLmluZm8sXG4gICAgICAgICAgY3JlZDogdGhpcy5jcmVkLFxuICAgICAgICAgIHVzZXI6IHRoaXMuY3JlZC51c2VyXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy5zdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLnBhc3N3b3JkRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlICdhdXRoL3dlYWstcGFzc3dvcmQnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLnBhc3N3b3JkRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRoaXMudW5oYW5kbGVkRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG59XG4iXX0=