UNPKG

@nowzoo/ngx-firebase-auth

Version:

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

285 lines (279 loc) 25.2 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 { NgxFirebaseAuthFormHelper } from '../../form-helper'; import { NgxFirebaseAuthService } from '../../ngx-firebase-auth.service'; import { getOAuthProviderIcon, getOAuthProviderName, fadeInOutAnimation } from '../../shared'; export class SignInFormComponent { /** * @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-in-form-'; this.submitting = false; this.methodsForEmail = []; this.getOAuthProviderIcon = getOAuthProviderIcon; this.getOAuthProviderName = getOAuthProviderName; } /** * @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.rememberFc = new FormControl(this.remember); this.rememberFc.valueChanges.subscribe(val => this.rememberChange.emit(val)); this.fg = new FormGroup({ email: this.emailFc, password: this.passwordFc, remember: this.rememberFc }); } /** * @return {?} */ ngAfterViewInit() { this.passwordInput.nativeElement.focus(); } /** * @return {?} */ submit() { /** @type {?} */ const email = this.emailFc.value.trim(); this.submitting = true; this.methodsForEmail = []; /** @type {?} */ let cred; this.auth.fetchSignInMethodsForEmail(email) .then(results => { this.methodsForEmail = results; if (results.length === 0) { return Promise.reject({ code: 'auth/user-not-found' }); } if (results.indexOf('password') === -1) { return Promise.reject({ code: 'ngx-firebase-auth/no-password', }); } return this.auth.signInWithEmailAndPassword(email, this.passwordFc.value); }) .then(result => { cred = result; return this.authService.setRemembered(this.rememberFc.value === true, 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 'auth/user-not-found': case 'auth/user-disabled': case 'ngx-firebase-auth/no-password': NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code); break; case 'auth/wrong-password': NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code); break; default: this.error.emit(error); break; } }); } } SignInFormComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-firebase-auth-sign-in-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('auth/user-not-found')"> We could not find an account with that email address. <a routerLink="." [queryParams]="{action: 'signIn'}">Create Account</a> </div> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="emailFc.hasError('auth/user-disabled')"> The account with that email address has been disabled. </div> <div class="invalid-feedback" [@fadeInOut]="'in'" *ngIf="emailFc.hasError('ngx-firebase-auth/no-password')"> The account with that email address does not have a password. Please sign in using: <span *ngFor="let id of methodsForEmail; let isLast = last"> <a routerLink="." [queryParams]="{action: 'signInOAuth', providerId: id}">{{getOAuthProviderName(id)}}</a> <span *ngIf="!isLast"> | </span> </span> </div> <small class="text-muted form-text" [attr.id]="formId + 'email'" > Not your email address? <a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a> </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')" [@fadeInOut]="'in'"> Required. </div> <div class="invalid-feedback" *ngIf="passwordFc.touched && passwordFc.hasError('auth/wrong-password')" [@fadeInOut]="'in'"> Wrong password. </div> <small [attr.id]="formId + 'password-help'" class="form-text text-muted"> Forgot? <a routerLink="." [queryParams]="{action: 'resetPassword'}">Reset Password</a> </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-lock fa-fw" aria-hidden="true"></i> Sign In </button> </div> </form> `, styles: [``], animations: [fadeInOutAnimation] },] }, ]; /** @nocollapse */ SignInFormComponent.ctorParameters = () => [ { type: AngularFireAuth }, { type: NgxFirebaseAuthService } ]; SignInFormComponent.propDecorators = { passwordInput: [{ type: ViewChild, args: ['passwordInput',] }], email: [{ type: Input }], remember: [{ type: Input }], rememberChange: [{ type: Output }], success: [{ type: Output }], error: [{ type: Output }] }; if (false) { /** @type {?} */ SignInFormComponent.prototype.passwordInput; /** @type {?} */ SignInFormComponent.prototype.email; /** @type {?} */ SignInFormComponent.prototype.remember; /** @type {?} */ SignInFormComponent.prototype.rememberChange; /** @type {?} */ SignInFormComponent.prototype.success; /** @type {?} */ SignInFormComponent.prototype.error; /** @type {?} */ SignInFormComponent.prototype.formId; /** @type {?} */ SignInFormComponent.prototype.submitting; /** @type {?} */ SignInFormComponent.prototype.fg; /** @type {?} */ SignInFormComponent.prototype.emailFc; /** @type {?} */ SignInFormComponent.prototype.passwordFc; /** @type {?} */ SignInFormComponent.prototype.rememberFc; /** @type {?} */ SignInFormComponent.prototype.methodsForEmail; /** @type {?} */ SignInFormComponent.prototype.getOAuthProviderIcon; /** @type {?} */ SignInFormComponent.prototype.getOAuthProviderName; /** @type {?} */ SignInFormComponent.prototype._afAuth; /** @type {?} */ SignInFormComponent.prototype._authService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbi1pbi1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvIiwic291cmNlcyI6WyJsaWIvc2lnbi1pbi9zaWduLWluLWZvcm0vc2lnbi1pbi1mb3JtLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBeUIsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNySCxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFHcEQsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDOUQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDekUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBeUg5RixNQUFNOzs7OztJQWtCSixZQUNVLFNBQ0E7UUFEQSxZQUFPLEdBQVAsT0FBTztRQUNQLGlCQUFZLEdBQVosWUFBWTs4QkFmNEIsSUFBSSxZQUFZLEVBQUU7dUJBQ2IsSUFBSSxZQUFZLEVBQUU7cUJBQzdCLElBQUksWUFBWSxFQUFFO3NCQUVyRCxpQ0FBaUM7MEJBQzdCLEtBQUs7K0JBS1UsRUFBRTtvQ0FDUCxvQkFBb0I7b0NBQ3BCLG9CQUFvQjtLQUl0Qzs7OztJQUVMLElBQUksSUFBSTtRQUNOLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztLQUMxQjs7OztJQUVELElBQUksV0FBVztRQUNiLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO0tBQzFCOzs7O0lBR0QsUUFBUTtRQUNOLElBQUks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QyxhQUFhLEVBQUUsQ0FBQztZQUNoQyxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDbkIsS0FBSyxvQkFBb0IsQ0FBQztnQkFDMUIsS0FBSyxxQkFBcUIsQ0FBQztnQkFDM0IsS0FBSyxvQkFBb0IsQ0FBQztnQkFDMUIsS0FBSywrQkFBK0I7b0JBQ2xDLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUN6RSxLQUFLLENBQUM7Z0JBQ1IsS0FBSyxxQkFBcUI7b0JBQ3hCLHlCQUF5QixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUM1RSxLQUFLLENBQUM7Z0JBQ1I7b0JBQ0UsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3ZCLEtBQUssQ0FBQzthQUNUO1NBQ0YsQ0FBQyxDQUFDO0tBQ047OztZQTFORixTQUFTLFNBQUM7Z0JBQ1QsUUFBUSxFQUFFLGdDQUFnQztnQkFDMUMsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBZ0hYO2dCQUNDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDWixVQUFVLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQzthQUNqQzs7OztZQTdIUSxlQUFlO1lBSWYsc0JBQXNCOzs7NEJBNEg1QixTQUFTLFNBQUMsZUFBZTtvQkFDekIsS0FBSzt1QkFDTCxLQUFLOzZCQUNMLE1BQU07c0JBQ04sTUFBTTtvQkFDTixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIEFmdGVyVmlld0luaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgVmlld0NoaWxkLCBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVBdXRoIH0gZnJvbSAnYW5ndWxhcmZpcmUyL2F1dGgnO1xuaW1wb3J0IHsgYXV0aCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5cbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIgfSBmcm9tICcuLi8uLi9mb3JtLWhlbHBlcic7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbmd4LWZpcmViYXNlLWF1dGguc2VydmljZSc7XG5pbXBvcnQgeyBnZXRPQXV0aFByb3ZpZGVySWNvbiwgZ2V0T0F1dGhQcm92aWRlck5hbWUsIGZhZGVJbk91dEFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1mb3JtJyxcbiAgdGVtcGxhdGU6IGA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCIgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCI+XG5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICdlbWFpbCdcIj5FbWFpbCBBZGRyZXNzPC9sYWJlbD5cblxuICAgIDxpbnB1dFxuICAgICAgcmVhZG9ubHlcbiAgICAgICNlbWFpbElucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICB0eXBlPVwiZW1haWxcIlxuICAgICAgYXV0b2NvbXBsZXRlPVwiZW1haWxcIlxuICAgICAgcGxhY2Vob2xkZXI9XCJFbWFpbCBBZGRyZXNzXCJcbiAgICAgIGZvcm1Db250cm9sTmFtZT1cImVtYWlsXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCI+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdhdXRoL2ludmFsaWQtZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdhdXRoL3VzZXItbm90LWZvdW5kJylcIj5cbiAgICAgIFdlIGNvdWxkIG5vdCBmaW5kIGFuIGFjY291bnQgd2l0aCB0aGF0IGVtYWlsIGFkZHJlc3MuXG4gICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5DcmVhdGUgQWNjb3VudDwvYT5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdhdXRoL3VzZXItZGlzYWJsZWQnKVwiPlxuICAgICAgVGhlIGFjY291bnQgd2l0aCB0aGF0IGVtYWlsIGFkZHJlc3MgaGFzIGJlZW4gZGlzYWJsZWQuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignbmd4LWZpcmViYXNlLWF1dGgvbm8tcGFzc3dvcmQnKVwiPlxuICAgICAgVGhlIGFjY291bnQgd2l0aCB0aGF0IGVtYWlsIGFkZHJlc3MgZG9lcyBub3QgaGF2ZSBhIHBhc3N3b3JkLlxuICAgICAgUGxlYXNlIHNpZ24gaW4gdXNpbmc6XG4gICAgICA8c3BhbiAqbmdGb3I9XCJsZXQgaWQgb2YgbWV0aG9kc0ZvckVtYWlsOyBsZXQgaXNMYXN0ID0gbGFzdFwiPlxuICAgICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluT0F1dGgnLCBwcm92aWRlcklkOiBpZH1cIj57e2dldE9BdXRoUHJvdmlkZXJOYW1lKGlkKX19PC9hPlxuICAgICAgICA8c3BhbiAqbmdJZj1cIiFpc0xhc3RcIj5cbiAgICAgICAgICB8XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvc3Bhbj5cbiAgICA8L2Rpdj5cblxuICAgIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgZm9ybS10ZXh0XCIgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiID5cbiAgICAgIE5vdCB5b3VyIGVtYWlsIGFkZHJlc3M/XG4gICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TdGFydCBPdmVyPC9hPlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuXG5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWVuZFwiPlxuICAgICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncGFzc3dvcmQnXCI+UGFzc3dvcmQ8L2xhYmVsPlxuICAgICAgPHNtYWxsPlxuICAgICAgICA8YSAoY2xpY2spPVwiJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IHBhc3N3b3JkSW5wdXQudHlwZSA9ICdwYXNzd29yZCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZSAgPyAndGV4dCcgOiAncGFzc3dvcmQnXCJcbiAgICAgICAgICBocmVmPVwiI1wiIHRhYmluZGV4PVwiLTFcIiBjbGFzcz1cImQtaW5saW5lLWJsb2NrXCI+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5TaG93PC9zcGFuPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3RleHQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5IaWRlPC9zcGFuPlxuICAgICAgICA8L2E+XG4gICAgICA8L3NtYWxsPlxuICAgIDwvZGl2PlxuICAgIDxpbnB1dFxuICAgICAgI3Bhc3N3b3JkSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdwYXNzd29yZCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAncGFzc3dvcmQtaGVscCdcIlxuICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgIGZvcm1Db250cm9sTmFtZT1cInBhc3N3b3JkXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiUGFzc3dvcmRcIlxuICAgICAgYXV0b2NvbXBsZXRlPVwicGFzc3dvcmRcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCJcbiAgICAgICpuZ0lmPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIlxuICAgICAgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIlxuICAgICAgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcignYXV0aC93cm9uZy1wYXNzd29yZCcpXCJcbiAgICAgIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgIFdyb25nIHBhc3N3b3JkLlxuICAgIDwvZGl2PlxuICAgIDxzbWFsbCBbYXR0ci5pZF09XCJmb3JtSWQgKyAncGFzc3dvcmQtaGVscCdcIiBjbGFzcz1cImZvcm0tdGV4dCB0ZXh0LW11dGVkXCI+XG4gICAgICBGb3Jnb3Q/IDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdyZXNldFBhc3N3b3JkJ31cIj5SZXNldCBQYXNzd29yZDwvYT5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVja1wiPlxuICAgICAgPGlucHV0XG4gICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiXG4gICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVtZW1iZXJcIlxuICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgUmVtZW1iZXIgbWUgb24gdGhpcyBkZXZpY2UuXG4gICAgICA8L2xhYmVsPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIlxuICAgICAgY2xhc3M9XCJidG4gYnRuLXN1Y2Nlc3MgYnRuLWJsb2NrXCJcbiAgICAgIFtkaXNhYmxlZF09XCJmZy5pbnZhbGlkIHx8IHN1Ym1pdHRpbmdcIj5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWxvY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBTaWduIEluXG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuPC9mb3JtPlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbZmFkZUluT3V0QW5pbWF0aW9uXVxufSlcbmV4cG9ydCBjbGFzcyBTaWduSW5Gb3JtQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcblxuICBAVmlld0NoaWxkKCdwYXNzd29yZElucHV0JykgcGFzc3dvcmRJbnB1dDogRWxlbWVudFJlZjtcbiAgQElucHV0KCkgZW1haWw6IHN0cmluZztcbiAgQElucHV0KCkgcmVtZW1iZXI6IGJvb2xlYW47XG4gIEBPdXRwdXQoKSByZW1lbWJlckNoYW5nZTogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPGF1dGguVXNlckNyZWRlbnRpYWw+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZXJyb3I6IEV2ZW50RW1pdHRlcjxhdXRoLkVycm9yPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBmb3JtSWQgPSAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1mb3JtLSc7XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHBhc3N3b3JkRmM6IEZvcm1Db250cm9sO1xuICByZW1lbWJlckZjOiBGb3JtQ29udHJvbDtcbiAgbWV0aG9kc0ZvckVtYWlsOiBzdHJpbmdbXSA9IFtdO1xuICBnZXRPQXV0aFByb3ZpZGVySWNvbiA9IGdldE9BdXRoUHJvdmlkZXJJY29uO1xuICBnZXRPQXV0aFByb3ZpZGVyTmFtZSA9IGdldE9BdXRoUHJvdmlkZXJOYW1lO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZVxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9hdXRoU2VydmljZTtcbiAgfVxuXG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5lbWFpbEZjID0gbmV3IEZvcm1Db250cm9sKFxuICAgICAgdGhpcy5lbWFpbCxcbiAgICAgIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5lbWFpbF19XG4gICAgKTtcbiAgICB0aGlzLnBhc3N3b3JkRmMgPSBuZXcgRm9ybUNvbnRyb2woJycsIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZF19KTtcbiAgICB0aGlzLnJlbWVtYmVyRmMgPSBuZXcgRm9ybUNvbnRyb2wodGhpcy5yZW1lbWJlcik7XG4gICAgdGhpcy5yZW1lbWJlckZjLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUodmFsID0+IHRoaXMucmVtZW1iZXJDaGFuZ2UuZW1pdCh2YWwpKTtcbiAgICB0aGlzLmZnID0gbmV3IEZvcm1Hcm91cCh7XG4gICAgICBlbWFpbDogdGhpcy5lbWFpbEZjLFxuICAgICAgcGFzc3dvcmQ6IHRoaXMucGFzc3dvcmRGYyxcbiAgICAgIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmNcbiAgICB9KTtcbiAgfVxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5wYXNzd29yZElucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgfVxuXG5cblxuICBzdWJtaXQoKSB7XG4gICAgY29uc3QgZW1haWwgPSB0aGlzLmVtYWlsRmMudmFsdWUudHJpbSgpO1xuICAgIHRoaXMuc3VibWl0dGluZyA9IHRydWU7XG4gICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSBbXTtcbiAgICBsZXQgY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbDtcbiAgICB0aGlzLmF1dGguZmV0Y2hTaWduSW5NZXRob2RzRm9yRW1haWwoZW1haWwpXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSByZXN1bHRzO1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3Qoe1xuICAgICAgICAgICAgY29kZTogJ2F1dGgvdXNlci1ub3QtZm91bmQnXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdHMuaW5kZXhPZigncGFzc3dvcmQnKSA9PT0gLTEpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3Qoe1xuICAgICAgICAgICAgY29kZTogJ25neC1maXJlYmFzZS1hdXRoL25vLXBhc3N3b3JkJyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLnNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkKGVtYWlsLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgIGNyZWQgPSByZXN1bHQ7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCBlbWFpbCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdChjcmVkKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLnBhc3N3b3JkRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlICdhdXRoL2ludmFsaWQtZW1haWwnOlxuICAgICAgICAgIGNhc2UgJ2F1dGgvdXNlci1ub3QtZm91bmQnOlxuICAgICAgICAgIGNhc2UgJ2F1dGgvdXNlci1kaXNhYmxlZCc6XG4gICAgICAgICAgY2FzZSAnbmd4LWZpcmViYXNlLWF1dGgvbm8tcGFzc3dvcmQnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLmVtYWlsRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnYXV0aC93cm9uZy1wYXNzd29yZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMucGFzc3dvcmRGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy5lcnJvci5lbWl0KGVycm9yKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG59XG4iXX0=