UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

90 lines 24.2 kB
import { Component, Output, Input, EventEmitter } from '@angular/core'; import { LoginService } from './login.service'; import { UserService, PasswordStrength } from '@c8y/client'; import { OptionsService } from '../common/options.service'; import { AlertService } from '../alert/alert.service'; import { LoginViews } from './login.model'; import * as i0 from "@angular/core"; import * as i1 from "./login.service"; import * as i2 from "@c8y/client"; import * as i3 from "../common/options.service"; import * as i4 from "../alert/alert.service"; import * as i5 from "@angular/forms"; import * as i6 from "../i18n/c8y-translate.directive"; import * as i7 from "@angular/common"; import * as i8 from "../authentication/password-check-list.component"; import * as i9 from "../authentication/password-confirm.directive"; import * as i10 from "../forms/form-group.component"; import * as i11 from "../forms/message.directive"; import * as i12 from "../forms/messages.component"; import * as i13 from "../forms/required-input-placeholder.directive"; import * as i14 from "./password-strength-validator.directive"; import * as i15 from "../i18n/c8y-translate.pipe"; export class ChangePasswordComponent { constructor(loginService, users, options, alert) { this.loginService = loginService; this.users = users; this.options = options; this.alert = alert; this.onChangeView = new EventEmitter(); this.passwordPattern = /^[a-zA-Z0-9`~!@#$%^&*()_|+\-=?;:'",.<>{}[\]\\/]{8,32}$/; this.isLoading = false; this.model = { tenantId: '', email: '', newPassword: '', newPasswordConfirm: '' }; this.emailReadOnly = false; this.passwordStrengthEnforced = false; this.TOKEN_PARAM = 'token'; this.EMAIL_PARAM = 'email'; } async ngOnInit() { this.model.tenantId = this.loginService.getTenant(); this.model.email = this.options.get(this.EMAIL_PARAM, ''); this.emailReadOnly = !!this.model.email; this.passwordStrengthEnforced = await this.loginService.getPasswordStrengthEnforced(); } async changePassword() { const resetPassword = { token: this.credentials.token, email: this.model.email, newPassword: this.model.newPassword, passwordStrength: PasswordStrength.GREEN // @TODO: MTM-58234 - Deprecated - currently Backend requires this parameter. }; try { this.isLoading = true; const { res } = await this.users.resetPassword(resetPassword, this.model.tenantId); if (res.status === 200) { this.loginService.addSuccessMessage('password_changed'); this.credentials.token = undefined; this.options.set(this.TOKEN_PARAM, undefined); if (this.loginService.showTenantSetup()) { this.onChangeView.emit({ view: LoginViews.TenantIdSetup }); } else { this.onChangeView.emit({ view: LoginViews.Credentials }); } } } catch (e) { this.alert.addServerFailure(e); } finally { this.loginService.reset(); this.isLoading = false; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChangePasswordComponent, deps: [{ token: i1.LoginService }, { token: i2.UserService }, { token: i3.OptionsService }, { token: i4.AlertService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ChangePasswordComponent, selector: "c8y-change-password", inputs: { credentials: "credentials" }, outputs: { onChangeView: "onChangeView" }, ngImport: i0, template: "<form class=\"loginForm\" (ngSubmit)=\"changePassword()\" #changePasswordForm=\"ngForm\" novalidate>\n <div class=\"legend form-block center\" translate>Change password</div>\n\n <c8y-form-group class=\"tenantField\" id=\"tenantField\" *ngIf=\"loginService.showTenant()\">\n <label translate>Tenant ID</label>\n <input\n [(ngModel)]=\"model.tenantId\"\n #tenantId=\"ngModel\"\n type=\"text\"\n name=\"tenantId\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n class=\"form-control\"\n placeholder=\"{{ 'Tenant ID' | translate }}\"\n required\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Email address</label>\n <input\n [(ngModel)]=\"model.email\"\n #email=\"ngModel\"\n type=\"text\"\n name=\"email\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n class=\"form-control\"\n placeholder=\"{{ 'Email address' | translate }}\"\n email\n required\n [readonly]=\"emailReadOnly\"\n />\n </c8y-form-group>\n\n <div class=\"row content-flex-50\">\n <div class=\"col-6\">\n <c8y-form-group>\n <label translate>New password</label>\n <input\n [(ngModel)]=\"model.newPassword\"\n #newPassword=\"ngModel\"\n type=\"password\"\n name=\"newPassword\"\n class=\"form-control\"\n placeholder=\"{{ 'New password' | translate }}\"\n [pattern]=\"passwordPattern\"\n autocomplete=\"new-password\"\n [passwordStrengthEnforced]=\"passwordStrengthEnforced\"\n required\n />\n <c8y-messages>\n <c8y-message\n name=\"pattern\"\n [text]=\"loginService.ERROR_MESSAGES.pattern_newPassword\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Confirm password</label>\n <input\n [(ngModel)]=\"model.newPasswordConfirm\"\n #newPasswordConfirm=\"ngModel\"\n type=\"password\"\n name=\"newPasswordConfirm\"\n class=\"form-control\"\n placeholder=\"{{ 'Confirm password' | translate }}\"\n passwordConfirm=\"newPassword\"\n autocomplete=\"new-password\"\n required\n />\n <c8y-messages>\n <c8y-message\n name=\"passwordConfirm\"\n [text]=\"loginService.ERROR_MESSAGES.passwordConfirm\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n <div class=\"col-6\">\n <c8y-password-check-list\n [password]=\"model.newPassword\"\n [strengthEnforced]=\"passwordStrengthEnforced\"\n ></c8y-password-check-list>\n </div>\n </div>\n\n <button\n title=\"{{ 'Set password' | translate }}\"\n [disabled]=\"!changePasswordForm.form.valid || isLoading\"\n type=\"submit\"\n class=\"btn btn-primary btn-lg btn-block form-group\"\n >\n {{ 'Set password' | translate }}\n </button>\n</form>\n", dependencies: [{ kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i5.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i8.PasswordCheckListComponent, selector: "c8y-password-check-list", inputs: ["strengthEnforced", "password"], outputs: ["onRequirementsFulfilled"] }, { kind: "directive", type: i9.PasswordConfirm, selector: "[passwordConfirm]" }, { kind: "component", type: i10.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i11.MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "component", type: i12.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i13.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i14.PasswordStrengthValidatorDirective, selector: "[passwordStrengthEnforced]", inputs: ["passwordStrengthEnforced"] }, { kind: "pipe", type: i15.C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChangePasswordComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-change-password', template: "<form class=\"loginForm\" (ngSubmit)=\"changePassword()\" #changePasswordForm=\"ngForm\" novalidate>\n <div class=\"legend form-block center\" translate>Change password</div>\n\n <c8y-form-group class=\"tenantField\" id=\"tenantField\" *ngIf=\"loginService.showTenant()\">\n <label translate>Tenant ID</label>\n <input\n [(ngModel)]=\"model.tenantId\"\n #tenantId=\"ngModel\"\n type=\"text\"\n name=\"tenantId\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n class=\"form-control\"\n placeholder=\"{{ 'Tenant ID' | translate }}\"\n required\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Email address</label>\n <input\n [(ngModel)]=\"model.email\"\n #email=\"ngModel\"\n type=\"text\"\n name=\"email\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n class=\"form-control\"\n placeholder=\"{{ 'Email address' | translate }}\"\n email\n required\n [readonly]=\"emailReadOnly\"\n />\n </c8y-form-group>\n\n <div class=\"row content-flex-50\">\n <div class=\"col-6\">\n <c8y-form-group>\n <label translate>New password</label>\n <input\n [(ngModel)]=\"model.newPassword\"\n #newPassword=\"ngModel\"\n type=\"password\"\n name=\"newPassword\"\n class=\"form-control\"\n placeholder=\"{{ 'New password' | translate }}\"\n [pattern]=\"passwordPattern\"\n autocomplete=\"new-password\"\n [passwordStrengthEnforced]=\"passwordStrengthEnforced\"\n required\n />\n <c8y-messages>\n <c8y-message\n name=\"pattern\"\n [text]=\"loginService.ERROR_MESSAGES.pattern_newPassword\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Confirm password</label>\n <input\n [(ngModel)]=\"model.newPasswordConfirm\"\n #newPasswordConfirm=\"ngModel\"\n type=\"password\"\n name=\"newPasswordConfirm\"\n class=\"form-control\"\n placeholder=\"{{ 'Confirm password' | translate }}\"\n passwordConfirm=\"newPassword\"\n autocomplete=\"new-password\"\n required\n />\n <c8y-messages>\n <c8y-message\n name=\"passwordConfirm\"\n [text]=\"loginService.ERROR_MESSAGES.passwordConfirm\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n <div class=\"col-6\">\n <c8y-password-check-list\n [password]=\"model.newPassword\"\n [strengthEnforced]=\"passwordStrengthEnforced\"\n ></c8y-password-check-list>\n </div>\n </div>\n\n <button\n title=\"{{ 'Set password' | translate }}\"\n [disabled]=\"!changePasswordForm.form.valid || isLoading\"\n type=\"submit\"\n class=\"btn btn-primary btn-lg btn-block form-group\"\n >\n {{ 'Set password' | translate }}\n </button>\n</form>\n" }] }], ctorParameters: () => [{ type: i1.LoginService }, { type: i2.UserService }, { type: i3.OptionsService }, { type: i4.AlertService }], propDecorators: { credentials: [{ type: Input }], onChangeView: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhbmdlLXBhc3N3b3JkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2NvcmUvbG9naW4vY2hhbmdlLXBhc3N3b3JkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL2NvcmUvbG9naW4vY2hhbmdlLXBhc3N3b3JkLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsTUFBTSxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0UsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBZ0MsV0FBVyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFPM0MsTUFBTSxPQUFPLHVCQUF1QjtJQWtCbEMsWUFDUyxZQUEwQixFQUN6QixLQUFrQixFQUNsQixPQUF1QixFQUN2QixLQUFtQjtRQUhwQixpQkFBWSxHQUFaLFlBQVksQ0FBYztRQUN6QixVQUFLLEdBQUwsS0FBSyxDQUFhO1FBQ2xCLFlBQU8sR0FBUCxPQUFPLENBQWdCO1FBQ3ZCLFVBQUssR0FBTCxLQUFLLENBQWM7UUFwQm5CLGlCQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUU1QyxvQkFBZSxHQUFHLHdEQUF3RCxDQUFDO1FBQzNFLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDbEIsVUFBSyxHQUFHO1lBQ04sUUFBUSxFQUFFLEVBQUU7WUFDWixLQUFLLEVBQUUsRUFBRTtZQUNULFdBQVcsRUFBRSxFQUFFO1lBQ2Ysa0JBQWtCLEVBQUUsRUFBRTtTQUN2QixDQUFDO1FBQ0Ysa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFDdEIsNkJBQXdCLEdBQUcsS0FBSyxDQUFDO1FBRXpCLGdCQUFXLEdBQUcsT0FBTyxDQUFDO1FBQ3RCLGdCQUFXLEdBQUcsT0FBTyxDQUFDO0lBTzNCLENBQUM7SUFFSixLQUFLLENBQUMsUUFBUTtRQUNaLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDcEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztRQUN4QyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLDJCQUEyQixFQUFFLENBQUM7SUFDeEYsQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjO1FBQ2xCLE1BQU0sYUFBYSxHQUFtQjtZQUNwQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLO1lBQzdCLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUs7WUFDdkIsV0FBVyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVztZQUNuQyxnQkFBZ0IsRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsNkVBQTZFO1NBQ3ZILENBQUM7UUFDRixJQUFJLENBQUM7WUFDSCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztZQUN0QixNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNuRixJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7Z0JBQ3ZCLElBQUksQ0FBQyxZQUFZLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCLENBQUMsQ0FBQztnQkFDeEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEdBQUcsU0FBUyxDQUFDO2dCQUNuQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUM5QyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQztvQkFDeEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUM7Z0JBQzdELENBQUM7cUJBQU0sQ0FBQztvQkFDTixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztnQkFDM0QsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakMsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN6QixDQUFDO0lBQ0gsQ0FBQzsrR0ExRFUsdUJBQXVCO21HQUF2Qix1QkFBdUIsOElDWnBDLHErRkFpR0E7OzRGRHJGYSx1QkFBdUI7a0JBTG5DLFNBQVM7K0JBQ0UscUJBQXFCO21LQUt0QixXQUFXO3NCQUFuQixLQUFLO2dCQUNJLFlBQVk7c0JBQXJCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgT3V0cHV0LCBJbnB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMb2dpblNlcnZpY2UgfSBmcm9tICcuL2xvZ2luLnNlcnZpY2UnO1xuaW1wb3J0IHsgSVJlc2V0UGFzc3dvcmQsIElDcmVkZW50aWFscywgVXNlclNlcnZpY2UsIFBhc3N3b3JkU3RyZW5ndGggfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBPcHRpb25zU2VydmljZSB9IGZyb20gJy4uL2NvbW1vbi9vcHRpb25zLnNlcnZpY2UnO1xuaW1wb3J0IHsgQWxlcnRTZXJ2aWNlIH0gZnJvbSAnLi4vYWxlcnQvYWxlcnQuc2VydmljZSc7XG5pbXBvcnQgeyBMb2dpblZpZXdzIH0gZnJvbSAnLi9sb2dpbi5tb2RlbCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1jaGFuZ2UtcGFzc3dvcmQnLFxuICB0ZW1wbGF0ZVVybDogJy4vY2hhbmdlLXBhc3N3b3JkLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVzOiBbXVxufSlcbmV4cG9ydCBjbGFzcyBDaGFuZ2VQYXNzd29yZENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIEBJbnB1dCgpIGNyZWRlbnRpYWxzOiBJQ3JlZGVudGlhbHM7XG4gIEBPdXRwdXQoKSBvbkNoYW5nZVZpZXcgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcGFzc3dvcmRQYXR0ZXJuID0gL15bYS16QS1aMC05YH4hQCMkJV4mKigpX3wrXFwtPT87OidcIiwuPD57fVtcXF1cXFxcL117OCwzMn0kLztcbiAgaXNMb2FkaW5nID0gZmFsc2U7XG4gIG1vZGVsID0ge1xuICAgIHRlbmFudElkOiAnJyxcbiAgICBlbWFpbDogJycsXG4gICAgbmV3UGFzc3dvcmQ6ICcnLFxuICAgIG5ld1Bhc3N3b3JkQ29uZmlybTogJydcbiAgfTtcbiAgZW1haWxSZWFkT25seSA9IGZhbHNlO1xuICBwYXNzd29yZFN0cmVuZ3RoRW5mb3JjZWQgPSBmYWxzZTtcblxuICBwcml2YXRlIFRPS0VOX1BBUkFNID0gJ3Rva2VuJztcbiAgcHJpdmF0ZSBFTUFJTF9QQVJBTSA9ICdlbWFpbCc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIGxvZ2luU2VydmljZTogTG9naW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgdXNlcnM6IFVzZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgb3B0aW9uczogT3B0aW9uc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBhbGVydDogQWxlcnRTZXJ2aWNlXG4gICkge31cblxuICBhc3luYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLm1vZGVsLnRlbmFudElkID0gdGhpcy5sb2dpblNlcnZpY2UuZ2V0VGVuYW50KCk7XG4gICAgdGhpcy5tb2RlbC5lbWFpbCA9IHRoaXMub3B0aW9ucy5nZXQodGhpcy5FTUFJTF9QQVJBTSwgJycpO1xuICAgIHRoaXMuZW1haWxSZWFkT25seSA9ICEhdGhpcy5tb2RlbC5lbWFpbDtcbiAgICB0aGlzLnBhc3N3b3JkU3RyZW5ndGhFbmZvcmNlZCA9IGF3YWl0IHRoaXMubG9naW5TZXJ2aWNlLmdldFBhc3N3b3JkU3RyZW5ndGhFbmZvcmNlZCgpO1xuICB9XG5cbiAgYXN5bmMgY2hhbmdlUGFzc3dvcmQoKSB7XG4gICAgY29uc3QgcmVzZXRQYXNzd29yZDogSVJlc2V0UGFzc3dvcmQgPSB7XG4gICAgICB0b2tlbjogdGhpcy5jcmVkZW50aWFscy50b2tlbixcbiAgICAgIGVtYWlsOiB0aGlzLm1vZGVsLmVtYWlsLFxuICAgICAgbmV3UGFzc3dvcmQ6IHRoaXMubW9kZWwubmV3UGFzc3dvcmQsXG4gICAgICBwYXNzd29yZFN0cmVuZ3RoOiBQYXNzd29yZFN0cmVuZ3RoLkdSRUVOIC8vIEBUT0RPOiBNVE0tNTgyMzQgLSBEZXByZWNhdGVkIC0gY3VycmVudGx5IEJhY2tlbmQgcmVxdWlyZXMgdGhpcyBwYXJhbWV0ZXIuXG4gICAgfTtcbiAgICB0cnkge1xuICAgICAgdGhpcy5pc0xvYWRpbmcgPSB0cnVlO1xuICAgICAgY29uc3QgeyByZXMgfSA9IGF3YWl0IHRoaXMudXNlcnMucmVzZXRQYXNzd29yZChyZXNldFBhc3N3b3JkLCB0aGlzLm1vZGVsLnRlbmFudElkKTtcbiAgICAgIGlmIChyZXMuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgdGhpcy5sb2dpblNlcnZpY2UuYWRkU3VjY2Vzc01lc3NhZ2UoJ3Bhc3N3b3JkX2NoYW5nZWQnKTtcbiAgICAgICAgdGhpcy5jcmVkZW50aWFscy50b2tlbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5vcHRpb25zLnNldCh0aGlzLlRPS0VOX1BBUkFNLCB1bmRlZmluZWQpO1xuICAgICAgICBpZiAodGhpcy5sb2dpblNlcnZpY2Uuc2hvd1RlbmFudFNldHVwKCkpIHtcbiAgICAgICAgICB0aGlzLm9uQ2hhbmdlVmlldy5lbWl0KHsgdmlldzogTG9naW5WaWV3cy5UZW5hbnRJZFNldHVwIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMub25DaGFuZ2VWaWV3LmVtaXQoeyB2aWV3OiBMb2dpblZpZXdzLkNyZWRlbnRpYWxzIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5hbGVydC5hZGRTZXJ2ZXJGYWlsdXJlKGUpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmxvZ2luU2VydmljZS5yZXNldCgpO1xuICAgICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZTtcbiAgICB9XG4gIH1cbn1cbiIsIjxmb3JtIGNsYXNzPVwibG9naW5Gb3JtXCIgKG5nU3VibWl0KT1cImNoYW5nZVBhc3N3b3JkKClcIiAjY2hhbmdlUGFzc3dvcmRGb3JtPVwibmdGb3JtXCIgbm92YWxpZGF0ZT5cbiAgPGRpdiBjbGFzcz1cImxlZ2VuZCBmb3JtLWJsb2NrIGNlbnRlclwiIHRyYW5zbGF0ZT5DaGFuZ2UgcGFzc3dvcmQ8L2Rpdj5cblxuICA8Yzh5LWZvcm0tZ3JvdXAgY2xhc3M9XCJ0ZW5hbnRGaWVsZFwiIGlkPVwidGVuYW50RmllbGRcIiAqbmdJZj1cImxvZ2luU2VydmljZS5zaG93VGVuYW50KClcIj5cbiAgICA8bGFiZWwgdHJhbnNsYXRlPlRlbmFudCBJRDwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICBbKG5nTW9kZWwpXT1cIm1vZGVsLnRlbmFudElkXCJcbiAgICAgICN0ZW5hbnRJZD1cIm5nTW9kZWxcIlxuICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgbmFtZT1cInRlbmFudElkXCJcbiAgICAgIGF1dG9jYXBpdGFsaXplPVwib2ZmXCJcbiAgICAgIGF1dG9jb3JyZWN0PVwib2ZmXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ1RlbmFudCBJRCcgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgcmVxdWlyZWRcbiAgICAvPlxuICA8L2M4eS1mb3JtLWdyb3VwPlxuXG4gIDxjOHktZm9ybS1ncm91cD5cbiAgICA8bGFiZWwgdHJhbnNsYXRlPkVtYWlsIGFkZHJlc3M8L2xhYmVsPlxuICAgIDxpbnB1dFxuICAgICAgWyhuZ01vZGVsKV09XCJtb2RlbC5lbWFpbFwiXG4gICAgICAjZW1haWw9XCJuZ01vZGVsXCJcbiAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgIG5hbWU9XCJlbWFpbFwiXG4gICAgICBhdXRvY2FwaXRhbGl6ZT1cIm9mZlwiXG4gICAgICBhdXRvY29ycmVjdD1cIm9mZlwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICBwbGFjZWhvbGRlcj1cInt7ICdFbWFpbCBhZGRyZXNzJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICBlbWFpbFxuICAgICAgcmVxdWlyZWRcbiAgICAgIFtyZWFkb25seV09XCJlbWFpbFJlYWRPbmx5XCJcbiAgICAvPlxuICA8L2M4eS1mb3JtLWdyb3VwPlxuXG4gIDxkaXYgY2xhc3M9XCJyb3cgY29udGVudC1mbGV4LTUwXCI+XG4gICAgPGRpdiBjbGFzcz1cImNvbC02XCI+XG4gICAgICA8Yzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgIDxsYWJlbCB0cmFuc2xhdGU+TmV3IHBhc3N3b3JkPC9sYWJlbD5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJtb2RlbC5uZXdQYXNzd29yZFwiXG4gICAgICAgICAgI25ld1Bhc3N3b3JkPVwibmdNb2RlbFwiXG4gICAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICBuYW1lPVwibmV3UGFzc3dvcmRcIlxuICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7ICdOZXcgcGFzc3dvcmQnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICBbcGF0dGVybl09XCJwYXNzd29yZFBhdHRlcm5cIlxuICAgICAgICAgIGF1dG9jb21wbGV0ZT1cIm5ldy1wYXNzd29yZFwiXG4gICAgICAgICAgW3Bhc3N3b3JkU3RyZW5ndGhFbmZvcmNlZF09XCJwYXNzd29yZFN0cmVuZ3RoRW5mb3JjZWRcIlxuICAgICAgICAgIHJlcXVpcmVkXG4gICAgICAgIC8+XG4gICAgICAgIDxjOHktbWVzc2FnZXM+XG4gICAgICAgICAgPGM4eS1tZXNzYWdlXG4gICAgICAgICAgICBuYW1lPVwicGF0dGVyblwiXG4gICAgICAgICAgICBbdGV4dF09XCJsb2dpblNlcnZpY2UuRVJST1JfTUVTU0FHRVMucGF0dGVybl9uZXdQYXNzd29yZFwiXG4gICAgICAgICAgPjwvYzh5LW1lc3NhZ2U+XG4gICAgICAgIDwvYzh5LW1lc3NhZ2VzPlxuICAgICAgPC9jOHktZm9ybS1ncm91cD5cblxuICAgICAgPGM4eS1mb3JtLWdyb3VwPlxuICAgICAgICA8bGFiZWwgdHJhbnNsYXRlPkNvbmZpcm0gcGFzc3dvcmQ8L2xhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBbKG5nTW9kZWwpXT1cIm1vZGVsLm5ld1Bhc3N3b3JkQ29uZmlybVwiXG4gICAgICAgICAgI25ld1Bhc3N3b3JkQ29uZmlybT1cIm5nTW9kZWxcIlxuICAgICAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICAgICAgbmFtZT1cIm5ld1Bhc3N3b3JkQ29uZmlybVwiXG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ0NvbmZpcm0gcGFzc3dvcmQnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICBwYXNzd29yZENvbmZpcm09XCJuZXdQYXNzd29yZFwiXG4gICAgICAgICAgYXV0b2NvbXBsZXRlPVwibmV3LXBhc3N3b3JkXCJcbiAgICAgICAgICByZXF1aXJlZFxuICAgICAgICAvPlxuICAgICAgICA8Yzh5LW1lc3NhZ2VzPlxuICAgICAgICAgIDxjOHktbWVzc2FnZVxuICAgICAgICAgICAgbmFtZT1cInBhc3N3b3JkQ29uZmlybVwiXG4gICAgICAgICAgICBbdGV4dF09XCJsb2dpblNlcnZpY2UuRVJST1JfTUVTU0FHRVMucGFzc3dvcmRDb25maXJtXCJcbiAgICAgICAgICA+PC9jOHktbWVzc2FnZT5cbiAgICAgICAgPC9jOHktbWVzc2FnZXM+XG4gICAgICA8L2M4eS1mb3JtLWdyb3VwPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtNlwiPlxuICAgICAgPGM4eS1wYXNzd29yZC1jaGVjay1saXN0XG4gICAgICAgIFtwYXNzd29yZF09XCJtb2RlbC5uZXdQYXNzd29yZFwiXG4gICAgICAgIFtzdHJlbmd0aEVuZm9yY2VkXT1cInBhc3N3b3JkU3RyZW5ndGhFbmZvcmNlZFwiXG4gICAgICA+PC9jOHktcGFzc3dvcmQtY2hlY2stbGlzdD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPGJ1dHRvblxuICAgIHRpdGxlPVwie3sgJ1NldCBwYXNzd29yZCcgfCB0cmFuc2xhdGUgfX1cIlxuICAgIFtkaXNhYmxlZF09XCIhY2hhbmdlUGFzc3dvcmRGb3JtLmZvcm0udmFsaWQgfHwgaXNMb2FkaW5nXCJcbiAgICB0eXBlPVwic3VibWl0XCJcbiAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSBidG4tbGcgYnRuLWJsb2NrIGZvcm0tZ3JvdXBcIlxuICA+XG4gICAge3sgJ1NldCBwYXNzd29yZCcgfCB0cmFuc2xhdGUgfX1cbiAgPC9idXR0b24+XG48L2Zvcm0+XG4iXX0=