UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

61 lines 17.4 kB
import { Component, EventEmitter } from '@angular/core'; import { AuthConfigurationService } from './auth-configuration.service'; import { AlertService, LoginService, ModalService } from '@c8y/ngx-components'; import { TenantLoginOptionsService } from '@c8y/client'; import { cloneDeep } from 'lodash-es'; import { BehaviorSubject } from 'rxjs'; import { tap, switchMap, shareReplay } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "./auth-configuration.service"; import * as i2 from "@c8y/client"; import * as i3 from "@c8y/ngx-components"; import * as i4 from "@angular/common"; import * as i5 from "@angular/forms"; import * as i6 from "./session-configuration.component"; import * as i7 from "./login-settings.component"; import * as i8 from "./basic-auth-settings.component"; import * as i9 from "./tfa-settings.component"; export class AuthConfigurationComponent { constructor(authConfigurationService, tenantLoginOptionsService, modalService, loginService, alertService) { this.authConfigurationService = authConfigurationService; this.tenantLoginOptionsService = tenantLoginOptionsService; this.modalService = modalService; this.loginService = loginService; this.alertService = alertService; this.reloading$ = new BehaviorSubject(false); this.reload = new EventEmitter(); this.authConfiguration$ = this.reload.pipe(tap(() => this.reloading$.next(true)), switchMap(() => this.authConfigurationService.getAuthConfiguration$()), tap(() => this.reloading$.next(false)), shareReplay(1)); } ngOnInit() { this.authConfigurationSubscription = this.authConfiguration$.subscribe((authConfiguration) => { this.authConfiguration = authConfiguration; this.previousAuthConfiguration = cloneDeep(this.authConfiguration); }); this.loadAuthConfig(); } loadAuthConfig() { this.reload.next(); } ngOnDestroy() { this.authConfigurationSubscription.unsubscribe(); } async save() { try { await this.modalService.confirmLogout(); await this.authConfigurationService.save(this.authConfiguration, this.previousAuthConfiguration); await this.loginService.logout(true); } catch (ex) { if (ex) { this.alertService.addServerFailure(ex); } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AuthConfigurationComponent, deps: [{ token: i1.AuthConfigurationService }, { token: i2.TenantLoginOptionsService }, { token: i3.ModalService }, { token: i3.LoginService }, { token: i3.AlertService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AuthConfigurationComponent, selector: "c8y-auth-configuration", ngImport: i0, template: "<c8y-title>{{ 'Authentication' | translate }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'cog'\"\n [label]=\"'Settings' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'cog'\"\n [label]=\"'Authentication' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n (click)=\"loadAuthConfig()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading$ | async }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/authentication/basic-settings/#basic-settings\"></c8y-help>\n\n<form\n class=\"card card--fullpage\"\n #authConfigurationForm=\"ngForm\"\n novalidate\n>\n <div class=\"card-header separator\">\n <div class=\"card-title\">\n {{ 'Authentication' | translate }}\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n *ngIf=\"authConfiguration\"\n >\n <c8y-login-settings [authConfiguration]=\"authConfiguration\"></c8y-login-settings>\n <c8y-basic-auth-settings [authConfiguration]=\"authConfiguration\"></c8y-basic-auth-settings>\n <c8y-session-configuration [authConfiguration]=\"authConfiguration\"></c8y-session-configuration>\n <c8y-auth-tfa [authConfiguration]=\"authConfiguration\"></c8y-auth-tfa>\n </div>\n <div class=\"card-footer separator\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n (click)=\"save()\"\n [disabled]=\"!authConfigurationForm.form.valid || authConfigurationForm.form.pristine\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</form>\n", dependencies: [{ kind: "component", type: i3.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i3.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i3.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i3.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: i6.SessionConfigurationComponent, selector: "c8y-session-configuration", inputs: ["authConfiguration"] }, { kind: "component", type: i7.LoginSettingsComponent, selector: "c8y-login-settings", inputs: ["authConfiguration"] }, { kind: "component", type: i8.BasicAuthSettingsComponent, selector: "c8y-basic-auth-settings", inputs: ["authConfiguration"] }, { kind: "component", type: i9.TfaSettingsComponent, selector: "c8y-auth-tfa", inputs: ["authConfiguration"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AuthConfigurationComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-auth-configuration', template: "<c8y-title>{{ 'Authentication' | translate }}</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'cog'\"\n [label]=\"'Settings' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'cog'\"\n [label]=\"'Authentication' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n (click)=\"loadAuthConfig()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading$ | async }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/authentication/basic-settings/#basic-settings\"></c8y-help>\n\n<form\n class=\"card card--fullpage\"\n #authConfigurationForm=\"ngForm\"\n novalidate\n>\n <div class=\"card-header separator\">\n <div class=\"card-title\">\n {{ 'Authentication' | translate }}\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n *ngIf=\"authConfiguration\"\n >\n <c8y-login-settings [authConfiguration]=\"authConfiguration\"></c8y-login-settings>\n <c8y-basic-auth-settings [authConfiguration]=\"authConfiguration\"></c8y-basic-auth-settings>\n <c8y-session-configuration [authConfiguration]=\"authConfiguration\"></c8y-session-configuration>\n <c8y-auth-tfa [authConfiguration]=\"authConfiguration\"></c8y-auth-tfa>\n </div>\n <div class=\"card-footer separator\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n (click)=\"save()\"\n [disabled]=\"!authConfigurationForm.form.valid || authConfigurationForm.form.pristine\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</form>\n" }] }], ctorParameters: () => [{ type: i1.AuthConfigurationService }, { type: i2.TenantLoginOptionsService }, { type: i3.ModalService }, { type: i3.LoginService }, { type: i3.AlertService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC1jb25maWd1cmF0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2F1dGgtY29uZmlndXJhdGlvbi9iYXNpYy1zZXR0aW5ncy9hdXRoLWNvbmZpZ3VyYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vYXV0aC1jb25maWd1cmF0aW9uL2Jhc2ljLXNldHRpbmdzL2F1dGgtY29uZmlndXJhdGlvbi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDeEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN0QyxPQUFPLEVBQUUsZUFBZSxFQUE0QixNQUFNLE1BQU0sQ0FBQztBQUNqRSxPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7Ozs7Ozs7QUFPN0QsTUFBTSxPQUFPLDBCQUEwQjtJQWNyQyxZQUNVLHdCQUFrRCxFQUNsRCx5QkFBb0QsRUFDcEQsWUFBMEIsRUFDMUIsWUFBMEIsRUFDMUIsWUFBMEI7UUFKMUIsNkJBQXdCLEdBQXhCLHdCQUF3QixDQUEwQjtRQUNsRCw4QkFBeUIsR0FBekIseUJBQXlCLENBQTJCO1FBQ3BELGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBbEJwQyxlQUFVLEdBQTZCLElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xFLFdBQU0sR0FBdUIsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUd4Qyx1QkFBa0IsR0FBa0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQzFFLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUNyQyxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLHFCQUFxQixFQUFFLENBQUMsRUFDdEUsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQ3RDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FDZixDQUFDO0lBVUMsQ0FBQztJQUVKLFFBQVE7UUFDTixJQUFJLENBQUMsNkJBQTZCLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FDcEUsQ0FBQyxpQkFBb0MsRUFBRSxFQUFFO1lBQ3ZDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztZQUMzQyxJQUFJLENBQUMseUJBQXlCLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3JFLENBQUMsQ0FDRixDQUFDO1FBQ0YsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRCxjQUFjO1FBQ1osSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNuRCxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUk7UUFDUixJQUFJLENBQUM7WUFDSCxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDeEMsTUFBTSxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUN0QyxJQUFJLENBQUMsaUJBQWlCLEVBQ3RCLElBQUksQ0FBQyx5QkFBeUIsQ0FDL0IsQ0FBQztZQUNGLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkMsQ0FBQztRQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDWixJQUFJLEVBQUUsRUFBRSxDQUFDO2dCQUNQLElBQUksQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDekMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDOytHQXJEVSwwQkFBMEI7bUdBQTFCLDBCQUEwQiw4RENidkMsNnZEQTREQTs7NEZEL0NhLDBCQUEwQjtrQkFKdEMsU0FBUzsrQkFDRSx3QkFBd0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBdXRoQ29uZmlndXJhdGlvblNlcnZpY2UgfSBmcm9tICcuL2F1dGgtY29uZmlndXJhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IEFsZXJ0U2VydmljZSwgTG9naW5TZXJ2aWNlLCBNb2RhbFNlcnZpY2UgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IFRlbmFudExvZ2luT3B0aW9uc1NlcnZpY2UgfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBjbG9uZURlZXAgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRhcCwgc3dpdGNoTWFwLCBzaGFyZVJlcGxheSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEF1dGhDb25maWd1cmF0aW9uIH0gZnJvbSAnLi9hdXRoLWNvbmZpZ3VyYXRpb24ubW9kZWwnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktYXV0aC1jb25maWd1cmF0aW9uJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2F1dGgtY29uZmlndXJhdGlvbi5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgQXV0aENvbmZpZ3VyYXRpb25Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICByZWxvYWRpbmckOiBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKTtcbiAgcmVsb2FkOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIGF1dGhDb25maWd1cmF0aW9uOiBBdXRoQ29uZmlndXJhdGlvbjtcblxuICBwcml2YXRlIGF1dGhDb25maWd1cmF0aW9uJDogT2JzZXJ2YWJsZTxBdXRoQ29uZmlndXJhdGlvbj4gPSB0aGlzLnJlbG9hZC5waXBlKFxuICAgIHRhcCgoKSA9PiB0aGlzLnJlbG9hZGluZyQubmV4dCh0cnVlKSksXG4gICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuYXV0aENvbmZpZ3VyYXRpb25TZXJ2aWNlLmdldEF1dGhDb25maWd1cmF0aW9uJCgpKSxcbiAgICB0YXAoKCkgPT4gdGhpcy5yZWxvYWRpbmckLm5leHQoZmFsc2UpKSxcbiAgICBzaGFyZVJlcGxheSgxKVxuICApO1xuICBwcml2YXRlIHByZXZpb3VzQXV0aENvbmZpZ3VyYXRpb246IEF1dGhDb25maWd1cmF0aW9uO1xuICBwcml2YXRlIGF1dGhDb25maWd1cmF0aW9uU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBhdXRoQ29uZmlndXJhdGlvblNlcnZpY2U6IEF1dGhDb25maWd1cmF0aW9uU2VydmljZSxcbiAgICBwcml2YXRlIHRlbmFudExvZ2luT3B0aW9uc1NlcnZpY2U6IFRlbmFudExvZ2luT3B0aW9uc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBtb2RhbFNlcnZpY2U6IE1vZGFsU2VydmljZSxcbiAgICBwcml2YXRlIGxvZ2luU2VydmljZTogTG9naW5TZXJ2aWNlLFxuICAgIHByaXZhdGUgYWxlcnRTZXJ2aWNlOiBBbGVydFNlcnZpY2VcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuYXV0aENvbmZpZ3VyYXRpb25TdWJzY3JpcHRpb24gPSB0aGlzLmF1dGhDb25maWd1cmF0aW9uJC5zdWJzY3JpYmUoXG4gICAgICAoYXV0aENvbmZpZ3VyYXRpb246IEF1dGhDb25maWd1cmF0aW9uKSA9PiB7XG4gICAgICAgIHRoaXMuYXV0aENvbmZpZ3VyYXRpb24gPSBhdXRoQ29uZmlndXJhdGlvbjtcbiAgICAgICAgdGhpcy5wcmV2aW91c0F1dGhDb25maWd1cmF0aW9uID0gY2xvbmVEZWVwKHRoaXMuYXV0aENvbmZpZ3VyYXRpb24pO1xuICAgICAgfVxuICAgICk7XG4gICAgdGhpcy5sb2FkQXV0aENvbmZpZygpO1xuICB9XG5cbiAgbG9hZEF1dGhDb25maWcoKSB7XG4gICAgdGhpcy5yZWxvYWQubmV4dCgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5hdXRoQ29uZmlndXJhdGlvblN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgYXN5bmMgc2F2ZSgpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5tb2RhbFNlcnZpY2UuY29uZmlybUxvZ291dCgpO1xuICAgICAgYXdhaXQgdGhpcy5hdXRoQ29uZmlndXJhdGlvblNlcnZpY2Uuc2F2ZShcbiAgICAgICAgdGhpcy5hdXRoQ29uZmlndXJhdGlvbixcbiAgICAgICAgdGhpcy5wcmV2aW91c0F1dGhDb25maWd1cmF0aW9uXG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5sb2dpblNlcnZpY2UubG9nb3V0KHRydWUpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXgpIHtcbiAgICAgICAgdGhpcy5hbGVydFNlcnZpY2UuYWRkU2VydmVyRmFpbHVyZShleCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCI8Yzh5LXRpdGxlPnt7ICdBdXRoZW50aWNhdGlvbicgfCB0cmFuc2xhdGUgfX08L2M4eS10aXRsZT5cblxuPGM4eS1icmVhZGNydW1iPlxuICA8Yzh5LWJyZWFkY3J1bWItaXRlbVxuICAgIFtpY29uXT1cIidjb2cnXCJcbiAgICBbbGFiZWxdPVwiJ1NldHRpbmdzJyB8IHRyYW5zbGF0ZVwiXG4gID48L2M4eS1icmVhZGNydW1iLWl0ZW0+XG4gIDxjOHktYnJlYWRjcnVtYi1pdGVtXG4gICAgW2ljb25dPVwiJ2NvZydcIlxuICAgIFtsYWJlbF09XCInQXV0aGVudGljYXRpb24nIHwgdHJhbnNsYXRlXCJcbiAgPjwvYzh5LWJyZWFkY3J1bWItaXRlbT5cbjwvYzh5LWJyZWFkY3J1bWI+XG5cbjxjOHktYWN0aW9uLWJhci1pdGVtIFtwbGFjZW1lbnRdPVwiJ3JpZ2h0J1wiPlxuICA8YnV0dG9uXG4gICAgY2xhc3M9XCJidG4gYnRuLWxpbmtcIlxuICAgIHRpdGxlPVwie3sgJ1JlbG9hZCcgfCB0cmFuc2xhdGUgfX1cIlxuICAgIChjbGljayk9XCJsb2FkQXV0aENvbmZpZygpXCJcbiAgPlxuICAgIDxpXG4gICAgICBjOHlJY29uPVwicmVmcmVzaFwiXG4gICAgICBbbmdDbGFzc109XCJ7ICdpY29uLXNwaW4nOiByZWxvYWRpbmckIHwgYXN5bmMgfVwiXG4gICAgPjwvaT5cbiAgICB7eyAnUmVsb2FkJyB8IHRyYW5zbGF0ZSB9fVxuICA8L2J1dHRvbj5cbjwvYzh5LWFjdGlvbi1iYXItaXRlbT5cblxuPGM4eS1oZWxwIHNyYz1cIi9kb2NzL2F1dGhlbnRpY2F0aW9uL2Jhc2ljLXNldHRpbmdzLyNiYXNpYy1zZXR0aW5nc1wiPjwvYzh5LWhlbHA+XG5cbjxmb3JtXG4gIGNsYXNzPVwiY2FyZCBjYXJkLS1mdWxscGFnZVwiXG4gICNhdXRoQ29uZmlndXJhdGlvbkZvcm09XCJuZ0Zvcm1cIlxuICBub3ZhbGlkYXRlXG4+XG4gIDxkaXYgY2xhc3M9XCJjYXJkLWhlYWRlciBzZXBhcmF0b3JcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY2FyZC10aXRsZVwiPlxuICAgICAge3sgJ0F1dGhlbnRpY2F0aW9uJyB8IHRyYW5zbGF0ZSB9fVxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGRpdlxuICAgIGNsYXNzPVwiaW5uZXItc2Nyb2xsXCJcbiAgICAqbmdJZj1cImF1dGhDb25maWd1cmF0aW9uXCJcbiAgPlxuICAgIDxjOHktbG9naW4tc2V0dGluZ3MgW2F1dGhDb25maWd1cmF0aW9uXT1cImF1dGhDb25maWd1cmF0aW9uXCI+PC9jOHktbG9naW4tc2V0dGluZ3M+XG4gICAgPGM4eS1iYXNpYy1hdXRoLXNldHRpbmdzIFthdXRoQ29uZmlndXJhdGlvbl09XCJhdXRoQ29uZmlndXJhdGlvblwiPjwvYzh5LWJhc2ljLWF1dGgtc2V0dGluZ3M+XG4gICAgPGM4eS1zZXNzaW9uLWNvbmZpZ3VyYXRpb24gW2F1dGhDb25maWd1cmF0aW9uXT1cImF1dGhDb25maWd1cmF0aW9uXCI+PC9jOHktc2Vzc2lvbi1jb25maWd1cmF0aW9uPlxuICAgIDxjOHktYXV0aC10ZmEgW2F1dGhDb25maWd1cmF0aW9uXT1cImF1dGhDb25maWd1cmF0aW9uXCI+PC9jOHktYXV0aC10ZmE+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiY2FyZC1mb290ZXIgc2VwYXJhdG9yXCI+XG4gICAgPGJ1dHRvblxuICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxuICAgICAgdGl0bGU9XCJ7eyAnU2F2ZScgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAoY2xpY2spPVwic2F2ZSgpXCJcbiAgICAgIFtkaXNhYmxlZF09XCIhYXV0aENvbmZpZ3VyYXRpb25Gb3JtLmZvcm0udmFsaWQgfHwgYXV0aENvbmZpZ3VyYXRpb25Gb3JtLmZvcm0ucHJpc3RpbmVcIlxuICAgID5cbiAgICAgIHt7ICdTYXZlJyB8IHRyYW5zbGF0ZSB9fVxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cbjwvZm9ybT5cbiJdfQ==