@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
111 lines • 45.7 kB
JavaScript
import { Component, Input } from '@angular/core';
import { gettext } from '@c8y/ngx-components';
import { pull, defaultsDeep } from 'lodash-es';
import { ControlContainer, NgForm } from '@angular/forms';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@c8y/ngx-components";
import * as i3 from "@angular/common";
import * as i4 from "ngx-bootstrap/popover";
import * as i5 from "./dynamic-access-mapping.component";
import * as i6 from "./inventory-roles-mapping.component";
export class AccessMappingComponent {
constructor(controlContainer) {
this.controlContainer = controlContainer;
this.USE_ACCESS_MAPPING_ON_USER_CREATION_TOOLTIP = gettext('The access mapping will be executed only once during the first login, then the administrator can edit the user roles. During the next login, these mappings will not be executed.');
this.USE_ACCESS_MAPPING_ON_USER_CREATION_OPTION = gettext('Use dynamic access mapping only on user creation');
this.UPDATE_ROLES_LISTED_IN_ACCESS_MAPPING_ON_EACH_LOG_IN_TOOLTIP = gettext('The access mapping will be executed only once during the first login, then the administrator can edit the user roles. During the next login only the roles listed in the access mappings will be updated.');
this.UPDATE_ROLES_LISTED_IN_ACCESS_MAPPING_ON_EACH_LOG_IN_OPTION = gettext('Roles selected in the rules below will be reassigned to a user on each log in and other ones will be unchanged');
this.CLEAR_AND_UPDATED_ROLES_ON_EACH_LOG_IN_TOOLTIP = gettext('The access mapping will be executed during the first login. The administrator cannot edit the SSO user roles. During the next login all the roles will be cleared and the mapping will be executed again.');
this.CLEAR_AND_UPDATED_ROLES_ON_EACH_LOG_IN_OPTION = gettext('Roles selected in the rules below will be reassigned to a user on each log in and other ones will be cleared');
this.RETRIVE_FROM_ACCESS_TOKEN = gettext('Retrieve from Access token');
this.RETRIVE_FROM_ID_TOKEN = gettext('Retrieve from ID token');
}
ngOnChanges() {
if (this.templateModel && this.apps && this.groups) {
this.setDynamicMapping();
}
}
addAccessMapping() {
const emptyMapping = {
when: {
operator: 'AND',
childPredicates: [{ parameterPath: '', operator: 'EQ', value: '' }]
},
thenGroups: [],
thenApplications: []
};
this.templateModel.onNewUser.dynamicMapping.mappings.push(emptyMapping);
}
addInventoryMapping() {
const emptyInventoryMapping = {
when: {
operator: 'AND',
childPredicates: [{ parameterPath: '', operator: 'EQ', value: '' }]
},
thenInventoryRoles: []
};
this.templateModel.onNewUser.dynamicMapping.inventoryMappings.push(emptyInventoryMapping);
}
onRemove(accessMapping) {
pull(this.templateModel.onNewUser.dynamicMapping.mappings, accessMapping);
}
onRemoveInventoryMapping(inventoryMapping) {
pull(this.templateModel.onNewUser.dynamicMapping.inventoryMappings, inventoryMapping);
}
setDynamicMappingConfiguration(mapRolesOnlyForNewUser, manageRolesOnlyFromAccessMapping = false) {
this.dynamicMappingConfiguration.mapRolesOnlyForNewUser = mapRolesOnlyForNewUser;
this.dynamicMappingConfiguration.manageRolesOnlyFromAccessMapping =
manageRolesOnlyFromAccessMapping;
this.controlContainer.control.markAsDirty();
}
get mapRolesOnlyForNewUser() {
return this.dynamicMappingConfiguration.mapRolesOnlyForNewUser;
}
get manageRolesOnlyFromAccessMapping() {
return this.dynamicMappingConfiguration.manageRolesOnlyFromAccessMapping;
}
get mapFromIdToken() {
return this.dynamicMappingConfiguration.mapFromIdToken;
}
setMapFromIdToken(mapFromIdToken) {
this.dynamicMappingConfiguration.mapFromIdToken = mapFromIdToken;
this.controlContainer.control.markAsDirty();
}
get dynamicMappingConfiguration() {
return this.templateModel.onNewUser.dynamicMapping.configuration;
}
setDynamicMapping() {
defaultsDeep(this.templateModel.onNewUser, {
dynamicMapping: {
mappings: [],
inventoryMappings: [],
configuration: {
mapRolesOnlyForNewUser: false,
manageRolesOnlyFromAccessMapping: false
}
}
});
const { configuration } = this.templateModel.onNewUser.dynamicMapping;
const { mapRolesOnlyForNewUser, manageRolesOnlyFromAccessMapping, mapFromIdToken } = configuration;
configuration.mapFromIdToken =
mapFromIdToken !== undefined
? mapFromIdToken
: mapRolesOnlyForNewUser === false && manageRolesOnlyFromAccessMapping === false;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AccessMappingComponent, deps: [{ token: i1.ControlContainer }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AccessMappingComponent, selector: "c8y-sso-access-mapping", inputs: { apps: "apps", groups: "groups", inventoryRoles: "inventoryRoles", templateModel: "templateModel" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"p-24\">\n <div class=\"row\">\n <div class=\"col-xs-12 col-sm-3 col-md-2\">\n <div\n class=\"h4 text-normal text-right text-left-xs\"\n translate\n >\n Access mapping\n </div>\n </div>\n\n <div class=\"col-xs-12 col-sm-9 col-md-10 col-lg-9\">\n <fieldset class=\"c8y-fieldset p-24\">\n <legend>{{ 'Source of dynamic access mapping' | translate }}</legend>\n <c8y-form-group>\n <label\n title=\"{{ RETRIVE_FROM_ACCESS_TOKEN | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingSource\"\n data-cy=\"dynamic-access-mapping-from-access-token\"\n [checked]=\"!mapFromIdToken\"\n (change)=\"setMapFromIdToken(false)\"\n />\n <span></span>\n <span>{{ RETRIVE_FROM_ACCESS_TOKEN | translate }}</span>\n </label>\n <label\n title=\"{{ RETRIVE_FROM_ID_TOKEN | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingSource\"\n data-cy=\"dynamic-access-mapping-from-id-token\"\n [checked]=\"mapFromIdToken\"\n (change)=\"setMapFromIdToken(true)\"\n />\n <span></span>\n <span>{{ RETRIVE_FROM_ID_TOKEN | translate }}</span>\n </label>\n </c8y-form-group>\n </fieldset>\n\n <fieldset class=\"c8y-fieldset p-24\">\n <legend>{{ 'Dynamic access mapping principle' | translate }}</legend>\n <c8y-form-group>\n <label\n title=\"{{ USE_ACCESS_MAPPING_ON_USER_CREATION_OPTION | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingConfiguration\"\n data-cy=\"c8y-inventory-roles-mapping--on-user-creation\"\n [checked]=\"mapRolesOnlyForNewUser\"\n (change)=\"setDynamicMappingConfiguration(true)\"\n />\n <span></span>\n <span>{{ USE_ACCESS_MAPPING_ON_USER_CREATION_OPTION | translate }}</span>\n <button\n class=\"btn-help\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ USE_ACCESS_MAPPING_ON_USER_CREATION_TOOLTIP | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n <label\n title=\"{{ UPDATE_ROLES_LISTED_IN_ACCESS_MAPPING_ON_EACH_LOG_IN_OPTION | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingConfiguration\"\n data-cy=\"c8y-inventory-roles-mapping--other-ones-will-be-unchanged\"\n [checked]=\"!mapRolesOnlyForNewUser && manageRolesOnlyFromAccessMapping\"\n (change)=\"setDynamicMappingConfiguration(false, true)\"\n />\n <span></span>\n <span>\n {{ UPDATE_ROLES_LISTED_IN_ACCESS_MAPPING_ON_EACH_LOG_IN_OPTION | translate }}\n </span>\n <button\n type=\"button\"\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ UPDATE_ROLES_LISTED_IN_ACCESS_MAPPING_ON_EACH_LOG_IN_TOOLTIP | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n <label\n title=\"{{ CLEAR_AND_UPDATED_ROLES_ON_EACH_LOG_IN_OPTION | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingConfiguration\"\n data-cy=\"c8y-inventory-roles-mapping--other-ones-will-be-cleared\"\n [checked]=\"!mapRolesOnlyForNewUser && !manageRolesOnlyFromAccessMapping\"\n (change)=\"setDynamicMappingConfiguration(false, false)\"\n />\n <span></span>\n <span>\n {{ CLEAR_AND_UPDATED_ROLES_ON_EACH_LOG_IN_OPTION | translate }}\n </span>\n <button\n class=\"btn-help\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ CLEAR_AND_UPDATED_ROLES_ON_EACH_LOG_IN_TOOLTIP | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n </c8y-form-group>\n </fieldset>\n <fieldset class=\"c8y-fieldset p-16\">\n <legend>{{ 'Dynamic access mapping' | translate }}</legend>\n <c8y-ui-empty-state\n *ngIf=\"templateModel.onNewUser.dynamicMapping.mappings.length === 0\"\n [icon]=\"'list'\"\n [title]=\"'No access mapping rules defined.' | translate\"\n [subtitle]=\"'Click below to add a new mapping.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <div\n *ngFor=\"\n let accessMapping of templateModel.onNewUser.dynamicMapping.mappings;\n index as idx\n \"\n >\n <c8y-sso-dynamic-access-mapping\n [accessMapping]=\"accessMapping\"\n (onRemoveAccessMapping)=\"onRemove(accessMapping)\"\n [apps]=\"apps\"\n [groups]=\"groups\"\n [accessMappingIndex]=\"idx\"\n ></c8y-sso-dynamic-access-mapping>\n </div>\n <div class=\"p-t-16\">\n <button\n id=\"add-access-mapping-button\"\n class=\"btn btn-default\"\n type=\"button\"\n title=\"{{ 'Add access mapping' | translate }}\"\n (click)=\"addAccessMapping()\"\n >\n <i\n c8yIcon=\"plus-circle\"\n class=\"m-r-4\"\n ></i>\n {{ 'Add access mapping' | translate }}\n </button>\n </div>\n </fieldset>\n <fieldset class=\"c8y-fieldset p-16\">\n <legend>\n {{ 'Inventory roles mapping' | translate }}\n </legend>\n <c8y-ui-empty-state\n *ngIf=\"templateModel.onNewUser.dynamicMapping.inventoryMappings.length === 0\"\n [icon]=\"'list'\"\n [title]=\"'No inventory roles mapping rules defined.' | translate\"\n [subtitle]=\"'Click below to add a new mapping.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <ng-container\n *ngFor=\"\n let inventoryMapping of templateModel.onNewUser.dynamicMapping.inventoryMappings;\n index as idx\n \"\n >\n <c8y-sso-inventory-roles-mapping\n [inventoryRoles]=\"inventoryRoles\"\n [inventoryMapping]=\"inventoryMapping\"\n (onRemoveInventoryMapping)=\"onRemoveInventoryMapping(inventoryMapping)\"\n [inventoryMappingIndex]=\"idx\"\n ></c8y-sso-inventory-roles-mapping>\n </ng-container>\n <div class=\"p-t-16\">\n <button\n id=\"add-inventory-mapping-button\"\n class=\"btn btn-default\"\n type=\"button\"\n title=\"{{ 'Add inventory roles mapping' | translate }}\"\n (click)=\"addInventoryMapping()\"\n >\n <i\n c8yIcon=\"plus-circle\"\n class=\"m-r-4\"\n ></i>\n {{ 'Add inventory roles mapping' | translate }}\n </button>\n </div>\n </fieldset>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i4.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: i5.DynamicAccessMappingComponent, selector: "c8y-sso-dynamic-access-mapping", inputs: ["groups", "apps", "accessMapping", "accessMappingIndex"], outputs: ["onRemoveAccessMapping"] }, { kind: "component", type: i6.InventoryRolesMappingComponent, selector: "c8y-sso-inventory-roles-mapping", inputs: ["inventoryMapping", "inventoryMappingIndex", "inventoryRoles"], outputs: ["onRemoveInventoryMapping"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AccessMappingComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-sso-access-mapping', viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], template: "<div class=\"p-24\">\n <div class=\"row\">\n <div class=\"col-xs-12 col-sm-3 col-md-2\">\n <div\n class=\"h4 text-normal text-right text-left-xs\"\n translate\n >\n Access mapping\n </div>\n </div>\n\n <div class=\"col-xs-12 col-sm-9 col-md-10 col-lg-9\">\n <fieldset class=\"c8y-fieldset p-24\">\n <legend>{{ 'Source of dynamic access mapping' | translate }}</legend>\n <c8y-form-group>\n <label\n title=\"{{ RETRIVE_FROM_ACCESS_TOKEN | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingSource\"\n data-cy=\"dynamic-access-mapping-from-access-token\"\n [checked]=\"!mapFromIdToken\"\n (change)=\"setMapFromIdToken(false)\"\n />\n <span></span>\n <span>{{ RETRIVE_FROM_ACCESS_TOKEN | translate }}</span>\n </label>\n <label\n title=\"{{ RETRIVE_FROM_ID_TOKEN | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingSource\"\n data-cy=\"dynamic-access-mapping-from-id-token\"\n [checked]=\"mapFromIdToken\"\n (change)=\"setMapFromIdToken(true)\"\n />\n <span></span>\n <span>{{ RETRIVE_FROM_ID_TOKEN | translate }}</span>\n </label>\n </c8y-form-group>\n </fieldset>\n\n <fieldset class=\"c8y-fieldset p-24\">\n <legend>{{ 'Dynamic access mapping principle' | translate }}</legend>\n <c8y-form-group>\n <label\n title=\"{{ USE_ACCESS_MAPPING_ON_USER_CREATION_OPTION | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingConfiguration\"\n data-cy=\"c8y-inventory-roles-mapping--on-user-creation\"\n [checked]=\"mapRolesOnlyForNewUser\"\n (change)=\"setDynamicMappingConfiguration(true)\"\n />\n <span></span>\n <span>{{ USE_ACCESS_MAPPING_ON_USER_CREATION_OPTION | translate }}</span>\n <button\n class=\"btn-help\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ USE_ACCESS_MAPPING_ON_USER_CREATION_TOOLTIP | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n <label\n title=\"{{ UPDATE_ROLES_LISTED_IN_ACCESS_MAPPING_ON_EACH_LOG_IN_OPTION | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingConfiguration\"\n data-cy=\"c8y-inventory-roles-mapping--other-ones-will-be-unchanged\"\n [checked]=\"!mapRolesOnlyForNewUser && manageRolesOnlyFromAccessMapping\"\n (change)=\"setDynamicMappingConfiguration(false, true)\"\n />\n <span></span>\n <span>\n {{ UPDATE_ROLES_LISTED_IN_ACCESS_MAPPING_ON_EACH_LOG_IN_OPTION | translate }}\n </span>\n <button\n type=\"button\"\n class=\"btn-help\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ UPDATE_ROLES_LISTED_IN_ACCESS_MAPPING_ON_EACH_LOG_IN_TOOLTIP | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n <label\n title=\"{{ CLEAR_AND_UPDATED_ROLES_ON_EACH_LOG_IN_OPTION | translate }}\"\n class=\"c8y-radio input-sm\"\n >\n <input\n type=\"radio\"\n name=\"dynamicAccessMappingConfiguration\"\n data-cy=\"c8y-inventory-roles-mapping--other-ones-will-be-cleared\"\n [checked]=\"!mapRolesOnlyForNewUser && !manageRolesOnlyFromAccessMapping\"\n (change)=\"setDynamicMappingConfiguration(false, false)\"\n />\n <span></span>\n <span>\n {{ CLEAR_AND_UPDATED_ROLES_ON_EACH_LOG_IN_OPTION | translate }}\n </span>\n <button\n class=\"btn-help\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ CLEAR_AND_UPDATED_ROLES_ON_EACH_LOG_IN_TOOLTIP | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n </c8y-form-group>\n </fieldset>\n <fieldset class=\"c8y-fieldset p-16\">\n <legend>{{ 'Dynamic access mapping' | translate }}</legend>\n <c8y-ui-empty-state\n *ngIf=\"templateModel.onNewUser.dynamicMapping.mappings.length === 0\"\n [icon]=\"'list'\"\n [title]=\"'No access mapping rules defined.' | translate\"\n [subtitle]=\"'Click below to add a new mapping.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <div\n *ngFor=\"\n let accessMapping of templateModel.onNewUser.dynamicMapping.mappings;\n index as idx\n \"\n >\n <c8y-sso-dynamic-access-mapping\n [accessMapping]=\"accessMapping\"\n (onRemoveAccessMapping)=\"onRemove(accessMapping)\"\n [apps]=\"apps\"\n [groups]=\"groups\"\n [accessMappingIndex]=\"idx\"\n ></c8y-sso-dynamic-access-mapping>\n </div>\n <div class=\"p-t-16\">\n <button\n id=\"add-access-mapping-button\"\n class=\"btn btn-default\"\n type=\"button\"\n title=\"{{ 'Add access mapping' | translate }}\"\n (click)=\"addAccessMapping()\"\n >\n <i\n c8yIcon=\"plus-circle\"\n class=\"m-r-4\"\n ></i>\n {{ 'Add access mapping' | translate }}\n </button>\n </div>\n </fieldset>\n <fieldset class=\"c8y-fieldset p-16\">\n <legend>\n {{ 'Inventory roles mapping' | translate }}\n </legend>\n <c8y-ui-empty-state\n *ngIf=\"templateModel.onNewUser.dynamicMapping.inventoryMappings.length === 0\"\n [icon]=\"'list'\"\n [title]=\"'No inventory roles mapping rules defined.' | translate\"\n [subtitle]=\"'Click below to add a new mapping.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <ng-container\n *ngFor=\"\n let inventoryMapping of templateModel.onNewUser.dynamicMapping.inventoryMappings;\n index as idx\n \"\n >\n <c8y-sso-inventory-roles-mapping\n [inventoryRoles]=\"inventoryRoles\"\n [inventoryMapping]=\"inventoryMapping\"\n (onRemoveInventoryMapping)=\"onRemoveInventoryMapping(inventoryMapping)\"\n [inventoryMappingIndex]=\"idx\"\n ></c8y-sso-inventory-roles-mapping>\n </ng-container>\n <div class=\"p-t-16\">\n <button\n id=\"add-inventory-mapping-button\"\n class=\"btn btn-default\"\n type=\"button\"\n title=\"{{ 'Add inventory roles mapping' | translate }}\"\n (click)=\"addInventoryMapping()\"\n >\n <i\n c8yIcon=\"plus-circle\"\n class=\"m-r-4\"\n ></i>\n {{ 'Add inventory roles mapping' | translate }}\n </button>\n </div>\n </fieldset>\n </div>\n </div>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.ControlContainer }], propDecorators: { apps: [{
type: Input
}], groups: [{
type: Input
}], inventoryRoles: [{
type: Input
}], templateModel: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjZXNzLW1hcHBpbmcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vYXV0aC1jb25maWd1cmF0aW9uL3Nzby1jb25maWd1cmF0aW9uL3RlbXBsYXRlLXBhcnRzL2FjY2Vzcy1tYXBwaW5nL2FjY2Vzcy1tYXBwaW5nLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL2F1dGgtY29uZmlndXJhdGlvbi9zc28tY29uZmlndXJhdGlvbi90ZW1wbGF0ZS1wYXJ0cy9hY2Nlc3MtbWFwcGluZy9hY2Nlc3MtbWFwcGluZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDOUMsT0FBTyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFL0MsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7OztBQVExRCxNQUFNLE9BQU8sc0JBQXNCO0lBOEJqQyxZQUFvQixnQkFBa0M7UUFBbEMscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQXhCdEQsZ0RBQTJDLEdBQUcsT0FBTyxDQUNuRCxtTEFBbUwsQ0FDcEwsQ0FBQztRQUNGLCtDQUEwQyxHQUFHLE9BQU8sQ0FDbEQsa0RBQWtELENBQ25ELENBQUM7UUFFRixpRUFBNEQsR0FBRyxPQUFPLENBQ3BFLDJNQUEyTSxDQUM1TSxDQUFDO1FBQ0YsZ0VBQTJELEdBQUcsT0FBTyxDQUNuRSxnSEFBZ0gsQ0FDakgsQ0FBQztRQUVGLG1EQUE4QyxHQUFHLE9BQU8sQ0FDdEQsMk1BQTJNLENBQzVNLENBQUM7UUFDRixrREFBNkMsR0FBRyxPQUFPLENBQ3JELDhHQUE4RyxDQUMvRyxDQUFDO1FBRUYsOEJB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RTtnQkFDZCxRQUFRLEVBQUUsRUFBRTtnQkFDWixpQkFBaUIsRUFBRSxFQUFFO2dCQUNyQixhQUFhLEVBQUU7b0JBQ2Isc0JBQXNCLEVBQUUsS0FBSztvQkFDN0IsZ0NBQWdDLEVBQUUsS0FBSztpQkFDeEM7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNILE1BQU0sRUFBRSxhQUFhLEVBQUUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUM7UUFDdEUsTUFBTSxFQUFFLHNCQUFzQixFQUFFLGdDQUFnQyxFQUFFLGNBQWMsRUFBRSxHQUNoRixhQUFhLENBQUM7UUFDaEIsYUFBYSxDQUFDLGNBQWM7WUFDMUIsY0FBYyxLQUFLLFNBQVM7Z0JBQzFCLENBQUMsQ0FBQyxjQUFjO2dCQUNoQixDQUFDLENBQUMsc0JBQXNCLEtBQUssS0FBSyxJQUFJLGdDQUFnQyxLQUFLLEtBQUssQ0FBQztJQUN2RixDQUFDOytHQXRIVSxzQkFBc0I7bUdBQXRCLHNCQUFzQixpTUNabkMsK3ZQQThNQSxraEREcE1pQixDQUFDLEVBQUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQzs7NEZBRXhELHNCQUFzQjtrQkFMbEMsU0FBUzsrQkFDRSx3QkFBd0IsaUJBRW5CLENBQUMsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxDQUFDO3FGQUcxRCxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGdldHRleHQgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IHB1bGwsIGRlZmF1bHRzRGVlcCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBJQXBwbGljYXRpb24sIElJZGVudGlmaWVkLCBJVXNlckdyb3VwIH0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHsgQ29udHJvbENvbnRhaW5lciwgTmdGb3JtIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgSW52ZW50b3J5TWFwcGluZywgQWNjZXNzTWFwcGluZyB9IGZyb20gJy4uLy4uL3Nzby1jb25maWd1cmF0aW9uLm1vZGVsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYzh5LXNzby1hY2Nlc3MtbWFwcGluZycsXG4gIHRlbXBsYXRlVXJsOiAnLi9hY2Nlc3MtbWFwcGluZy5jb21wb25lbnQuaHRtbCcsXG4gIHZpZXdQcm92aWRlcnM6IFt7IHByb3ZpZGU6IENvbnRyb2xDb250YWluZXIsIHVzZUV4aXN0aW5nOiBOZ0Zvcm0gfV1cbn0pXG5leHBvcnQgY2xhc3MgQWNjZXNzTWFwcGluZ0NvbXBvbmVudCB7XG4gIEBJbnB1dCgpIGFwcHM6IElBcHBsaWNhdGlvbltdO1xuICBASW5wdXQoKSBncm91cHM6IElVc2VyR3JvdXBbXTtcbiAgQElucHV0KCkgaW52ZW50b3J5Um9sZXM6IElJZGVudGlmaWVkW107XG4gIEBJbnB1dCgpIHRlbXBsYXRlTW9kZWw7XG5cbiAgVVNFX0FDQ0VTU19NQVBQSU5HX09OX1VTRVJfQ1JFQVRJT05fVE9PTFRJUCA9IGdldHRleHQoXG4gICAgJ1RoZSBhY2Nlc3MgbWFwcGluZyB3aWxsIGJlIGV4ZWN1dGVkIG9ubHkgb25jZSBkdXJpbmcgdGhlIGZpcnN0IGxvZ2luLCB0aGVuIHRoZSBhZG1pbmlzdHJhdG9yIGNhbiBlZGl0IHRoZSB1c2VyIHJvbGVzLiBEdXJpbmcgdGhlIG5leHQgbG9naW4sIHRoZXNlIG1hcHBpbmdzIHdpbGwgbm90IGJlIGV4ZWN1dGVkLidcbiAgKTtcbiAgVVNFX0FDQ0VTU19NQVBQSU5HX09OX1VTRVJfQ1JFQVRJT05fT1BUSU9OID0gZ2V0dGV4dChcbiAgICAnVXNlIGR5bmFtaWMgYWNjZXNzIG1hcHBpbmcgb25seSBvbiB1c2VyIGNyZWF0aW9uJ1xuICApO1xuXG4gIFVQREFURV9ST0xFU19MSVNURURfSU5fQUNDRVNTX01BUFBJTkdfT05fRUFDSF9MT0dfSU5fVE9PTFRJUCA9IGdldHRleHQoXG4gICAgJ1RoZSBhY2Nlc3MgbWFwcGluZyB3aWxsIGJlIGV4ZWN1dGVkIG9ubHkgb25jZSBkdXJpbmcgdGhlIGZpcnN0IGxvZ2luLCB0aGVuIHRoZSBhZG1pbmlzdHJhdG9yIGNhbiBlZGl0IHRoZSB1c2VyIHJvbGVzLiBEdXJpbmcgdGhlIG5leHQgbG9naW4gb25seSB0aGUgcm9sZXMgbGlzdGVkIGluIHRoZSBhY2Nlc3MgbWFwcGluZ3Mgd2lsbCBiZSB1cGRhdGVkLidcbiAgKTtcbiAgVVBEQVRFX1JPTEVTX0xJU1RFRF9JTl9BQ0NFU1NfTUFQUElOR19PTl9FQUNIX0xPR19JTl9PUFRJT04gPSBnZXR0ZXh0KFxuICAgICdSb2xlcyBzZWxlY3RlZCBpbiB0aGUgcnVsZXMgYmVsb3cgd2lsbCBiZSByZWFzc2lnbmVkIHRvIGEgdXNlciBvbiBlYWNoIGxvZyBpbiBhbmQgb3RoZXIgb25lcyB3aWxsIGJlIHVuY2hhbmdlZCdcbiAgKTtcblxuICBDTEVBUl9BTkRfVVBEQVRFRF9ST0xFU19PTl9FQUNIX0xPR19JTl9UT09MVElQID0gZ2V0dGV4dChcbiAgICAnVGhlIGFjY2VzcyBtYXBwaW5nIHdpbGwgYmUgZXhlY3V0ZWQgZHVyaW5nIHRoZSBmaXJzdCBsb2dpbi4gVGhlIGFkbWluaXN0cmF0b3IgY2Fubm90IGVkaXQgdGhlIFNTTyB1c2VyIHJvbGVzLiBEdXJpbmcgdGhlIG5leHQgbG9naW4gYWxsIHRoZSByb2xlcyB3aWxsIGJlIGNsZWFyZWQgYW5kIHRoZSBtYXBwaW5nIHdpbGwgYmUgZXhlY3V0ZWQgYWdhaW4uJ1xuICApO1xuICBDTEVBUl9BTkRfVVBEQVRFRF9ST0xFU19PTl9FQUNIX0xPR19JTl9PUFRJT04gPSBnZXR0ZXh0KFxuICAgICdSb2xlcyBzZWxlY3RlZCBpbiB0aGUgcnVsZXMgYmVsb3cgd2lsbCBiZSByZWFzc2lnbmVkIHRvIGEgdXNlciBvbiBlYWNoIGxvZyBpbiBhbmQgb3RoZXIgb25lcyB3aWxsIGJlIGNsZWFyZWQnXG4gICk7XG5cbiAgUkVUUklWRV9GUk9NX0FDQ0VTU19UT0tFTiA9IGdldHRleHQoJ1JldHJpZXZlIGZyb20gQWNjZXNzIHRva2VuJyk7XG4gIFJFVFJJVkVfRlJPTV9JRF9UT0tFTiA9IGdldHRleHQoJ1JldHJpZXZlIGZyb20gSUQgdG9rZW4nKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNvbnRyb2xDb250YWluZXI6IENvbnRyb2xDb250YWluZXIpIHt9XG5cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMudGVtcGxhdGVNb2RlbCAmJiB0aGlzLmFwcHMgJiYgdGhpcy5ncm91cHMpIHtcbiAgICAgIHRoaXMuc2V0RHluYW1pY01hcHBpbmcoKTtcbiAgICB9XG4gIH1cblxuICBhZGRBY2Nlc3NNYXBwaW5nKCkge1xuICAgIGNvbnN0IGVtcHR5TWFwcGluZzogQWNjZXNzTWFwcGluZyA9IHtcbiAgICAgIHdoZW46IHtcbiAgICAgICAgb3BlcmF0b3I6ICdBTkQnLFxuICAgICAgICBjaGlsZFByZWRpY2F0ZXM6IFt7IHBhcmFtZXRlclBhdGg6ICcnLCBvcGVyYXRvcjogJ0VRJywgdmFsdWU6ICcnIH1dXG4gICAgICB9LFxuICAgICAgdGhlbkdyb3VwczogW10sXG4gICAgICB0aGVuQXBwbGljYXRpb25zOiBbXVxuICAgIH07XG4gICAgdGhpcy50ZW1wbGF0ZU1vZGVsLm9uTmV3VXNlci5keW5hbWljTWFwcGluZy5tYXBwaW5ncy5wdXNoKGVtcHR5TWFwcGluZyk7XG4gIH1cblxuICBhZGRJbnZlbnRvcnlNYXBwaW5nKCkge1xuICAgIGNvbnN0IGVtcHR5SW52ZW50b3J5TWFwcGluZzogSW52ZW50b3J5TWFwcGluZyA9IHtcbiAgICAgIHdoZW46IHtcbiAgICAgICAgb3BlcmF0b3I6ICdBTkQnLFxuICAgICAgICBjaGlsZFByZWRpY2F0ZXM6IFt7IHBhcmFtZXRlclBhdGg6ICcnLCBvcGVyYXRvcjogJ0VRJywgdmFsdWU6ICcnIH1dXG4gICAgICB9LFxuICAgICAgdGhlbkludmVudG9yeVJvbGVzOiBbXVxuICAgIH07XG4gICAgdGhpcy50ZW1wbGF0ZU1vZGVsLm9uTmV3VXNlci5keW5hbWljTWFwcGluZy5pbnZlbnRvcnlNYXBwaW5ncy5wdXNoKGVtcHR5SW52ZW50b3J5TWFwcGluZyk7XG4gIH1cblxuICBvblJlbW92ZShhY2Nlc3NNYXBwaW5nOiBBY2Nlc3NNYXBwaW5nKSB7XG4gICAgcHVsbCh0aGlzLnRlbXBsYXRlTW9kZWwub25OZXdVc2VyLmR5bmFtaWNNYXBwaW5nLm1hcHBpbmdzLCBhY2Nlc3NNYXBwaW5nKTtcbiAgfVxuXG4gIG9uUmVtb3ZlSW52ZW50b3J5TWFwcGluZyhpbnZlbnRvcnlNYXBwaW5nOiBJbnZlbnRvcnlNYXBwaW5nKSB7XG4gICAgcHVsbCh0aGlzLnRlbXBsYXRlTW9kZWwub25OZXdVc2VyLmR5bmFtaWNNYXBwaW5nLmludmVudG9yeU1hcHBpbmdzLCBpbnZlbnRvcnlNYXBwaW5nKTtcbiAgfVxuXG4gIHNldER5bmFtaWNNYXBwaW5nQ29uZmlndXJhdGlvbihcbiAgICBtYXBSb2xlc09ubHlGb3JOZXdVc2VyOiBib29sZWFuLFxuICAgIG1hbmFnZVJvbGVzT25seUZyb21BY2Nlc3NNYXBwaW5nID0gZmFsc2VcbiAgKSB7XG4gICAgdGhpcy5keW5hbWljTWFwcGluZ0NvbmZpZ3VyYXRpb24ubWFwUm9sZXNPbmx5Rm9yTmV3VXNlciA9IG1hcFJvbGVzT25seUZvck5ld1VzZXI7XG4gICAgdGhpcy5keW5hbWljTWFwcGluZ0NvbmZpZ3VyYXRpb24ubWFuYWdlUm9sZXNPbmx5RnJvbUFjY2Vzc01hcHBpbmcgPVxuICAgICAgbWFuYWdlUm9sZXNPbmx5RnJvbUFjY2Vzc01hcHBpbmc7XG4gICAgdGhpcy5jb250cm9sQ29udGFpbmVyLmNvbnRyb2wubWFya0FzRGlydHkoKTtcbiAgfVxuXG4gIGdldCBtYXBSb2xlc09ubHlGb3JOZXdVc2VyKCkge1xuICAgIHJldHVybiB0aGlzLmR5bmFtaWNNYXBwaW5nQ29uZmlndXJhdGlvbi5tYXBSb2xlc09ubHlGb3JOZXdVc2VyO1xuICB9XG5cbiAgZ2V0IG1hbmFnZVJvbGVzT25seUZyb21BY2Nlc3NNYXBwaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmR5bmFtaWNNYXBwaW5nQ29uZmlndXJhdGlvbi5tYW5hZ2VSb2xlc09ubHlGcm9tQWNjZXNzTWFwcGluZztcbiAgfVxuXG4gIGdldCBtYXBGcm9tSWRUb2tlbigpIHtcbiAgICByZXR1cm4gdGhpcy5keW5hbWljTWFwcGluZ0NvbmZpZ3VyYXRpb24ubWFwRnJvbUlkVG9rZW47XG4gIH1cblxuICBzZXRNYXBGcm9tSWRUb2tlbihtYXBGcm9tSWRUb2tlbikge1xuICAgIHRoaXMuZHluYW1pY01hcHBpbmdDb25maWd1cmF0aW9uLm1hcEZyb21JZFRva2VuID0gbWFwRnJvbUlkVG9rZW47XG4gICAgdGhpcy5jb250cm9sQ29udGFpbmVyLmNvbnRyb2wubWFya0FzRGlydHkoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGR5bmFtaWNNYXBwaW5nQ29uZmlndXJhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy50ZW1wbGF0ZU1vZGVsLm9uTmV3VXNlci5keW5hbWljTWFwcGluZy5jb25maWd1cmF0aW9uO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXREeW5hbWljTWFwcGluZygpIHtcbiAgICBkZWZhdWx0c0RlZXAodGhpcy50ZW1wbGF0ZU1vZGVsLm9uTmV3VXNlciwge1xuICAgICAgZHluYW1pY01hcHBpbmc6IHtcbiAgICAgICAgbWFwcGluZ3M6IFtdLFxuICAgICAgICBpbnZlbnRvcnlNYXBwaW5nczogW10sXG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgICBtYXBSb2xlc09ubHlGb3JOZXdVc2VyOiBmYWxzZSxcbiAgICAgICAgICBtYW5hZ2VSb2xlc09ubHlGcm9tQWNjZXNzTWFwcGluZzogZmFsc2VcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIGNvbnN0IHsgY29uZmlndXJhdGlvbiB9ID0gdGhpcy50ZW1wbGF0ZU1vZGVsLm9uTmV3VXNlci5keW5hbWljTWFwcGluZztcbiAgICBjb25zdCB7IG1hcFJvbGVzT25seUZvck5ld1VzZXIsIG1hbmFnZVJvbGVzT25seUZyb21BY2Nlc3NNYXBwaW5nLCBtYXBGcm9tSWRUb2tlbiB9ID1cbiAgICAgIGNvbmZpZ3VyYXRpb247XG4gICAgY29uZmlndXJhdGlvbi5tYXBGcm9tSWRUb2tlbiA9XG4gICAgICBtYXBGcm9tSWRUb2tlbiAhPT0gdW5kZWZpbmVkXG4gICAgICAgID8gbWFwRnJvbUlkVG9rZW5cbiAgICAgICAgOiBtYXBSb2xlc09ubHlGb3JOZXdVc2VyID09PSBmYWxzZSAmJiBtYW5hZ2VSb2xlc09ubHlGcm9tQWNjZXNzTWFwcGluZyA9PT0gZmFsc2U7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJwLTI0XCI+XG4gIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLXhzLTEyIGNvbC1zbS0zIGNvbC1tZC0yXCI+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwiaDQgdGV4dC1ub3JtYWwgdGV4dC1yaWdodCB0ZXh0LWxlZnQteHNcIlxuICAgICAgICB0cmFuc2xhdGVcbiAgICAgID5cbiAgICAgICAgQWNjZXNzIG1hcHBpbmdcbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cImNvbC14cy0xMiBjb2wtc20tOSBjb2wtbWQtMTAgY29sLWxnLTlcIj5cbiAgICAgIDxmaWVsZHNldCBjbGFzcz1cImM4eS1maWVsZHNldCBwLTI0XCI+XG4gICAgICAgIDxsZWdlbmQ+e3sgJ1NvdXJjZSBvZiBkeW5hbWljIGFjY2VzcyBtYXBwaW5nJyB8IHRyYW5zbGF0ZSB9fTwvbGVnZW5kPlxuICAgICAgICA8Yzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgICAgPGxhYmVsXG4gICAgICAgICAgICB0aXRsZT1cInt7IFJFVFJJVkVfRlJPTV9BQ0NFU1NfVE9LRU4gfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgY2xhc3M9XCJjOHktcmFkaW8gaW5wdXQtc21cIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwicmFkaW9cIlxuICAgICAgICAgICAgICBuYW1lPVwiZHluYW1pY0FjY2Vzc01hcHBpbmdTb3VyY2VcIlxuICAgICAgICAgICAgICBkYXRhLWN5PVwiZHluYW1pYy1hY2Nlc3MtbWFwcGluZy1mcm9tLWFjY2Vzcy10b2tlblwiXG4gICAgICAgICAgICAgIFtjaGVja2VkXT1cIiFtYXBGcm9tSWRUb2tlblwiXG4gICAgICAgICAgICAgIChjaGFuZ2UpPVwic2V0TWFwRnJvbUlkVG9rZW4oZmFsc2UpXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8c3Bhbj48L3NwYW4+XG4gICAgICAgICAgICA8c3Bhbj57eyBSRVRSSVZFX0ZST01fQUNDRVNTX1RPS0VOIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgPGxhYmVsXG4gICAgICAgICAgICB0aXRsZT1cInt7IFJFVFJJVkVfRlJPTV9JRF9UT0tFTiB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICBjbGFzcz1cImM4eS1yYWRpbyBpbnB1dC1zbVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgIHR5cGU9XCJyYWRpb1wiXG4gICAgICAgICAgICAgIG5hbWU9XCJkeW5hbWljQWNjZXNzTWFwcGluZ1NvdXJjZVwiXG4gICAgICAgICAgICAgIGRhdGEtY3k9XCJkeW5hbWljLWFjY2Vzcy1tYXBwaW5nLWZyb20taWQtdG9rZW5cIlxuICAgICAgICAgICAgICBbY2hlY2tlZF09XCJtYXBGcm9tSWRUb2tlblwiXG4gICAgICAgICAgICAgIChjaGFuZ2UpPVwic2V0TWFwRnJvbUlkVG9rZW4odHJ1ZSlcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxzcGFuPjwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuPnt7IFJFVFJJVkVfRlJPTV9JRF9UT0tFTiB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICA8L2M4eS1mb3JtLWdyb3VwPlxuICAgICAgPC9maWVsZHNldD5cblxuICAgICAgPGZpZWxkc2V0IGNsYXNzPVwiYzh5LWZpZWxkc2V0IHAtMjRcIj5cbiAgICAgICAgPGxlZ2VuZD57eyAnRHluYW1pYyBhY2Nlc3MgbWFwcGluZyBwcmluY2lwbGUnIHwgdHJhbnNsYXRlIH19PC9sZWdlbmQ+XG4gICAgICAgIDxjOHktZm9ybS1ncm91cD5cbiAgICAgICAgICA8bGFiZWxcbiAgICAgICAgICAgIHRpdGxlPVwie3sgVVNFX0FDQ0VTU19NQVBQSU5HX09OX1VTRVJfQ1JFQVRJT05fT1BUSU9OIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICAgIGNsYXNzPVwiYzh5LXJhZGlvIGlucHV0LXNtXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgdHlwZT1cInJhZGlvXCJcbiAgICAgICAgICAgICAgbmFtZT1cImR5bmFtaWNBY2Nlc3NNYXBwaW5nQ29uZmlndXJhdGlvblwiXG4gICAgICAgICAgICAgIGRhdGEtY3k9XCJjOHktaW52ZW50b3J5LXJvbGVzLW1hcHBpbmctLW9uLXVzZXItY3JlYXRpb25cIlxuICAgICAgICAgICAgICBbY2hlY2tlZF09XCJtYXBSb2xlc09ubHlGb3JOZXdVc2VyXCJcbiAgICAgICAgICAgICAgKGNoYW5nZSk9XCJzZXREeW5hbWljTWFwcGluZ0NvbmZpZ3VyYXRpb24odHJ1ZSlcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxzcGFuPjwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuPnt7IFVTRV9BQ0NFU1NfTUFQUElOR19PTl9VU0VSX0NSRUFUSU9OX09QVElPTiB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgY2xhc3M9XCJidG4taGVscFwiXG4gICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidIZWxwJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgIHBvcG92ZXI9XCJ7eyBVU0VfQUNDRVNTX01BUFBJTkdfT05fVVNFUl9DUkVBVElPTl9UT09MVElQIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICAgICAgcGxhY2VtZW50PVwicmlnaHRcIlxuICAgICAgICAgICAgICB0cmlnZ2Vycz1cImZvY3VzXCJcbiAgICAgICAgICAgICAgY29udGFpbmVyPVwiYm9keVwiXG4gICAgICAgICAgICA+PC9idXR0b24+XG4gICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICA8bGFiZWxcbiAgICAgICAgICAgIHRpdGxlPVwie3sgVVBEQVRFX1JPTEVTX0xJU1RFRF9JTl9BQ0NFU1NfTUFQUElOR19PTl9FQUNIX0xPR19JTl9PUFRJT04gfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgY2xhc3M9XCJjOHktcmFkaW8gaW5wdXQtc21cIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwicmFkaW9cIlxuICAgICAgICAgICAgICBuYW1lPVwiZHluYW1pY0FjY2Vzc01hcHBpbmdDb25maWd1cmF0aW9uXCJcbiAgICAgICAgICAgICAgZGF0YS1jeT1cImM4eS1pbnZlbnRvcnktcm9sZXMtbWFwcGluZy0tb3RoZXItb25lcy13aWxsLWJlLXVuY2hhbmdlZFwiXG4gICAgICAgICAgICAgIFtjaGVja2VkXT1cIiFtYXBSb2xlc09ubHlGb3JOZXdVc2VyICYmIG1hbmFnZVJvbGVzT25seUZyb21BY2Nlc3NNYXBwaW5nXCJcbiAgICAgICAgICAgICAgKGNoYW5nZSk9XCJzZXREeW5hbWljTWFwcGluZ0NvbmZpZ3VyYXRpb24oZmFsc2UsIHRydWUpXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8c3Bhbj48L3NwYW4+XG4gICAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgICAge3sgVVBEQVRFX1JPTEVTX0xJU1RFRF9JTl9BQ0NFU1NfTUFQUElOR19PTl9FQUNIX0xPR19JTl9PUFRJT04gfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiYnRuLWhlbHBcIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidIZWxwJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgIHBvcG92ZXI9XCJ7eyBVUERBVEVfUk9MRVNfTElTVEVEX0lOX0FDQ0VTU19NQVBQSU5HX09OX0VBQ0hfTE9HX0lOX1RPT0xUSVAgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgICBwbGFjZW1lbnQ9XCJyaWdodFwiXG4gICAgICAgICAgICAgIHRyaWdnZXJzPVwiZm9jdXNcIlxuICAgICAgICAgICAgICBjb250YWluZXI9XCJib2R5XCJcbiAgICAgICAgICAgID48L2J1dHRvbj5cbiAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIDxsYWJlbFxuICAgICAgICAgICAgdGl0bGU9XCJ7eyBDTEVBUl9BTkRfVVBEQVRFRF9ST0xFU19PTl9FQUNIX0xPR19JTl9PUFRJT04gfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgY2xhc3M9XCJjOHktcmFkaW8gaW5wdXQtc21cIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwicmFkaW9cIlxuICAgICAgICAgICAgICBuYW1lPVwiZHluYW1pY0FjY2Vzc01hcHBpbmdDb25maWd1cmF0aW9uXCJcbiAgICAgICAgICAgICAgZGF0YS1jeT1cImM4eS1pbnZlbnRvcnktcm9sZXMtbWFwcGluZy0tb3RoZXItb25lcy13aWxsLWJlLWNsZWFyZWRcIlxuICAgICAgICAgICAgICBbY2hlY2tlZF09XCIhbWFwUm9sZXNPbmx5Rm9yTmV3VXNlciAmJiAhbWFuYWdlUm9sZXNPbmx5RnJvbUFjY2Vzc01hcHBpbmdcIlxuICAgICAgICAgICAgICAoY2hhbmdlKT1cInNldER5bmFtaWNNYXBwaW5nQ29uZmlndXJhdGlvbihmYWxzZSwgZmFsc2UpXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8c3Bhbj48L3NwYW4+XG4gICAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgICAge3sgQ0xFQVJfQU5EX1VQREFURURfUk9MRVNfT05fRUFDSF9MT0dfSU5fT1BUSU9OIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIGNsYXNzPVwiYnRuLWhlbHBcIlxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInSGVscCcgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBwb3BvdmVyPVwie3sgQ0xFQVJfQU5EX1VQREFURURfUk9MRVNfT05fRUFDSF9MT0dfSU5fVE9PTFRJUCB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICAgIHBsYWNlbWVudD1cInJpZ2h0XCJcbiAgICAgICAgICAgICAgdHJpZ2dlcnM9XCJmb2N1c1wiXG4gICAgICAgICAgICAgIGNvbnRhaW5lcj1cImJvZHlcIlxuICAgICAgICAgICAgPjwvYnV0dG9uPlxuICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgIDwvYzh5LWZvcm0tZ3JvdXA+XG4gICAgICA8L2ZpZWxkc2V0PlxuICAgICAgPGZpZWxkc2V0IGNsYXNzPVwiYzh5LWZpZWxkc2V0IHAtMTZcIj5cbiAgICAgICAgPGxlZ2VuZD57eyAnRHluYW1pYyBhY2Nlc3MgbWFwcGluZycgfCB0cmFuc2xhdGUgfX08L2xlZ2VuZD5cbiAgICAgICAgPGM4eS11aS1lbXB0eS1zdGF0ZVxuICAgICAgICAgICpuZ0lmPVwidGVtcGxhdGVNb2RlbC5vbk5ld1VzZXIuZHluYW1pY01hcHBpbmcubWFwcGluZ3MubGVuZ3RoID09PSAwXCJcbiAgICAgICAgICBbaWNvbl09XCInbGlzdCdcIlxuICAgICAgICAgIFt0aXRsZV09XCInTm8gYWNjZXNzIG1hcHBpbmcgcnVsZXMgZGVmaW5lZC4nIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICBbc3VidGl0bGVdPVwiJ0NsaWNrIGJlbG93IHRvIGFkZCBhIG5ldyBtYXBwaW5nLicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgIFtob3Jpem9udGFsXT1cInRydWVcIlxuICAgICAgICA+PC9jOHktdWktZW1wdHktc3RhdGU+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICAqbmdGb3I9XCJcbiAgICAgICAgICAgIGxldCBhY2Nlc3NNYXBwaW5nIG9mIHRlbXBsYXRlTW9kZWwub25OZXdVc2VyLmR5bmFtaWNNYXBwaW5nLm1hcHBpbmdzO1xuICAgICAgICAgICAgaW5kZXggYXMgaWR4XG4gICAgICAgICAgXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxjOHktc3NvLWR5bmFtaWMtYWNjZXNzLW1hcHBpbmdcbiAgICAgICAgICAgIFthY2Nlc3NNYXBwaW5nXT1cImFjY2Vzc01hcHBpbmdcIlxuICAgICAgICAgICAgKG9uUmVtb3ZlQWNjZXNzTWFwcGluZyk9XCJvblJlbW92ZShhY2Nlc3NNYXBwaW5nKVwiXG4gICAgICAgICAgICBbYXBwc109XCJhcHBzXCJcbiAgICAgICAgICAgIFtncm91cHNdPVwiZ3JvdXBzXCJcbiAgICAgICAgICAgIFthY2Nlc3NNYXBwaW5nSW5kZXhdPVwiaWR4XCJcbiAgICAgICAgICA+PC9jOHktc3NvLWR5bmFtaWMtYWNjZXNzLW1hcHBpbmc+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwicC10LTE2XCI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgaWQ9XCJhZGQtYWNjZXNzLW1hcHBpbmctYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0XCJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgdGl0bGU9XCJ7eyAnQWRkIGFjY2VzcyBtYXBwaW5nJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiYWRkQWNjZXNzTWFwcGluZygpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8aVxuICAgICAgICAgICAgICBjOHlJY29uPVwicGx1cy1jaXJjbGVcIlxuICAgICAgICAgICAgICBjbGFzcz1cIm0tci00XCJcbiAgICAgICAgICAgID48L2k+XG4gICAgICAgICAgICB7eyAnQWRkIGFjY2VzcyBtYXBwaW5nJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZmllbGRzZXQ+XG4gICAgICA8ZmllbGRzZXQgY2xhc3M9XCJjOHktZmllbGRzZXQgcC0xNlwiPlxuICAgICAgICA8bGVnZW5kPlxuICAgICAgICAgIHt7ICdJbnZlbnRvcnkgcm9sZXMgbWFwcGluZycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgPC9sZWdlbmQ+XG4gICAgICAgIDxjOHktdWktZW1wdHktc3RhdGVcbiAgICAgICAgICAqbmdJZj1cInRlbXBsYXRlTW9kZWwub25OZXdVc2VyLmR5bmFtaWNNYXBwaW5nLmludmVudG9yeU1hcHBpbmdzLmxlbmd0aCA9PT0gMFwiXG4gICAgICAgICAgW2ljb25dPVwiJ2xpc3QnXCJcbiAgICAgICAgICBbdGl0bGVdPVwiJ05vIGludmVudG9yeSByb2xlcyBtYXBwaW5nIHJ1bGVzIGRlZmluZWQuJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgW3N1YnRpdGxlXT1cIidDbGljayBiZWxvdyB0byBhZGQgYSBuZXcgbWFwcGluZy4nIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICBbaG9yaXpvbnRhbF09XCJ0cnVlXCJcbiAgICAgICAgPjwvYzh5LXVpLWVtcHR5LXN0YXRlPlxuICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgKm5nRm9yPVwiXG4gICAgICAgICAgICBsZXQgaW52ZW50b3J5TWFwcGluZyBvZiB0ZW1wbGF0ZU1vZGVsLm9uTmV3VXNlci5keW5hbWljTWFwcGluZy5pbnZlbnRvcnlNYXBwaW5ncztcbiAgICAgICAgICAgIGluZGV4IGFzIGlkeFxuICAgICAgICAgIFwiXG4gICAgICAgID5cbiAgICAgICAgICA8Yzh5LXNzby1pbnZlbnRvcnktcm9sZXMtbWFwcGluZ1xuICAgICAgICAgICAgW2ludmVudG9yeVJvbGVzXT1cImludmVudG9yeVJvbGVzXCJcbiAgICAgICAgICAgIFtpbnZlbnRvcnlNYXBwaW5nXT1cImludmVudG9yeU1hcHBpbmdcIlxuICAgICAgICAgICAgKG9uUmVtb3ZlSW52ZW50b3J5TWFwcGluZyk9XCJvblJlbW92ZUludmVudG9yeU1hcHBpbmcoaW52ZW50b3J5TWFwcGluZylcIlxuICAgICAgICAgICAgW2ludmVudG9yeU1hcHBpbmdJbmRleF09XCJpZHhcIlxuICAgICAgICAgID48L2M4eS1zc28taW52ZW50b3J5LXJvbGVzLW1hcHBpbmc+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicC10LTE2XCI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgaWQ9XCJhZGQtaW52ZW50b3J5LW1hcHBpbmctYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0XCJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgdGl0bGU9XCJ7eyAnQWRkIGludmVudG9yeSByb2xlcyBtYXBwaW5nJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiYWRkSW52ZW50b3J5TWFwcGluZygpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8aVxuICAgICAgICAgICAgICBjOHlJY29uPVwicGx1cy1jaXJjbGVcIlxuICAgICAgICAgICAgICBjbGFzcz1cIm0tci00XCJcbiAgICAgICAgICAgID48L2k+XG4gICAgICAgICAgICB7eyAnQWRkIGludmVudG9yeSByb2xlcyBtYXBwaW5nJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZmllbGRzZXQ+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=