UNPKG

@nowzoo/ngx-firebase-auth

Version:

Angular components for Firebase email-first sign in and out-of-band (oob) actions (reset password, etc).

265 lines (263 loc) 23.7 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { Component, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { AngularFireAuth } from 'angularfire2/auth'; import { fadeInOutAnimation } from '../../shared'; import { NgxFirebaseAuthFormHelper } from '../../form-helper'; import { NgxFirebaseAuthService } from '../../ngx-firebase-auth.service'; export class SignUpFormComponent { /** * @param {?} _afAuth * @param {?} _authService */ constructor(_afAuth, _authService) { this._afAuth = _afAuth; this._authService = _authService; this.rememberChange = new EventEmitter(); this.success = new EventEmitter(); this.error = new EventEmitter(); this.formId = 'ngx-firebase-auth-sign-up-form-'; this.submitting = false; } /** * @return {?} */ get auth() { return this._afAuth.auth; } /** * @return {?} */ get authService() { return this._authService; } /** * @return {?} */ ngOnInit() { this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] }); this.passwordFc = new FormControl('', { validators: [Validators.required] }); this.nameFc = new FormControl('', { validators: [Validators.required, NgxFirebaseAuthFormHelper.requiredNonEmpty] }); this.rememberFc = new FormControl(this.remember); this.rememberFc.valueChanges.subscribe(val => this.rememberChange.emit(val)); this.fg = new FormGroup({ email: this.emailFc, password: this.passwordFc, name: this.nameFc, remember: this.rememberFc }); } /** * @return {?} */ ngAfterViewInit() { this.passwordInput.nativeElement.focus(); } /** * @return {?} */ submit() { this.submitting = true; /** @type {?} */ let cred; this.auth.fetchSignInMethodsForEmail(this.email) .then((results) => { if (results.length > 0) { return Promise.reject({ code: 'ngx-firebase-auth/account-exists' }); } return this.auth.createUserWithEmailAndPassword(this.email, this.passwordFc.value); }) .then(result => { cred = result; return cred.user.updateProfile({ displayName: this.nameFc.value.trim(), photoURL: null }); }) .then(() => { return this.authService.setRemembered(this.rememberFc.value === true, this.email); }) .then(() => { this.success.emit(cred); }) .catch(error => { this.submitting = false; this.emailFc.markAsDirty(); this.emailFc.markAsTouched(); this.passwordFc.markAsDirty(); this.passwordFc.markAsTouched(); switch (error.code) { case 'auth/invalid-email': case 'ngx-firebase-auth/account-exists': NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code); break; case 'auth/weak-password': NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code); break; default: this.error.emit(error); break; } }); } } SignUpFormComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-firebase-auth-sign-up-form', template: `<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"> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="emailFc.hasError('required')"> Required. </div> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="emailFc.hasError('email')"> Invalid email. </div> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="emailFc.hasError('auth/invalid-email')"> Invalid email. </div> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="emailFc.hasError('ngx-firebase-auth/account-exists')"> We found an account with that email address. <a routerLink="." [queryParams]="{action: 'signIn'}">Sign In</a> </div> <small class="text-muted form-text" [attr.id]="formId + 'email'" > Not your email address? <a routerLink="." [queryParams]="{action: 'signIn'}">Go Back</a> </small> </div> <div class="form-group"> <div class="d-flex justify-content-between align-items-end"> <label [attr.for]="formId + 'password'">Choose 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="Choose Password" autocomplete="password" class="form-control" [class.is-invalid]="passwordFc.touched && passwordFc.invalid"> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="passwordFc.touched && passwordFc.hasError('required')"> Required. </div> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="passwordFc.touched && passwordFc.hasError('auth/wrong-password')"> Wrong password. </div> <small [attr.id]="formId + 'password-help'" class="form-text text-muted"> Please choose a strong password. </small> </div> <div class="form-group"> <label [attr.for]="formId + 'name'">Your Name</label> <input [attr.id]="formId + 'name'" type="text" formControlName="name" placeholder="Your Name" class="form-control" [class.is-invalid]="nameFc.touched && nameFc.invalid"> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="nameFc.touched && nameFc.hasError('required')"> Required. </div> </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-lock fa-fw" aria-hidden="true"></i> Create Account </button> </div> </form> `, styles: [``], animations: [fadeInOutAnimation] },] }, ]; /** @nocollapse */ SignUpFormComponent.ctorParameters = () => [ { type: AngularFireAuth }, { type: NgxFirebaseAuthService } ]; SignUpFormComponent.propDecorators = { passwordInput: [{ type: ViewChild, args: ['passwordInput',] }], email: [{ type: Input }], remember: [{ type: Input }], rememberChange: [{ type: Output }], success: [{ type: Output }], error: [{ type: Output }] }; if (false) { /** @type {?} */ SignUpFormComponent.prototype.passwordInput; /** @type {?} */ SignUpFormComponent.prototype.email; /** @type {?} */ SignUpFormComponent.prototype.remember; /** @type {?} */ SignUpFormComponent.prototype.rememberChange; /** @type {?} */ SignUpFormComponent.prototype.success; /** @type {?} */ SignUpFormComponent.prototype.error; /** @type {?} */ SignUpFormComponent.prototype.formId; /** @type {?} */ SignUpFormComponent.prototype.submitting; /** @type {?} */ SignUpFormComponent.prototype.fg; /** @type {?} */ SignUpFormComponent.prototype.emailFc; /** @type {?} */ SignUpFormComponent.prototype.passwordFc; /** @type {?} */ SignUpFormComponent.prototype.nameFc; /** @type {?} */ SignUpFormComponent.prototype.rememberFc; /** @type {?} */ SignUpFormComponent.prototype._afAuth; /** @type {?} */ SignUpFormComponent.prototype._authService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbi11cC1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvIiwic291cmNlcyI6WyJsaWIvc2lnbi1pbi9zaWduLXVwLWZvcm0vc2lnbi11cC1mb3JtLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBeUIsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNySCxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFHcEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2xELE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzlELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBZ0h6RSxNQUFNOzs7OztJQWdCSixZQUNVLFNBQ0E7UUFEQSxZQUFPLEdBQVAsT0FBTztRQUNQLGlCQUFZLEdBQVosWUFBWTs4QkFiNEIsSUFBSSxZQUFZLEVBQUU7dUJBQ2IsSUFBSSxZQUFZLEVBQUU7cUJBQzdCLElBQUksWUFBWSxFQUFFO3NCQUVyRCxpQ0FBaUM7MEJBQzdCLEtBQUs7S0FTYjs7OztJQUVMLElBQUksSUFBSTtRQUNOLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztLQUMxQjs7OztJQUVELElBQUksV0FBVztRQUNiLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0tBQzFCOzs7O0lBR0QsUUFBUTtRQUNOLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQzVCLElBQUksQ0FBQyxLQUFLLEVBQ1YsRUFBQyxVQUFVLEVB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Q0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNoQyxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDbkIsS0FBSyxvQkFBb0IsQ0FBQztnQkFDMUIsS0FBSyxrQ0FBa0M7b0JBQ3JDLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUN6RSxLQUFLLENBQUM7Z0JBQ1IsS0FBSyxvQkFBb0I7b0JBQ3ZCLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUM1RSxLQUFLLENBQUM7Z0JBQ1I7b0JBQ0UsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3ZCLEtBQUssQ0FBQzthQUNUO1NBQ0YsQ0FBQyxDQUFDO0tBQ047OztZQTNNRixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLGdDQUFnQztnQkFDMUMsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0F5R1g7Z0JBQ0MsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNaLFVBQVUsRUFBRSxDQUFFLGtCQUFrQixDQUFFO2FBQ25DOzs7O1lBcEhRLGVBQWU7WUFLZixzQkFBc0I7Ozs0QkFrSDVCLFNBQVMsU0FBQyxlQUFlO29CQUN6QixLQUFLO3VCQUNMLEtBQUs7NkJBQ0wsTUFBTTtzQkFDTixNQUFNO29CQUNOLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcblxuaW1wb3J0IHsgZmFkZUluT3V0QW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIgfSBmcm9tICcuLi8uLi9mb3JtLWhlbHBlcic7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbmd4LWZpcmViYXNlLWF1dGguc2VydmljZSc7XG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLXVwLWZvcm0nLFxuICB0ZW1wbGF0ZTogYDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIiAobmdTdWJtaXQpPVwic3VibWl0KClcIj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICdlbWFpbCdcIj5FbWFpbCBBZGRyZXNzPC9sYWJlbD5cbiAgICA8aW5wdXRcbiAgICAgIHJlYWRvbmx5XG4gICAgICAjZW1haWxJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cImVtYWlsXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiRW1haWwgQWRkcmVzc1wiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2VtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC9pbnZhbGlkLWVtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignbmd4LWZpcmViYXNlLWF1dGgvYWNjb3VudC1leGlzdHMnKVwiPlxuICAgICAgV2UgZm91bmQgYW4gYWNjb3VudCB3aXRoIHRoYXQgZW1haWwgYWRkcmVzcy5cbiAgICAgIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW4nfVwiPlNpZ24gSW48L2E+XG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBmb3JtLXRleHRcIiBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCIgPlxuICAgICAgTm90IHlvdXIgZW1haWwgYWRkcmVzcz9cbiAgICAgIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW4nfVwiPkdvIEJhY2s8L2E+XG4gICAgPC9zbWFsbD5cbiAgPC9kaXY+XG5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWVuZFwiPlxuICAgICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncGFzc3dvcmQnXCI+Q2hvb3NlIFBhc3N3b3JkPC9sYWJlbD5cbiAgICAgIDxzbWFsbD5cbiAgICAgICAgPGEgKGNsaWNrKT1cIiRldmVudC5wcmV2ZW50RGVmYXVsdCgpOyBwYXNzd29yZElucHV0LnR5cGUgPSAncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGUgID8gJ3RleHQnIDogJ3Bhc3N3b3JkJ1wiXG4gICAgICAgICAgaHJlZj1cIiNcIiB0YWJpbmRleD1cIi0xXCIgY2xhc3M9XCJkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+U2hvdzwvc3Bhbj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIid0ZXh0JyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+SGlkZTwvc3Bhbj5cbiAgICAgICAgPC9hPlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cbiAgICA8aW5wdXRcbiAgICAgICNwYXNzd29yZElucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncGFzc3dvcmQnXCJcbiAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCJcbiAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJwYXNzd29yZFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkNob29zZSBQYXNzd29yZFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJwYXNzd29yZFwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5pbnZhbGlkXCI+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdhdXRoL3dyb25nLXBhc3N3b3JkJylcIj5cbiAgICAgIFdyb25nIHBhc3N3b3JkLlxuICAgIDwvZGl2PlxuICAgIDxzbWFsbCBbYXR0ci5pZF09XCJmb3JtSWQgKyAncGFzc3dvcmQtaGVscCdcIiBjbGFzcz1cImZvcm0tdGV4dCB0ZXh0LW11dGVkXCI+XG4gICAgICBQbGVhc2UgY2hvb3NlIGEgc3Ryb25nIHBhc3N3b3JkLlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ25hbWUnXCI+WW91ciBOYW1lPC9sYWJlbD5cbiAgICA8aW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICduYW1lJ1wiXG4gICAgICB0eXBlPVwidGV4dFwiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJuYW1lXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiWW91ciBOYW1lXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cIm5hbWVGYy50b3VjaGVkICYmIG5hbWVGYy5pbnZhbGlkXCI+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwibmFtZUZjLnRvdWNoZWQgJiYgbmFtZUZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgIDxpbnB1dFxuICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxuICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICBbdmFsdWVdPVwidHJ1ZVwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJlbWVtYmVyXCJcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgIFJlbWVtYmVyIG1lIG9uIHRoaXMgZGV2aWNlLlxuICAgICAgPC9sYWJlbD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCJcbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzIGJ0bi1ibG9ja1wiXG4gICAgICBbZGlzYWJsZWRdPVwiZmcuaW52YWxpZCB8fCBzdWJtaXR0aW5nXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgQ3JlYXRlIEFjY291bnRcbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Zvcm0+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFsgZmFkZUluT3V0QW5pbWF0aW9uIF1cbn0pXG5leHBvcnQgY2xhc3MgU2lnblVwRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgQFZpZXdDaGlsZCgncGFzc3dvcmRJbnB1dCcpIHBhc3N3b3JkSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpIGVtYWlsOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHJlbWVtYmVyOiBib29sZWFuO1xuICBAT3V0cHV0KCkgcmVtZW1iZXJDaGFuZ2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVycm9yOiBFdmVudEVtaXR0ZXI8YXV0aC5FcnJvcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLXNpZ24tdXAtZm9ybS0nO1xuICBzdWJtaXR0aW5nID0gZmFsc2U7XG4gIGZnOiBGb3JtR3JvdXA7XG4gIGVtYWlsRmM6IEZvcm1Db250cm9sO1xuICBwYXNzd29yZEZjOiBGb3JtQ29udHJvbDtcbiAgbmFtZUZjOiBGb3JtQ29udHJvbDtcbiAgcmVtZW1iZXJGYzogRm9ybUNvbnRyb2w7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2FmQXV0aDogQW5ndWxhckZpcmVBdXRoLFxuICAgIHByaXZhdGUgX2F1dGhTZXJ2aWNlOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlXG4gICkgeyB9XG5cbiAgZ2V0IGF1dGgoKTogYXV0aC5BdXRoIHtcbiAgICByZXR1cm4gdGhpcy5fYWZBdXRoLmF1dGg7XG4gIH1cblxuICBnZXQgYXV0aFNlcnZpY2UoKTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSB7XG4gICAgcmV0dXJuIHRoaXMuX2F1dGhTZXJ2aWNlO1xuICB9XG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmVtYWlsRmMgPSBuZXcgRm9ybUNvbnRyb2woXG4gICAgICB0aGlzLmVtYWlsLFxuICAgICAge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLmVtYWlsXX1cbiAgICApO1xuICAgIHRoaXMucGFzc3dvcmRGYyA9IG5ldyBGb3JtQ29udHJvbCgnJywge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkXX0pO1xuICAgIHRoaXMubmFtZUZjID0gbmV3IEZvcm1Db250cm9sKCcnLCB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIucmVxdWlyZWROb25FbXB0eV19KTtcbiAgICB0aGlzLnJlbWVtYmVyRmMgPSBuZXcgRm9ybUNvbnRyb2wodGhpcy5yZW1lbWJlcik7XG4gICAgdGhpcy5yZW1lbWJlckZjLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUodmFsID0+IHRoaXMucmVtZW1iZXJDaGFuZ2UuZW1pdCh2YWwpKTtcbiAgICB0aGlzLmZnID0gbmV3IEZvcm1Hcm91cCh7XG4gICAgICBlbWFpbDogdGhpcy5lbWFpbEZjLFxuICAgICAgcGFzc3dvcmQ6IHRoaXMucGFzc3dvcmRGYyxcbiAgICAgIG5hbWU6IHRoaXMubmFtZUZjLFxuICAgICAgcmVtZW1iZXI6IHRoaXMucmVtZW1iZXJGY1xuICAgIH0pO1xuICB9XG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLnBhc3N3b3JkSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICB9XG5cbiAgc3VibWl0KCkge1xuXG4gICAgdGhpcy5zdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICBsZXQgY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbDtcbiAgICB0aGlzLmF1dGguZmV0Y2hTaWduSW5NZXRob2RzRm9yRW1haWwodGhpcy5lbWFpbClcbiAgICAgIC50aGVuKChyZXN1bHRzKSA9PiB7XG4gICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3Qoe1xuICAgICAgICAgICAgY29kZTogJ25neC1maXJlYmFzZS1hdXRoL2FjY291bnQtZXhpc3RzJ1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGguY3JlYXRlVXNlcldpdGhFbWFpbEFuZFBhc3N3b3JkKHRoaXMuZW1haWwsIHRoaXMucGFzc3dvcmRGYy52YWx1ZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgY3JlZCA9IHJlc3VsdDtcbiAgICAgICAgcmV0dXJuIGNyZWQudXNlci51cGRhdGVQcm9maWxlKHtkaXNwbGF5TmFtZTogdGhpcy5uYW1lRmMudmFsdWUudHJpbSgpLCBwaG90b1VSTDogbnVsbH0pO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aFNlcnZpY2Uuc2V0UmVtZW1iZXJlZCh0aGlzLnJlbWVtYmVyRmMudmFsdWUgPT09IHRydWUsIHRoaXMuZW1haWwpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoY3JlZCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgdGhpcy5zdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICB0aGlzLnBhc3N3b3JkRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgc3dpdGNoIChlcnJvci5jb2RlKSB7XG4gICAgICAgICAgY2FzZSAnYXV0aC9pbnZhbGlkLWVtYWlsJzpcbiAgICAgICAgICBjYXNlICduZ3gtZmlyZWJhc2UtYXV0aC9hY2NvdW50LWV4aXN0cyc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMuZW1haWxGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdhdXRoL3dlYWstcGFzc3dvcmQnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLnBhc3N3b3JkRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRoaXMuZXJyb3IuZW1pdChlcnJvcik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxufVxuIl19