@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
86 lines • 18.4 kB
JavaScript
import { Component, Output, EventEmitter, ViewChild } from '@angular/core';
import { UserService, FetchClient, Client } from '@c8y/client';
import { AppStateService } from '../common/ui-state.service';
import { AlertService } from '../alert/alert.service';
import { ModalComponent } from '../modal/modal.component';
import { LoginService } from '../login/login.service';
import { clone } from 'lodash-es';
import { gettext } from '../i18n/gettext';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
import * as i2 from "../common/ui-state.service";
import * as i3 from "../alert/alert.service";
import * as i4 from "../login/login.service";
import * as i5 from "@angular/forms";
import * as i6 from "../forms/form-group.component";
import * as i7 from "../forms/message.directive";
import * as i8 from "../forms/messages.component";
import * as i9 from "../forms/required-input-placeholder.directive";
import * as i10 from "../i18n/c8y-translate.directive";
import * as i11 from "../modal/modal.component";
import * as i12 from "../i18n/c8y-translate.pipe";
export class PasswordConfirmModalComponent {
constructor(user, ui, client, alert, loginService) {
this.user = user;
this.ui = ui;
this.client = client;
this.alert = alert;
this.loginService = loginService;
this.passwordConfirmedEmitter = new EventEmitter();
this.loading = false;
}
async passwordConfirm() {
if (this.password) {
const supportUserName = this.ui.currentSupportUserName.value;
const userId = this.ui.currentUser.value.id;
const credentials = {
password: this.password,
user: `${supportUserName ? `${supportUserName}$` : ''}${userId}`,
tenant: this.client.tenant
};
try {
this.loading = true;
const strategy = clone(this.loginService.useBasicAuth({}));
delete credentials.tfa;
strategy.updateCredentials(credentials);
const newClient = this.createNewClient(strategy, this.client.baseUrl);
await newClient.user.current();
this.emitSuccessAndClose();
}
catch (e) {
if (e.res && e.res.status === 401 && e.data && /pin|totp/i.test(e.data.message)) {
this.emitSuccessAndClose();
}
else {
this.alert.danger(gettext("Provided password doesn't match your current one."));
}
}
finally {
this.loading = false;
}
}
}
cancel() {
this.passwordConfirmedEmitter.emit(false);
this.modal._dismiss();
}
createNewClient(strategy, baseUrl) {
return new Client(strategy, baseUrl);
}
emitSuccessAndClose() {
this.passwordConfirmedEmitter.emit(true);
this.modal._dismiss();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PasswordConfirmModalComponent, deps: [{ token: i1.UserService }, { token: i2.AppStateService }, { token: i1.FetchClient }, { token: i3.AlertService }, { token: i4.LoginService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PasswordConfirmModalComponent, selector: "c8y-password-confirm-modal", outputs: { passwordConfirmedEmitter: "passwordConfirmedEmitter" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true }], ngImport: i0, template: "<c8y-modal [customFooter]=\"true\" [title]=\"'Confirm your current password' | translate\" #modal>\r\n <form #confirmForm=\"ngForm\" (ngSubmit)=\"confirmForm.form.valid && passwordConfirm()\">\r\n <div class=\"d-block p-24 p-b-0\">\r\n <c8y-form-group [hasWarning]=\"true\">\r\n <label translate for=\"currentPassword\">Enter your password</label>\r\n <input\r\n id=\"currentPassword\"\r\n [(ngModel)]=\"password\"\r\n type=\"password\"\r\n name=\"password\"\r\n class=\"form-control\"\r\n placeholder=\"{{ 'Enter your password' | translate }}\"\r\n required\r\n />\r\n <c8y-messages>\r\n <c8y-message translate>\r\n Enter the password of the user that you are currently logged in with.\r\n </c8y-message>\r\n </c8y-messages>\r\n </c8y-form-group>\r\n </div>\r\n <div class=\"modal-footer separator-top bg-level-0 sticky-bottom\">\r\n <button\r\n title=\"{{ 'Cancel' | translate }}\"\r\n class=\"btn btn-default\"\r\n type=\"button\"\r\n (click)=\"cancel()\"\r\n >\r\n {{ 'Cancel' | translate }}\r\n </button>\r\n <button\r\n title=\"{{ 'Confirm' | translate }}\"\r\n class=\"btn btn-primary\"\r\n type=\"submit\"\r\n [disabled]=\"!confirmForm.form.valid || loading\"\r\n >\r\n {{ 'Confirm' | translate }}\r\n </button>\r\n </div>\r\n </form>\r\n</c8y-modal>\r\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.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: "component", type: i6.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i7.MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "component", type: i8.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i9.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i10.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: i11.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "pipe", type: i12.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PasswordConfirmModalComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-password-confirm-modal', template: "<c8y-modal [customFooter]=\"true\" [title]=\"'Confirm your current password' | translate\" #modal>\r\n <form #confirmForm=\"ngForm\" (ngSubmit)=\"confirmForm.form.valid && passwordConfirm()\">\r\n <div class=\"d-block p-24 p-b-0\">\r\n <c8y-form-group [hasWarning]=\"true\">\r\n <label translate for=\"currentPassword\">Enter your password</label>\r\n <input\r\n id=\"currentPassword\"\r\n [(ngModel)]=\"password\"\r\n type=\"password\"\r\n name=\"password\"\r\n class=\"form-control\"\r\n placeholder=\"{{ 'Enter your password' | translate }}\"\r\n required\r\n />\r\n <c8y-messages>\r\n <c8y-message translate>\r\n Enter the password of the user that you are currently logged in with.\r\n </c8y-message>\r\n </c8y-messages>\r\n </c8y-form-group>\r\n </div>\r\n <div class=\"modal-footer separator-top bg-level-0 sticky-bottom\">\r\n <button\r\n title=\"{{ 'Cancel' | translate }}\"\r\n class=\"btn btn-default\"\r\n type=\"button\"\r\n (click)=\"cancel()\"\r\n >\r\n {{ 'Cancel' | translate }}\r\n </button>\r\n <button\r\n title=\"{{ 'Confirm' | translate }}\"\r\n class=\"btn btn-primary\"\r\n type=\"submit\"\r\n [disabled]=\"!confirmForm.form.valid || loading\"\r\n >\r\n {{ 'Confirm' | translate }}\r\n </button>\r\n </div>\r\n </form>\r\n</c8y-modal>\r\n" }]
}], ctorParameters: () => [{ type: i1.UserService }, { type: i2.AppStateService }, { type: i1.FetchClient }, { type: i3.AlertService }, { type: i4.LoginService }], propDecorators: { passwordConfirmedEmitter: [{
type: Output
}], modal: [{
type: ViewChild,
args: ['modal', { static: false }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFzc3dvcmQtY29uZmlybS1tb2RhbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL2F1dGhlbnRpY2F0aW9uL3Bhc3N3b3JkLWNvbmZpcm0tbW9kYWwuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vY29yZS9hdXRoZW50aWNhdGlvbi9wYXNzd29yZC1jb25maXJtLW1vZGFsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0UsT0FBTyxFQUFFLFdBQVcsRUFBZ0IsV0FBVyxFQUFFLE1BQU0sRUFBbUIsTUFBTSxhQUFhLENBQUM7QUFDOUYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzdELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7Ozs7Ozs7Ozs7OztBQU0xQyxNQUFNLE9BQU8sNkJBQTZCO0lBT3hDLFlBQ1MsSUFBaUIsRUFDakIsRUFBbUIsRUFDbEIsTUFBbUIsRUFDbkIsS0FBbUIsRUFDbkIsWUFBMEI7UUFKM0IsU0FBSSxHQUFKLElBQUksQ0FBYTtRQUNqQixPQUFFLEdBQUYsRUFBRSxDQUFpQjtRQUNsQixXQUFNLEdBQU4sTUFBTSxDQUFhO1FBQ25CLFVBQUssR0FBTCxLQUFLLENBQWM7UUFDbkIsaUJBQVksR0FBWixZQUFZLENBQWM7UUFYMUIsNkJBQXdCLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUNqRSxZQUFPLEdBQUcsS0FBSyxDQUFDO0lBV2IsQ0FBQztJQUVKLEtBQUssQ0FBQyxlQUFlO1FBQ25CLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2xCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDO1lBQzdELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDNUMsTUFBTSxXQUFXLEdBQWlCO2dCQUNoQyxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7Z0JBQ3ZCLElBQUksRUFBRSxHQUFHLGVBQWUsQ0FBQyxDQUFDLENBQUMsR0FBRyxlQUFlLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLE1BQU0sRUFBRTtnQkFDaEUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTthQUMzQixDQUFDO1lBQ0YsSUFBSSxDQUFDO2dCQUNILElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO2dCQUNwQixNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDM0QsT0FBTyxXQUFXLENBQUMsR0FBRyxDQUFDO2dCQUN2QixRQUFRLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3hDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3RFLE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDL0IsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7WUFDN0IsQ0FBQztZQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ1gsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNoRixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztnQkFDN0IsQ0FBQztxQkFBTSxDQUFDO29CQUNOLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxtREFBbUQsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xGLENBQUM7WUFDSCxDQUFDO29CQUFTLENBQUM7Z0JBQ1QsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDdkIsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTTtRQUNKLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRUQsZUFBZSxDQUFDLFFBQXlCLEVBQUUsT0FBZTtRQUN4RCxPQUFPLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRU8sbUJBQW1CO1FBQ3pCLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN4QixDQUFDOytHQXhEVSw2QkFBNkI7bUdBQTdCLDZCQUE2QixxT0NiMUMsMitDQXlDQTs7NEZENUJhLDZCQUE2QjtrQkFKekMsU0FBUzsrQkFDRSw0QkFBNEI7OExBSTVCLHdCQUF3QjtzQkFBakMsTUFBTTtnQkFJd0MsS0FBSztzQkFBbkQsU0FBUzt1QkFBQyxPQUFPLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBVc2VyU2VydmljZSwgSUNyZWRlbnRpYWxzLCBGZXRjaENsaWVudCwgQ2xpZW50LCBJQXV0aGVudGljYXRpb24gfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBBcHBTdGF0ZVNlcnZpY2UgfSBmcm9tICcuLi9jb21tb24vdWktc3RhdGUuc2VydmljZSc7XG5pbXBvcnQgeyBBbGVydFNlcnZpY2UgfSBmcm9tICcuLi9hbGVydC9hbGVydC5zZXJ2aWNlJztcbmltcG9ydCB7IE1vZGFsQ29tcG9uZW50IH0gZnJvbSAnLi4vbW9kYWwvbW9kYWwuY29tcG9uZW50JztcbmltcG9ydCB7IExvZ2luU2VydmljZSB9IGZyb20gJy4uL2xvZ2luL2xvZ2luLnNlcnZpY2UnO1xuaW1wb3J0IHsgY2xvbmUgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgZ2V0dGV4dCB9IGZyb20gJy4uL2kxOG4vZ2V0dGV4dCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1wYXNzd29yZC1jb25maXJtLW1vZGFsJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3Bhc3N3b3JkLWNvbmZpcm0tbW9kYWwuY29tcG9uZW50Lmh0bWwnXG59KVxuZXhwb3J0IGNsYXNzIFBhc3N3b3JkQ29uZmlybU1vZGFsQ29tcG9uZW50IHtcbiAgQE91dHB1dCgpIHBhc3N3b3JkQ29uZmlybWVkRW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcbiAgbG9hZGluZyA9IGZhbHNlO1xuICBwYXNzd29yZDogc3RyaW5nO1xuXG4gIEBWaWV3Q2hpbGQoJ21vZGFsJywgeyBzdGF0aWM6IGZhbHNlIH0pIHByaXZhdGUgbW9kYWw6IE1vZGFsQ29tcG9uZW50O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyB1c2VyOiBVc2VyU2VydmljZSxcbiAgICBwdWJsaWMgdWk6IEFwcFN0YXRlU2VydmljZSxcbiAgICBwcml2YXRlIGNsaWVudDogRmV0Y2hDbGllbnQsXG4gICAgcHJpdmF0ZSBhbGVydDogQWxlcnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgbG9naW5TZXJ2aWNlOiBMb2dpblNlcnZpY2VcbiAgKSB7fVxuXG4gIGFzeW5jIHBhc3N3b3JkQ29uZmlybSgpIHtcbiAgICBpZiAodGhpcy5wYXNzd29yZCkge1xuICAgICAgY29uc3Qgc3VwcG9ydFVzZXJOYW1lID0gdGhpcy51aS5jdXJyZW50U3VwcG9ydFVzZXJOYW1lLnZhbHVlO1xuICAgICAgY29uc3QgdXNlcklkID0gdGhpcy51aS5jdXJyZW50VXNlci52YWx1ZS5pZDtcbiAgICAgIGNvbnN0IGNyZWRlbnRpYWxzOiBJQ3JlZGVudGlhbHMgPSB7XG4gICAgICAgIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkLFxuICAgICAgICB1c2VyOiBgJHtzdXBwb3J0VXNlck5hbWUgPyBgJHtzdXBwb3J0VXNlck5hbWV9JGAgOiAnJ30ke3VzZXJJZH1gLFxuICAgICAgICB0ZW5hbnQ6IHRoaXMuY2xpZW50LnRlbmFudFxuICAgICAgfTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG4gICAgICAgIGNvbnN0IHN0cmF0ZWd5ID0gY2xvbmUodGhpcy5sb2dpblNlcnZpY2UudXNlQmFzaWNBdXRoKHt9KSk7XG4gICAgICAgIGRlbGV0ZSBjcmVkZW50aWFscy50ZmE7XG4gICAgICAgIHN0cmF0ZWd5LnVwZGF0ZUNyZWRlbnRpYWxzKGNyZWRlbnRpYWxzKTtcbiAgICAgICAgY29uc3QgbmV3Q2xpZW50ID0gdGhpcy5jcmVhdGVOZXdDbGllbnQoc3RyYXRlZ3ksIHRoaXMuY2xpZW50LmJhc2VVcmwpO1xuICAgICAgICBhd2FpdCBuZXdDbGllbnQudXNlci5jdXJyZW50KCk7XG4gICAgICAgIHRoaXMuZW1pdFN1Y2Nlc3NBbmRDbG9zZSgpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZS5yZXMgJiYgZS5yZXMuc3RhdHVzID09PSA0MDEgJiYgZS5kYXRhICYmIC9waW58dG90cC9pLnRlc3QoZS5kYXRhLm1lc3NhZ2UpKSB7XG4gICAgICAgICAgdGhpcy5lbWl0U3VjY2Vzc0FuZENsb3NlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5hbGVydC5kYW5nZXIoZ2V0dGV4dChcIlByb3ZpZGVkIHBhc3N3b3JkIGRvZXNuJ3QgbWF0Y2ggeW91ciBjdXJyZW50IG9uZS5cIikpO1xuICAgICAgICB9XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjYW5jZWwoKSB7XG4gICAgdGhpcy5wYXNzd29yZENvbmZpcm1lZEVtaXR0ZXIuZW1pdChmYWxzZSk7XG4gICAgdGhpcy5tb2RhbC5fZGlzbWlzcygpO1xuICB9XG5cbiAgY3JlYXRlTmV3Q2xpZW50KHN0cmF0ZWd5OiBJQXV0aGVudGljYXRpb24sIGJhc2VVcmw6IHN0cmluZykge1xuICAgIHJldHVybiBuZXcgQ2xpZW50KHN0cmF0ZWd5LCBiYXNlVXJsKTtcbiAgfVxuXG4gIHByaXZhdGUgZW1pdFN1Y2Nlc3NBbmRDbG9zZSgpIHtcbiAgICB0aGlzLnBhc3N3b3JkQ29uZmlybWVkRW1pdHRlci5lbWl0KHRydWUpO1xuICAgIHRoaXMubW9kYWwuX2Rpc21pc3MoKTtcbiAgfVxufVxuIiwiPGM4eS1tb2RhbCBbY3VzdG9tRm9vdGVyXT1cInRydWVcIiBbdGl0bGVdPVwiJ0NvbmZpcm0geW91ciBjdXJyZW50IHBhc3N3b3JkJyB8IHRyYW5zbGF0ZVwiICNtb2RhbD5cclxuICA8Zm9ybSAjY29uZmlybUZvcm09XCJuZ0Zvcm1cIiAobmdTdWJtaXQpPVwiY29uZmlybUZvcm0uZm9ybS52YWxpZCAmJiBwYXNzd29yZENvbmZpcm0oKVwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImQtYmxvY2sgcC0yNCBwLWItMFwiPlxyXG4gICAgICA8Yzh5LWZvcm0tZ3JvdXAgW2hhc1dhcm5pbmddPVwidHJ1ZVwiPlxyXG4gICAgICAgIDxsYWJlbCB0cmFuc2xhdGUgZm9yPVwiY3VycmVudFBhc3N3b3JkXCI+RW50ZXIgeW91ciBwYXNzd29yZDwvbGFiZWw+XHJcbiAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICBpZD1cImN1cnJlbnRQYXNzd29yZFwiXHJcbiAgICAgICAgICBbKG5nTW9kZWwpXT1cInBhc3N3b3JkXCJcclxuICAgICAgICAgIHR5cGU9XCJwYXNzd29yZFwiXHJcbiAgICAgICAgICBuYW1lPVwicGFzc3dvcmRcIlxyXG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxyXG4gICAgICAgICAgcGxhY2Vob2xkZXI9XCJ7eyAnRW50ZXIgeW91ciBwYXNzd29yZCcgfCB0cmFuc2xhdGUgfX1cIlxyXG4gICAgICAgICAgcmVxdWlyZWRcclxuICAgICAgICAvPlxyXG4gICAgICAgIDxjOHktbWVzc2FnZXM+XHJcbiAgICAgICAgICA8Yzh5LW1lc3NhZ2UgdHJhbnNsYXRlPlxyXG4gICAgICAgICAgICBFbnRlciB0aGUgcGFzc3dvcmQgb2YgdGhlIHVzZXIgdGhhdCB5b3UgYXJlIGN1cnJlbnRseSBsb2dnZWQgaW4gd2l0aC5cclxuICAgICAgICAgIDwvYzh5LW1lc3NhZ2U+XHJcbiAgICAgICAgPC9jOHktbWVzc2FnZXM+XHJcbiAgICAgIDwvYzh5LWZvcm0tZ3JvdXA+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJtb2RhbC1mb290ZXIgc2VwYXJhdG9yLXRvcCBiZy1sZXZlbC0wIHN0aWNreS1ib3R0b21cIj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIHRpdGxlPVwie3sgJ0NhbmNlbCcgfCB0cmFuc2xhdGUgfX1cIlxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0XCJcclxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAoY2xpY2spPVwiY2FuY2VsKClcIlxyXG4gICAgICA+XHJcbiAgICAgICAge3sgJ0NhbmNlbCcgfCB0cmFuc2xhdGUgfX1cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICB0aXRsZT1cInt7ICdDb25maXJtJyB8IHRyYW5zbGF0ZSB9fVwiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxyXG4gICAgICAgIHR5cGU9XCJzdWJtaXRcIlxyXG4gICAgICAgIFtkaXNhYmxlZF09XCIhY29uZmlybUZvcm0uZm9ybS52YWxpZCB8fCBsb2FkaW5nXCJcclxuICAgICAgPlxyXG4gICAgICAgIHt7ICdDb25maXJtJyB8IHRyYW5zbGF0ZSB9fVxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZm9ybT5cclxuPC9jOHktbW9kYWw+XHJcbiJdfQ==