@firestitch/app-acl 13.0.0 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/app/components/acl-entries/acl-entries.component.d.ts +33 -33
  2. package/app/components/acl-entry/acl-entry.component.d.ts +31 -31
  3. package/app/components/acl-object-roles/acl-object-roles.component.d.ts +18 -18
  4. package/app/components/acl-permission-popover/acl-permission-popover.component.d.ts +12 -12
  5. package/app/components/acl-role/acl-role.component.d.ts +56 -56
  6. package/app/components/acl-role-popover/acl-role-popover.component.d.ts +13 -13
  7. package/app/components/acl-roles/acl-roles.component.d.ts +38 -38
  8. package/app/consts/acl-role-accesses.d.ts +5 -5
  9. package/app/enums/acl-role-access.d.ts +6 -6
  10. package/app/fs-app-acl.module.d.ts +33 -33
  11. package/app/injectors/app-acl-config.injector.d.ts +2 -2
  12. package/app/interfaces/acl-entry-data.d.ts +11 -11
  13. package/app/interfaces/acl-entry.d.ts +18 -18
  14. package/app/interfaces/acl-level.d.ts +3 -3
  15. package/app/interfaces/acl-object-entry.d.ts +11 -11
  16. package/app/interfaces/acl-object-role.d.ts +6 -6
  17. package/app/interfaces/acl-object.d.ts +4 -4
  18. package/app/interfaces/acl-permission.d.ts +7 -7
  19. package/app/interfaces/acl-role-config.d.ts +5 -5
  20. package/app/interfaces/acl-role.d.ts +16 -16
  21. package/app/interfaces/app-acl-config.d.ts +7 -7
  22. package/app/interfaces/index.d.ts +2 -2
  23. package/app/interfaces/name-value.d.ts +4 -4
  24. package/app/interfaces/role-config.d.ts +12 -12
  25. package/app/pipes/acl-role-permission-available.pipe.d.ts +7 -7
  26. package/app/pipes/bulk-options-filter.pipe.d.ts +13 -13
  27. package/app/pipes/index.d.ts +2 -2
  28. package/app/services/app-acl.service.d.ts +16 -16
  29. package/esm2020/app/components/acl-entries/acl-entries.component.mjs +173 -173
  30. package/esm2020/app/components/acl-entry/acl-entry.component.mjs +92 -92
  31. package/esm2020/app/components/acl-object-roles/acl-object-roles.component.mjs +52 -52
  32. package/esm2020/app/components/acl-permission-popover/acl-permission-popover.component.mjs +28 -28
  33. package/esm2020/app/components/acl-role/acl-role.component.mjs +253 -253
  34. package/esm2020/app/components/acl-role-popover/acl-role-popover.component.mjs +33 -33
  35. package/esm2020/app/components/acl-roles/acl-roles.component.mjs +169 -169
  36. package/esm2020/app/consts/acl-role-accesses.mjs +7 -7
  37. package/esm2020/app/enums/acl-role-access.mjs +7 -7
  38. package/esm2020/app/fs-app-acl.module.mjs +127 -129
  39. package/esm2020/app/injectors/app-acl-config.injector.mjs +2 -2
  40. package/esm2020/app/interfaces/acl-entry-data.mjs +1 -1
  41. package/esm2020/app/interfaces/acl-entry.mjs +1 -1
  42. package/esm2020/app/interfaces/acl-level.mjs +1 -1
  43. package/esm2020/app/interfaces/acl-object-entry.mjs +1 -1
  44. package/esm2020/app/interfaces/acl-object-role.mjs +1 -1
  45. package/esm2020/app/interfaces/acl-object.mjs +1 -1
  46. package/esm2020/app/interfaces/acl-permission.mjs +1 -1
  47. package/esm2020/app/interfaces/acl-role-config.mjs +1 -1
  48. package/esm2020/app/interfaces/acl-role.mjs +1 -1
  49. package/esm2020/app/interfaces/app-acl-config.mjs +1 -1
  50. package/esm2020/app/interfaces/index.mjs +2 -2
  51. package/esm2020/app/interfaces/name-value.mjs +1 -1
  52. package/esm2020/app/interfaces/role-config.mjs +1 -1
  53. package/esm2020/app/pipes/acl-role-permission-available.pipe.mjs +20 -20
  54. package/esm2020/app/pipes/bulk-options-filter.pipe.mjs +26 -26
  55. package/esm2020/app/pipes/index.mjs +2 -2
  56. package/esm2020/app/services/app-acl.service.mjs +50 -50
  57. package/esm2020/firestitch-app-acl.mjs +4 -4
  58. package/esm2020/public_api.mjs +10 -10
  59. package/fesm2015/firestitch-app-acl.mjs +887 -889
  60. package/fesm2015/firestitch-app-acl.mjs.map +1 -1
  61. package/fesm2020/firestitch-app-acl.mjs +900 -902
  62. package/fesm2020/firestitch-app-acl.mjs.map +1 -1
  63. package/{firestitch-app-acl.d.ts → index.d.ts} +5 -5
  64. package/package.json +3 -3
  65. package/public_api.d.ts +20 -20
@@ -1,7 +1,7 @@
1
- export interface AclPermission {
2
- value: string;
3
- name: string;
4
- levels: string[];
5
- accesses: number[];
6
- description: string;
7
- }
1
+ export interface AclPermission {
2
+ value: string;
3
+ name: string;
4
+ levels: string[];
5
+ accesses: number[];
6
+ description: string;
7
+ }
@@ -1,5 +1,5 @@
1
- export interface AclRoleConfig {
2
- id?: number;
3
- name?: any;
4
- value?: any;
5
- }
1
+ export interface AclRoleConfig {
2
+ id?: number;
3
+ name?: any;
4
+ value?: any;
5
+ }
@@ -1,16 +1,16 @@
1
- import { AclRoleConfig } from './acl-role-config';
2
- export interface AclRole {
3
- id?: number;
4
- name?: string;
5
- description?: string;
6
- state?: string;
7
- reference?: string;
8
- allPermissions?: boolean;
9
- role?: string;
10
- level?: string;
11
- permissions?: any;
12
- access?: string;
13
- protected?: boolean;
14
- aclPermissions?: any;
15
- aclRoleConfigs?: AclRoleConfig[];
16
- }
1
+ import { AclRoleConfig } from './acl-role-config';
2
+ export interface AclRole {
3
+ id?: number;
4
+ name?: string;
5
+ description?: string;
6
+ state?: string;
7
+ reference?: string;
8
+ allPermissions?: boolean;
9
+ role?: string;
10
+ level?: string;
11
+ permissions?: any;
12
+ access?: string;
13
+ protected?: boolean;
14
+ aclPermissions?: any;
15
+ aclRoleConfigs?: AclRoleConfig[];
16
+ }
@@ -1,7 +1,7 @@
1
- import { Observable } from 'rxjs';
2
- import { AclLevel } from './acl-level';
3
- export interface AppAclConfig {
4
- permissions: Observable<any[]>;
5
- levels: Observable<AclLevel[]>;
6
- case: 'snake' | 'camel';
7
- }
1
+ import { Observable } from 'rxjs';
2
+ import { AclLevel } from './acl-level';
3
+ export interface AppAclConfig {
4
+ permissions: Observable<any[]>;
5
+ levels: Observable<AclLevel[]>;
6
+ case: 'snake' | 'camel';
7
+ }
@@ -1,2 +1,2 @@
1
- export * from './app-acl-config';
2
- export * from './role-config';
1
+ export * from './app-acl-config';
2
+ export * from './role-config';
@@ -1,4 +1,4 @@
1
- export interface NameValue {
2
- name: string;
3
- value: any;
4
- }
1
+ export interface NameValue {
2
+ name: string;
3
+ value: any;
4
+ }
@@ -1,12 +1,12 @@
1
- export interface RoleConfig {
2
- name?: string;
3
- description?: string;
4
- type?: 'checkbox' | 'select';
5
- values?: {
6
- name: string;
7
- value: string;
8
- }[];
9
- required?: boolean;
10
- level?: string;
11
- label?: string;
12
- }
1
+ export interface RoleConfig {
2
+ name?: string;
3
+ description?: string;
4
+ type?: 'checkbox' | 'select';
5
+ values?: {
6
+ name: string;
7
+ value: string;
8
+ }[];
9
+ required?: boolean;
10
+ level?: string;
11
+ label?: string;
12
+ }
@@ -1,7 +1,7 @@
1
- import { PipeTransform } from '@angular/core';
2
- import * as i0 from "@angular/core";
3
- export declare class AclRolePermissionAvailablePipe implements PipeTransform {
4
- transform(permission: any, aclRolePermissions: any): boolean;
5
- static ɵfac: i0.ɵɵFactoryDeclaration<AclRolePermissionAvailablePipe, never>;
6
- static ɵpipe: i0.ɵɵPipeDeclaration<AclRolePermissionAvailablePipe, "aclRolePermissionAvailable">;
7
- }
1
+ import { PipeTransform } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export declare class AclRolePermissionAvailablePipe implements PipeTransform {
4
+ transform(permission: any, aclRolePermissions: any): boolean;
5
+ static ɵfac: i0.ɵɵFactoryDeclaration<AclRolePermissionAvailablePipe, never>;
6
+ static ɵpipe: i0.ɵɵPipeDeclaration<AclRolePermissionAvailablePipe, "aclRolePermissionAvailable", false>;
7
+ }
@@ -1,13 +1,13 @@
1
- import { PipeTransform } from '@angular/core';
2
- import { AclRoleAccess } from '../enums/acl-role-access';
3
- import { AclPermission } from '../interfaces/acl-permission';
4
- import * as i0 from "@angular/core";
5
- export declare class BulkOptionsFilterPipe implements PipeTransform {
6
- transform(rolesList: {
7
- name: string;
8
- value: AclRoleAccess;
9
- }[], children: AclPermission[]): any;
10
- private _uniqListOfAccessLevels;
11
- static ɵfac: i0.ɵɵFactoryDeclaration<BulkOptionsFilterPipe, never>;
12
- static ɵpipe: i0.ɵɵPipeDeclaration<BulkOptionsFilterPipe, "builkOptionsFilter">;
13
- }
1
+ import { PipeTransform } from '@angular/core';
2
+ import { AclRoleAccess } from '../enums/acl-role-access';
3
+ import { AclPermission } from '../interfaces/acl-permission';
4
+ import * as i0 from "@angular/core";
5
+ export declare class BulkOptionsFilterPipe implements PipeTransform {
6
+ transform(rolesList: {
7
+ name: string;
8
+ value: AclRoleAccess;
9
+ }[], children: AclPermission[]): any;
10
+ private _uniqListOfAccessLevels;
11
+ static ɵfac: i0.ɵɵFactoryDeclaration<BulkOptionsFilterPipe, never>;
12
+ static ɵpipe: i0.ɵɵPipeDeclaration<BulkOptionsFilterPipe, "builkOptionsFilter", false>;
13
+ }
@@ -1,2 +1,2 @@
1
- export * from './acl-role-permission-available.pipe';
2
- export * from './bulk-options-filter.pipe';
1
+ export * from './acl-role-permission-available.pipe';
2
+ export * from './bulk-options-filter.pipe';
@@ -1,16 +1,16 @@
1
- import { ReplaySubject } from 'rxjs';
2
- import { AppAclConfig } from './../interfaces/app-acl-config';
3
- import { AclPermission } from './../interfaces/acl-permission';
4
- import { AclLevel } from './../interfaces/acl-level';
5
- import * as i0 from "@angular/core";
6
- export declare class FsAppAclService {
7
- private _appAclConfig;
8
- private _permissions$;
9
- private _levels$;
10
- constructor(_appAclConfig: AppAclConfig);
11
- getPermissions(): ReplaySubject<AclPermission[]>;
12
- getLevels(): ReplaySubject<AclLevel[]>;
13
- getIndexedLevels(): import("rxjs").Observable<any>;
14
- static ɵfac: i0.ɵɵFactoryDeclaration<FsAppAclService, never>;
15
- static ɵprov: i0.ɵɵInjectableDeclaration<FsAppAclService>;
16
- }
1
+ import { ReplaySubject } from 'rxjs';
2
+ import { AppAclConfig } from './../interfaces/app-acl-config';
3
+ import { AclPermission } from './../interfaces/acl-permission';
4
+ import { AclLevel } from './../interfaces/acl-level';
5
+ import * as i0 from "@angular/core";
6
+ export declare class FsAppAclService {
7
+ private _appAclConfig;
8
+ private _permissions$;
9
+ private _levels$;
10
+ constructor(_appAclConfig: AppAclConfig);
11
+ getPermissions(): ReplaySubject<AclPermission[]>;
12
+ getLevels(): ReplaySubject<AclLevel[]>;
13
+ getIndexedLevels(): import("rxjs").Observable<any>;
14
+ static ɵfac: i0.ɵɵFactoryDeclaration<FsAppAclService, never>;
15
+ static ɵprov: i0.ɵɵInjectableDeclaration<FsAppAclService>;
16
+ }
@@ -1,176 +1,176 @@
1
- import { takeUntil } from 'rxjs/operators';
2
- import { Component, ViewChild, Input } from '@angular/core';
3
- import { MatDialog } from '@angular/material/dialog';
4
- import { Subject, Observable } from 'rxjs';
5
- import { sortBy, groupBy } from 'lodash-es';
6
- import { FsListComponent } from '@firestitch/list';
7
- import { FsPrompt } from '@firestitch/prompt';
8
- import { FsAppAclService } from '../../services/app-acl.service';
9
- import { FsAclEntryComponent } from '../acl-entry/acl-entry.component';
10
- import * as i0 from "@angular/core";
11
- import * as i1 from "../../services/app-acl.service";
12
- import * as i2 from "@angular/material/dialog";
13
- import * as i3 from "@firestitch/prompt";
14
- import * as i4 from "@firestitch/list";
15
- import * as i5 from "@firestitch/badge";
16
- import * as i6 from "../acl-role-popover/acl-role-popover.component";
17
- import * as i7 from "@angular/common";
18
- export class FsAclEntriesComponent {
19
- constructor(_appAclService, _dialog, _confirm) {
20
- this._appAclService = _appAclService;
21
- this._dialog = _dialog;
22
- this._confirm = _confirm;
23
- this.environmentShow = true;
24
- this.environmentLabel = 'Environment';
25
- this.environmentKey = 'environment';
26
- this.actions = [];
27
- this.aclEntriesList = null;
28
- this.aclEntriesConfig = null;
29
- this.permissions = [];
30
- this._destroy$ = new Subject();
31
- }
32
- ngOnInit() {
33
- this._appAclService.getPermissions()
34
- .subscribe(response => {
35
- this.permissions = response;
36
- });
37
- this.aclEntriesConfig = {
38
- status: false,
39
- paging: false,
40
- actions: this.actions,
41
- rowActions: [
42
- {
43
- label: 'Remove All Roles',
44
- click: (aclObjectEntry) => {
45
- this._confirm
46
- .confirm({
47
- title: 'Remove All Roles',
48
- commitLabel: 'Save',
1
+ import { takeUntil } from 'rxjs/operators';
2
+ import { Component, ViewChild, Input } from '@angular/core';
3
+ import { MatDialog } from '@angular/material/dialog';
4
+ import { Subject, Observable } from 'rxjs';
5
+ import { sortBy, groupBy } from 'lodash-es';
6
+ import { FsListComponent } from '@firestitch/list';
7
+ import { FsPrompt } from '@firestitch/prompt';
8
+ import { FsAppAclService } from '../../services/app-acl.service';
9
+ import { FsAclEntryComponent } from '../acl-entry/acl-entry.component';
10
+ import * as i0 from "@angular/core";
11
+ import * as i1 from "../../services/app-acl.service";
12
+ import * as i2 from "@angular/material/dialog";
13
+ import * as i3 from "@firestitch/prompt";
14
+ import * as i4 from "@angular/common";
15
+ import * as i5 from "@firestitch/list";
16
+ import * as i6 from "@firestitch/badge";
17
+ import * as i7 from "../acl-role-popover/acl-role-popover.component";
18
+ export class FsAclEntriesComponent {
19
+ constructor(_appAclService, _dialog, _confirm) {
20
+ this._appAclService = _appAclService;
21
+ this._dialog = _dialog;
22
+ this._confirm = _confirm;
23
+ this.environmentShow = true;
24
+ this.environmentLabel = 'Environment';
25
+ this.environmentKey = 'environment';
26
+ this.actions = [];
27
+ this.aclEntriesList = null;
28
+ this.aclEntriesConfig = null;
29
+ this.permissions = [];
30
+ this._destroy$ = new Subject();
31
+ }
32
+ ngOnInit() {
33
+ this._appAclService.getPermissions()
34
+ .subscribe(response => {
35
+ this.permissions = response;
36
+ });
37
+ this.aclEntriesConfig = {
38
+ status: false,
39
+ paging: false,
40
+ actions: this.actions,
41
+ rowActions: [
42
+ {
43
+ label: 'Remove All Roles',
44
+ click: (aclObjectEntry) => {
45
+ this._confirm
46
+ .confirm({
47
+ title: 'Remove All Roles',
48
+ commitLabel: 'Save',
49
49
  template: `Please note that removing roles may prevent users from being able to successfully login.<br>
50
50
  These changes are effective immediately.<br>
51
- Are you sure you would like to continue?`,
52
- }).subscribe(() => {
53
- const data = { ...aclObjectEntry, aclEntries: [] };
54
- this.saveAclObjectEntry(data)
55
- .subscribe(() => {
56
- this.aclEntriesList.reload();
57
- });
58
- });
59
- }
60
- }
61
- ],
62
- fetch: () => {
63
- return new Observable((observer) => {
64
- this.loadAclEntries({
65
- aclRoles: true,
66
- aclRolePermissions: true,
67
- objects: true,
68
- aclRoleState: 'active',
69
- })
70
- .subscribe((aclEntries) => {
71
- const objects = aclEntries
72
- .filter((aclEntry) => (!!aclEntry.object))
73
- .reduce((items, item) => {
74
- return {
75
- ...items,
76
- [item.object.id]: item.object,
77
- };
78
- }, {});
79
- const environments = aclEntries
80
- .filter((aclEntry) => (!!aclEntry[this.environmentKey]))
81
- .reduce((items, item) => {
82
- const environment = item[this.environmentKey];
83
- return {
84
- ...items,
85
- [environment.id]: environment,
86
- };
87
- }, {});
88
- const groupedAclEntries = groupBy(aclEntries, (item) => {
89
- const environmentId = (item[this.environmentKey])?.id;
90
- return [item.aclRole.level, environmentId, item.objectId];
91
- });
92
- let aclObjectEntries = Object.keys(groupedAclEntries)
93
- .reduce((accum, key) => {
94
- const parts = key.split(',');
95
- return [
96
- ...accum,
97
- {
98
- object: objects[parts[2]],
99
- level: parts[0],
100
- [`${this.environmentKey}Id`]: parts[1] ? parseInt(parts[1]) : null,
101
- [this.environmentKey]: environments[parts[1]],
102
- aclEntries: groupedAclEntries[key],
103
- }
104
- ];
105
- }, []);
106
- const hasApp = aclObjectEntries.some((item) => {
107
- return item.aclEntries.some((entry) => {
108
- return !entry.objectId;
109
- });
110
- });
111
- if (!hasApp) {
112
- aclObjectEntries.unshift({
113
- object: null,
114
- aclEntries: [],
115
- level: 'app',
116
- environmentId: null,
117
- });
118
- }
119
- aclObjectEntries = sortBy(aclObjectEntries, (item) => {
120
- return item.object ? item.level : '';
121
- });
122
- observer.next({ data: aclObjectEntries });
123
- observer.complete();
124
- });
125
- });
126
- },
127
- };
128
- }
129
- update(aclObjectEntry) {
130
- const data = {
131
- aclObjectEntry,
132
- required: false,
133
- loadAclRoles: this.loadAclRoles,
134
- saveAclObjectEntry: this.saveAclObjectEntry
135
- };
136
- this._dialog.open(FsAclEntryComponent, {
137
- data: data
138
- })
139
- .afterClosed()
140
- .pipe(takeUntil(this._destroy$))
141
- .subscribe(() => {
142
- this.aclEntriesList.reload();
143
- });
144
- }
145
- ngOnDestroy() {
146
- this._destroy$.next();
147
- this._destroy$.complete();
148
- }
149
- reload() {
150
- this.aclEntriesList.reload();
151
- }
152
- }
153
- FsAclEntriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FsAclEntriesComponent, deps: [{ token: i1.FsAppAclService }, { token: i2.MatDialog }, { token: i3.FsPrompt }], target: i0.ɵɵFactoryTarget.Component });
154
- FsAclEntriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: FsAclEntriesComponent, selector: "fs-acl-entries", inputs: { loadAclEntries: "loadAclEntries", loadAclRoles: "loadAclRoles", saveAclObjectEntry: "saveAclObjectEntry", environmentShow: "environmentShow", environmentLabel: "environmentLabel", environmentKey: "environmentKey", actions: "actions" }, viewQueries: [{ propertyName: "aclEntriesList", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "\n<fs-list [config]=\"aclEntriesConfig\">\n <fs-list-column>\n <ng-template fs-list-header>Context</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div\n *ngIf=\"row.object; else elseObject\"\n class=\"fs-row.gap-small\">\n <fs-badge *ngIf=\"row.object.imageUrl\" shape=\"circle\" image=\"{{ row.object.imageUrl }}\"></fs-badge>\n <span>\n <div><small>{{ row.object.className }}</small></div>\n <a (click)=\"update(row)\">{{ row.object.name }}</a>\n </span>\n </div>\n\n <ng-template #elseObject>\n <a (click)=\"update(row)\">App</a>\n </ng-template>\n </ng-template>\n </fs-list-column>\n\n <fs-list-column [show]=\"environmentShow\">\n <ng-template fs-list-header>{{environmentLabel}}</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{row.environment?.name}}\n </ng-template>\n </fs-list-column>\n\n <fs-list-column>\n <ng-template fs-list-header>Roles</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div class=\"fs-column\">\n <div div *ngFor=\"let aclEntry of row.aclEntries\">\n <ng-container [ngSwitch]=\"row.level\">\n <ng-container *ngSwitchCase=\"'app'\">\n <fs-acl-role-popover [aclRole]=\"aclEntry.aclRole\" objectName=\"App\">{{aclEntry.aclRole.name}}</fs-acl-role-popover>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container *ngIf=\"row.object\">\n <fs-acl-role-popover [aclRole]=\"aclEntry.aclRole\">{{aclEntry.aclRole.name}}</fs-acl-role-popover>\n </ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], components: [{ type: i4.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { type: i5.FsBadgeComponent, selector: "fs-badge", inputs: ["color", "text", "tooltip", "size", "shape", "image", "icon", "iconSize", "iconColor", "backgroundSize"] }, { type: i6.FsAclRolePopoverComponent, selector: "fs-acl-role-popover", inputs: ["aclRole", "objectName"] }], directives: [{ type: i4.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { type: i4.FsListHeaderDirective, selector: "[fs-list-header]", inputs: ["colspan", "align", "class"] }, { type: i4.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i7.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i7.NgSwitchDefault, selector: "[ngSwitchDefault]" }] });
155
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FsAclEntriesComponent, decorators: [{
156
- type: Component,
157
- args: [{ selector: 'fs-acl-entries', template: "\n<fs-list [config]=\"aclEntriesConfig\">\n <fs-list-column>\n <ng-template fs-list-header>Context</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div\n *ngIf=\"row.object; else elseObject\"\n class=\"fs-row.gap-small\">\n <fs-badge *ngIf=\"row.object.imageUrl\" shape=\"circle\" image=\"{{ row.object.imageUrl }}\"></fs-badge>\n <span>\n <div><small>{{ row.object.className }}</small></div>\n <a (click)=\"update(row)\">{{ row.object.name }}</a>\n </span>\n </div>\n\n <ng-template #elseObject>\n <a (click)=\"update(row)\">App</a>\n </ng-template>\n </ng-template>\n </fs-list-column>\n\n <fs-list-column [show]=\"environmentShow\">\n <ng-template fs-list-header>{{environmentLabel}}</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{row.environment?.name}}\n </ng-template>\n </fs-list-column>\n\n <fs-list-column>\n <ng-template fs-list-header>Roles</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div class=\"fs-column\">\n <div div *ngFor=\"let aclEntry of row.aclEntries\">\n <ng-container [ngSwitch]=\"row.level\">\n <ng-container *ngSwitchCase=\"'app'\">\n <fs-acl-role-popover [aclRole]=\"aclEntry.aclRole\" objectName=\"App\">{{aclEntry.aclRole.name}}</fs-acl-role-popover>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container *ngIf=\"row.object\">\n <fs-acl-role-popover [aclRole]=\"aclEntry.aclRole\">{{aclEntry.aclRole.name}}</fs-acl-role-popover>\n </ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""] }]
158
- }], ctorParameters: function () { return [{ type: i1.FsAppAclService }, { type: i2.MatDialog }, { type: i3.FsPrompt }]; }, propDecorators: { loadAclEntries: [{
159
- type: Input
160
- }], loadAclRoles: [{
161
- type: Input
162
- }], saveAclObjectEntry: [{
163
- type: Input
164
- }], environmentShow: [{
165
- type: Input
166
- }], environmentLabel: [{
167
- type: Input
168
- }], environmentKey: [{
169
- type: Input
170
- }], actions: [{
171
- type: Input
172
- }], aclEntriesList: [{
173
- type: ViewChild,
174
- args: [FsListComponent]
175
- }] } });
51
+ Are you sure you would like to continue?`,
52
+ }).subscribe(() => {
53
+ const data = { ...aclObjectEntry, aclEntries: [] };
54
+ this.saveAclObjectEntry(data)
55
+ .subscribe(() => {
56
+ this.aclEntriesList.reload();
57
+ });
58
+ });
59
+ }
60
+ }
61
+ ],
62
+ fetch: () => {
63
+ return new Observable((observer) => {
64
+ this.loadAclEntries({
65
+ aclRoles: true,
66
+ aclRolePermissions: true,
67
+ objects: true,
68
+ aclRoleState: 'active',
69
+ })
70
+ .subscribe((aclEntries) => {
71
+ const objects = aclEntries
72
+ .filter((aclEntry) => (!!aclEntry.object))
73
+ .reduce((items, item) => {
74
+ return {
75
+ ...items,
76
+ [item.object.id]: item.object,
77
+ };
78
+ }, {});
79
+ const environments = aclEntries
80
+ .filter((aclEntry) => (!!aclEntry[this.environmentKey]))
81
+ .reduce((items, item) => {
82
+ const environment = item[this.environmentKey];
83
+ return {
84
+ ...items,
85
+ [environment.id]: environment,
86
+ };
87
+ }, {});
88
+ const groupedAclEntries = groupBy(aclEntries, (item) => {
89
+ const environmentId = (item[this.environmentKey])?.id;
90
+ return [item.aclRole.level, environmentId, item.objectId];
91
+ });
92
+ let aclObjectEntries = Object.keys(groupedAclEntries)
93
+ .reduce((accum, key) => {
94
+ const parts = key.split(',');
95
+ return [
96
+ ...accum,
97
+ {
98
+ object: objects[parts[2]],
99
+ level: parts[0],
100
+ [`${this.environmentKey}Id`]: parts[1] ? parseInt(parts[1]) : null,
101
+ [this.environmentKey]: environments[parts[1]],
102
+ aclEntries: groupedAclEntries[key],
103
+ }
104
+ ];
105
+ }, []);
106
+ const hasApp = aclObjectEntries.some((item) => {
107
+ return item.aclEntries.some((entry) => {
108
+ return !entry.objectId;
109
+ });
110
+ });
111
+ if (!hasApp) {
112
+ aclObjectEntries.unshift({
113
+ object: null,
114
+ aclEntries: [],
115
+ level: 'app',
116
+ environmentId: null,
117
+ });
118
+ }
119
+ aclObjectEntries = sortBy(aclObjectEntries, (item) => {
120
+ return item.object ? item.level : '';
121
+ });
122
+ observer.next({ data: aclObjectEntries });
123
+ observer.complete();
124
+ });
125
+ });
126
+ },
127
+ };
128
+ }
129
+ update(aclObjectEntry) {
130
+ const data = {
131
+ aclObjectEntry,
132
+ required: false,
133
+ loadAclRoles: this.loadAclRoles,
134
+ saveAclObjectEntry: this.saveAclObjectEntry
135
+ };
136
+ this._dialog.open(FsAclEntryComponent, {
137
+ data: data
138
+ })
139
+ .afterClosed()
140
+ .pipe(takeUntil(this._destroy$))
141
+ .subscribe(() => {
142
+ this.aclEntriesList.reload();
143
+ });
144
+ }
145
+ ngOnDestroy() {
146
+ this._destroy$.next();
147
+ this._destroy$.complete();
148
+ }
149
+ reload() {
150
+ this.aclEntriesList.reload();
151
+ }
152
+ }
153
+ FsAclEntriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsAclEntriesComponent, deps: [{ token: i1.FsAppAclService }, { token: i2.MatDialog }, { token: i3.FsPrompt }], target: i0.ɵɵFactoryTarget.Component });
154
+ FsAclEntriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: FsAclEntriesComponent, selector: "fs-acl-entries", inputs: { loadAclEntries: "loadAclEntries", loadAclRoles: "loadAclRoles", saveAclObjectEntry: "saveAclObjectEntry", environmentShow: "environmentShow", environmentLabel: "environmentLabel", environmentKey: "environmentKey", actions: "actions" }, viewQueries: [{ propertyName: "aclEntriesList", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "\n<fs-list [config]=\"aclEntriesConfig\">\n <fs-list-column>\n <ng-template fs-list-header>Context</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div\n *ngIf=\"row.object; else elseObject\"\n class=\"fs-row.gap-small\">\n <fs-badge *ngIf=\"row.object.imageUrl\" shape=\"circle\" image=\"{{ row.object.imageUrl }}\"></fs-badge>\n <span>\n <div><small>{{ row.object.className }}</small></div>\n <a (click)=\"update(row)\">{{ row.object.name }}</a>\n </span>\n </div>\n\n <ng-template #elseObject>\n <a (click)=\"update(row)\">App</a>\n </ng-template>\n </ng-template>\n </fs-list-column>\n\n <fs-list-column [show]=\"environmentShow\">\n <ng-template fs-list-header>{{environmentLabel}}</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{row.environment?.name}}\n </ng-template>\n </fs-list-column>\n\n <fs-list-column>\n <ng-template fs-list-header>Roles</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div class=\"fs-column\">\n <div div *ngFor=\"let aclEntry of row.aclEntries\">\n <ng-container [ngSwitch]=\"row.level\">\n <ng-container *ngSwitchCase=\"'app'\">\n <fs-acl-role-popover [aclRole]=\"aclEntry.aclRole\" objectName=\"App\">{{aclEntry.aclRole.name}}</fs-acl-role-popover>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container *ngIf=\"row.object\">\n <fs-acl-role-popover [aclRole]=\"aclEntry.aclRole\">{{aclEntry.aclRole.name}}</fs-acl-role-popover>\n </ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: i5.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i5.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i5.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: i5.FsListHeaderDirective, selector: "[fs-list-header]", inputs: ["colspan", "align", "class"] }, { kind: "component", type: i6.FsBadgeComponent, selector: "fs-badge", inputs: ["color", "text", "tooltip", "size", "shape", "image", "icon", "iconSize", "iconColor", "backgroundSize"] }, { kind: "component", type: i7.FsAclRolePopoverComponent, selector: "fs-acl-role-popover", inputs: ["aclRole", "objectName"] }] });
155
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsAclEntriesComponent, decorators: [{
156
+ type: Component,
157
+ args: [{ selector: 'fs-acl-entries', template: "\n<fs-list [config]=\"aclEntriesConfig\">\n <fs-list-column>\n <ng-template fs-list-header>Context</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div\n *ngIf=\"row.object; else elseObject\"\n class=\"fs-row.gap-small\">\n <fs-badge *ngIf=\"row.object.imageUrl\" shape=\"circle\" image=\"{{ row.object.imageUrl }}\"></fs-badge>\n <span>\n <div><small>{{ row.object.className }}</small></div>\n <a (click)=\"update(row)\">{{ row.object.name }}</a>\n </span>\n </div>\n\n <ng-template #elseObject>\n <a (click)=\"update(row)\">App</a>\n </ng-template>\n </ng-template>\n </fs-list-column>\n\n <fs-list-column [show]=\"environmentShow\">\n <ng-template fs-list-header>{{environmentLabel}}</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{row.environment?.name}}\n </ng-template>\n </fs-list-column>\n\n <fs-list-column>\n <ng-template fs-list-header>Roles</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div class=\"fs-column\">\n <div div *ngFor=\"let aclEntry of row.aclEntries\">\n <ng-container [ngSwitch]=\"row.level\">\n <ng-container *ngSwitchCase=\"'app'\">\n <fs-acl-role-popover [aclRole]=\"aclEntry.aclRole\" objectName=\"App\">{{aclEntry.aclRole.name}}</fs-acl-role-popover>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container *ngIf=\"row.object\">\n <fs-acl-role-popover [aclRole]=\"aclEntry.aclRole\">{{aclEntry.aclRole.name}}</fs-acl-role-popover>\n </ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </fs-list-column>\n</fs-list>\n" }]
158
+ }], ctorParameters: function () { return [{ type: i1.FsAppAclService }, { type: i2.MatDialog }, { type: i3.FsPrompt }]; }, propDecorators: { loadAclEntries: [{
159
+ type: Input
160
+ }], loadAclRoles: [{
161
+ type: Input
162
+ }], saveAclObjectEntry: [{
163
+ type: Input
164
+ }], environmentShow: [{
165
+ type: Input
166
+ }], environmentLabel: [{
167
+ type: Input
168
+ }], environmentKey: [{
169
+ type: Input
170
+ }], actions: [{
171
+ type: Input
172
+ }], aclEntriesList: [{
173
+ type: ViewChild,
174
+ args: [FsListComponent]
175
+ }] } });
176
176
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNsLWVudHJpZXMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb21wb25lbnRzL2FjbC1lbnRyaWVzL2FjbC1lbnRyaWVzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29tcG9uZW50cy9hY2wtZW50cmllcy9hY2wtZW50cmllcy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFPLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFNBQVMsRUFBVSxTQUFTLEVBQWEsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9FLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUVyRCxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUUzQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUU1QyxPQUFPLEVBQWdCLGVBQWUsRUFBZ0IsTUFBTSxrQkFBa0IsQ0FBQztBQUMvRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFOUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBS2pFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDOzs7Ozs7Ozs7QUFRdkUsTUFBTSxPQUFPLHFCQUFxQjtJQWtCaEMsWUFDbUIsY0FBK0IsRUFDL0IsT0FBa0IsRUFDM0IsUUFBa0I7UUFGVCxtQkFBYyxHQUFkLGNBQWMsQ0FBaUI7UUFDL0IsWUFBTyxHQUFQLE9BQU8sQ0FBVztRQUMzQixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBaEJaLG9CQUFlLEdBQUcsSUFBSSxDQUFDO1FBQ3ZCLHFCQUFnQixHQUFHLGFBQWEsQ0FBQztRQUNqQyxtQkFBYyxHQUFHLGFBQWEs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QUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVNLFdBQVc7UUFDaEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFTSxNQUFNO1FBQ1gsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUMvQixDQUFDOztrSEE3SlUscUJBQXFCO3NHQUFyQixxQkFBcUIsNFZBVXJCLGVBQWUsZ0RDbEM1Qiw0d0RBZ0RBOzJGRHhCYSxxQkFBcUI7a0JBTGpDLFNBQVM7K0JBQ0UsZ0JBQWdCO3FKQU1WLGNBQWM7c0JBQTdCLEtBQUs7Z0JBQ1UsWUFBWTtzQkFBM0IsS0FBSztnQkFDVSxrQkFBa0I7c0JBQWpDLEtBQUs7Z0JBQ1UsZUFBZTtzQkFBOUIsS0FBSztnQkFDVSxnQkFBZ0I7c0JBQS9CLEtBQUs7Z0JBQ1UsY0FBYztzQkFBN0IsS0FBSztnQkFDVSxPQUFPO3NCQUF0QixLQUFLO2dCQUdDLGNBQWM7c0JBRHBCLFNBQVM7dUJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHRha2VVbnRpbCwgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIFZpZXdDaGlsZCwgT25EZXN0cm95LCBJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTWF0RGlhbG9nIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcblxuaW1wb3J0IHsgU3ViamVjdCwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBzb3J0QnksIGdyb3VwQnkgfSBmcm9tICdsb2Rhc2gtZXMnO1xuXG5pbXBvcnQgeyBGc0xpc3RBY3Rpb24sIEZzTGlzdENvbXBvbmVudCwgRnNMaXN0Q29uZmlnIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbGlzdCc7XG5pbXBvcnQgeyBGc1Byb21wdCB9IGZyb20gJ0BmaXJlc3RpdGNoL3Byb21wdCc7XG5cbmltcG9ydCB7IEZzQXBwQWNsU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FwcC1hY2wuc2VydmljZSc7XG5pbXBvcnQgeyBBY2xFbnRyeURhdGEgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL2FjbC1lbnRyeS1kYXRhJztcbmltcG9ydCB7IEFjbEVudHJ5IH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9hY2wtZW50cnknO1xuaW1wb3J0IHsgQWNsUm9sZSB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvYWNsLXJvbGUnO1xuaW1wb3J0IHsgQWNsT2JqZWN0RW50cnkgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL2FjbC1vYmplY3QtZW50cnknO1xuaW1wb3J0IHsgRnNBY2xFbnRyeUNvbXBvbmVudCB9IGZyb20gJy4uL2FjbC1lbnRyeS9hY2wtZW50cnkuY29tcG9uZW50JztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmcy1hY2wtZW50cmllcycsXG4gIHRlbXBsYXRlVXJsOiAnLi9hY2wtZW50cmllcy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2FjbC1lbnRyaWVzLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgRnNBY2xFbnRyaWVzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gIEBJbnB1dCgpIHB1YmxpYyBsb2FkQWNsRW50cmllczogKHF1ZXJ5OiBhbnkpID0+IE9ic2VydmFibGU8QWNsRW50cnlbXT47XG4gIEBJbnB1dCgpIHB1YmxpYyBsb2FkQWNsUm9sZXM6IChxdWVyeTogYW55KSA9PiBPYnNlcnZhYmxlPEFjbFJvbGVbXT47XG4gIEBJbnB1dCgpIHB1YmxpYyBzYXZlQWNsT2JqZWN0RW50cnk6IChhY2xPYmplY3RFbnRyeTogQWNsT2JqZWN0RW50cnkpID0+IE9ic2VydmFibGU8YW55PjtcbiAgQElucHV0KCkgcHVibGljIGVudmlyb25tZW50U2hvdyA9IHRydWU7XG4gIEBJbnB1dCgpIHB1YmxpYyBlbnZpcm9ubWVudExhYmVsID0gJ0Vudmlyb25tZW50JztcbiAgQElucHV0KCkgcHVibGljIGVudmlyb25tZW50S2V5ID0gJ2Vudmlyb25tZW50JztcbiAgQElucHV0KCkgcHVibGljIGFjdGlvbnM6IEZzTGlzdEFjdGlvbltdID0gW107XG5cbiAgQFZpZXdDaGlsZChGc0xpc3RDb21wb25lbnQpXG4gIHB1YmxpYyBhY2xFbnRyaWVzTGlzdDogRnNMaXN0Q29tcG9uZW50ID0gbnVsbDtcblxuICBwdWJsaWMgYWNsRW50cmllc0NvbmZpZzogRnNMaXN0Q29uZmlnID0gbnVsbDtcbiAgcHVibGljIHBlcm1pc3Npb25zOiBhbnlbXSA9IFtdO1xuXG4gIHByaXZhdGUgX2Rlc3Ryb3kkID0gbmV3IFN1YmplY3QoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9hcHBBY2xTZXJ2aWNlOiBGc0FwcEFjbFNlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZGlhbG9nOiBNYXREaWFsb2csXG4gICAgcHJpdmF0ZSBfY29uZmlybTogRnNQcm9tcHQsXG4gICkgeyB9XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuX2FwcEFjbFNlcnZpY2UuZ2V0UGVybWlzc2lvbnMoKVxuICAgICAgLnN1YnNjcmliZShyZXNwb25zZSA9PiB7XG4gICAgICAgIHRoaXMucGVybWlzc2lvbnMgPSByZXNwb25zZTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5hY2xFbnRyaWVzQ29uZmlnID0ge1xuICAgICAgc3RhdHVzOiBmYWxzZSxcbiAgICAgIHBhZ2luZzogZmFsc2UsXG4gICAgICBhY3Rpb25zOiB0aGlzLmFjdGlvbnMsXG4gICAgICByb3dBY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBsYWJlbDogJ1JlbW92ZSBBbGwgUm9sZXMnLFxuICAgICAgICAgIGNsaWNrOiAoYWNsT2JqZWN0RW50cnk6IEFjbE9iamVjdEVudHJ5KSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9jb25maXJtXG4gICAgICAgICAgICAgIC5jb25maXJtKHtcbiAgICAgICAgICAgICAgICB0aXRsZTogJ1JlbW92ZSBBbGwgUm9sZXMnLFxuICAgICAgICAgICAgICAgIGNvbW1pdExhYmVsOiAnU2F2ZScsXG4gICAgICAgICAgICAgICAgdGVtcGxhdGU6IGBQbGVhc2Ugbm90ZSB0aGF0IHJlbW92aW5nIHJvbGVzIG1heSBwcmV2ZW50IHVzZXJzIGZyb20gYmVpbmcgYWJsZSB0byBzdWNjZXNzZnVsbHkgbG9naW4uPGJyPlxuICAgICAgICAgICAgICAgICAgVGhlc2UgY2hhbmdlcyBhcmUgZWZmZWN0aXZlIGltbWVkaWF0ZWx5Ljxicj5cbiAgICAgICAgICAgICAgICAgIEFyZSB5b3Ugc3VyZSB5b3Ugd291bGQgbGlrZSB0byBjb250aW51ZT9gLFxuICAgICAgICAgICAgICB9KS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB7IC4uLmFjbE9iamVjdEVudHJ5LCBhY2xFbnRyaWVzOiBbXSB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2F2ZUFjbE9iamVjdEVudHJ5KGRhdGEpXG4gICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY2xFbnRyaWVzTGlzdC5yZWxvYWQoKTtcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIF0sXG4gICAgICBmZXRjaDogKCkgPT4ge1xuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb2FkQWNsRW50cmllcyh7XG4gICAgICAgICAgICBhY2xSb2xlczogdHJ1ZSxcbiAgICAgICAgICAgIGFjbFJvbGVQZXJtaXNzaW9uczogdHJ1ZSxcbiAgICAgICAgICAgIG9iamVjdHM6IHRydWUsXG4gICAgICAgICAgICBhY2xSb2xlU3RhdGU6ICdhY3RpdmUnLFxuICAgICAgICAgIH0pXG4gICAgICAgICAgICAuc3Vic2NyaWJlKChhY2xFbnRyaWVzOiBBY2xFbnRyeVtdKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IG9iamVjdHMgPSBhY2xFbnRyaWVzXG4gICAgICAgICAgICAgICAgLmZpbHRlcigoYWNsRW50cnkpID0+ICghIWFjbEVudHJ5Lm9iamVjdCkpXG4gICAgICAgICAgICAgICAgLnJlZHVjZSgoaXRlbXMsIGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIC4uLml0ZW1zLFxuICAgICAgICAgICAgICAgICAgICBbaXRlbS5vYmplY3QuaWRdOiBpdGVtLm9iamVjdCxcbiAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfSwge30pO1xuXG4gICAgICAgICAgICAgIGNvbnN0IGVudmlyb25tZW50cyA9IGFjbEVudHJpZXNcbiAgICAgICAgICAgICAgICAuZmlsdGVyKChhY2xFbnRyeSkgPT4gKCEhYWNsRW50cnlbdGhpcy5lbnZpcm9ubWVudEtleV0pKVxuICAgICAgICAgICAgICAgIC5yZWR1Y2UoKGl0ZW1zLCBpdGVtKSA9PiB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBlbnZpcm9ubWVudCA9IGl0ZW1bdGhpcy5lbnZpcm9ubWVudEtleV07XG4gICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAuLi5pdGVtcyxcbiAgICAgICAgICAgICAgICAgICAgW2Vudmlyb25tZW50LmlkXTogZW52aXJvbm1lbnQsXG4gICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0sIHt9KTtcblxuICAgICAgICAgICAgICBjb25zdCBncm91cGVkQWNsRW50cmllcyA9IGdyb3VwQnkoYWNsRW50cmllcywgKGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBlbnZpcm9ubWVudElkID0gKGl0ZW1bdGhpcy5lbnZpcm9ubWVudEtleV0pPy5pZDtcbiAgICAgICAgICAgICAgICByZXR1cm4gW2l0ZW0uYWNsUm9sZS5sZXZlbCwgZW52aXJvbm1lbnRJZCwgaXRlbS5vYmplY3RJZF07XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIGxldCBhY2xPYmplY3RFbnRyaWVzOiBBY2xPYmplY3RFbnRyeVtdID0gT2JqZWN0LmtleXMoZ3JvdXBlZEFjbEVudHJpZXMpXG4gICAgICAgICAgICAgICAgLnJlZHVjZSgoYWNjdW0sIGtleTogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBwYXJ0cyA9IGtleS5zcGxpdCgnLCcpO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAgLi4uYWNjdW0sXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICBvYmplY3Q6IG9iamVjdHNbcGFydHNbMl1dLFxuICAgICAgICAgICAgICAgICAgICAgIGxldmVsOiBwYXJ0c1swXSxcbiAgICAgICAgICAgICAgICAgICAgICBbYCR7dGhpcy5lbnZpcm9ubWVudEtleX1JZGBdOiBwYXJ0c1sxXSA/IHBhcnNlSW50KHBhcnRzWzFdKSA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgW3RoaXMuZW52aXJvbm1lbnRLZXldOiBlbnZpcm9ubWVudHNbcGFydHNbMV1dLFxuICAgICAgICAgICAgICAgICAgICAgIGFjbEVudHJpZXM6IGdyb3VwZWRBY2xFbnRyaWVzW2tleV0sXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgfSwgW10pO1xuXG4gICAgICAgICAgICAgIGNvbnN0IGhhc0FwcCA9IGFjbE9iamVjdEVudHJpZXMuc29tZSgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBpdGVtLmFjbEVudHJpZXMuc29tZSgoZW50cnkpID0+IHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiAhZW50cnkub2JqZWN0SWQ7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIGlmICghaGFzQXBwKSB7XG4gICAgICAgICAgICAgICAgYWNsT2JqZWN0RW50cmllcy51bnNoaWZ0KHtcbiAgICAgICAgICAgICAgICAgIG9iamVjdDogbnVsbCxcbiAgICAgICAgICAgICAgICAgIGFjbEVudHJpZXM6IFtdLFxuICAgICAgICAgICAgICAgICAgbGV2ZWw6ICdhcHAnLFxuICAgICAgICAgICAgICAgICAgZW52aXJvbm1lbnRJZDogbnVsbCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGFjbE9iamVjdEVudHJpZXMgPSBzb3J0QnkoYWNsT2JqZWN0RW50cmllcywgKGl0ZW06IEFjbE9iamVjdEVudHJ5KSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0ub2JqZWN0ID8gaXRlbS5sZXZlbCA6ICcnO1xuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHsgZGF0YTogYWNsT2JqZWN0RW50cmllcyB9KTtcbiAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyB1cGRhdGUoYWNsT2JqZWN0RW50cnk6IEFjbE9iamVjdEVudHJ5KSB7XG4gICAgY29uc3QgZGF0YTogQWNsRW50cnlEYXRhID0ge1xuICAgICAgYWNsT2JqZWN0RW50cnksXG4gICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICBsb2FkQWNsUm9sZXM6IHRoaXMubG9hZEFjbFJvbGVzLFxuICAgICAgc2F2ZUFjbE9iamVjdEVudHJ5OiB0aGlzLnNhdmVBY2xPYmplY3RFbnRyeVxuICAgIH1cblxuICAgIHRoaXMuX2RpYWxvZy5vcGVuKEZzQWNsRW50cnlDb21wb25lbnQsIHtcbiAgICAgIGRhdGE6IGRhdGFcbiAgICB9KVxuICAgICAgLmFmdGVyQ2xvc2VkKClcbiAgICAgIC5waXBlKFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuYWNsRW50cmllc0xpc3QucmVsb2FkKCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLl9kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5fZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIHB1YmxpYyByZWxvYWQoKTogdm9pZCB7XG4gICAgdGhpcy5hY2xFbnRyaWVzTGlzdC5yZWxvYWQoKTtcbiAgfVxuXG59XG4iLCJcbjxmcy1saXN0IFtjb25maWddPVwiYWNsRW50cmllc0NvbmZpZ1wiPlxuICA8ZnMtbGlzdC1jb2x1bW4+XG4gICAgPG5nLXRlbXBsYXRlIGZzLWxpc3QtaGVhZGVyPkNvbnRleHQ8L25nLXRlbXBsYXRlPlxuICAgIDxuZy10ZW1wbGF0ZSBmcy1saXN0LWNlbGwgbGV0LXJvdz1cInJvd1wiPlxuICAgICAgPGRpdlxuICAgICAgICAgICpuZ0lmPVwicm93Lm9iamVjdDsgZWxzZSBlbHNlT2JqZWN0XCJcbiAgICAgICAgICBjbGFzcz1cImZzLXJvdy5nYXAtc21hbGxcIj5cbiAgICAgICAgPGZzLWJhZGdlICpuZ0lmPVwicm93Lm9iamVjdC5pbWFnZVVybFwiIHNoYXBlPVwiY2lyY2xlXCIgaW1hZ2U9XCJ7eyByb3cub2JqZWN0LmltYWdlVXJsIH19XCI+PC9mcy1iYWRnZT5cbiAgICAgICAgPHNwYW4+XG4gICAgICAgICAgPGRpdj48c21hbGw+e3sgcm93Lm9iamVjdC5jbGFzc05hbWUgfX08L3NtYWxsPjwvZGl2PlxuICAgICAgICAgIDxhIChjbGljayk9XCJ1cGRhdGUocm93KVwiPnt7IHJvdy5vYmplY3QubmFtZSB9fTwvYT5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjZWxzZU9iamVjdD5cbiAgICAgICAgPGEgKGNsaWNrKT1cInVwZGF0ZShyb3cpXCI+QXBwPC9hPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L25nLXRlbXBsYXRlPlxuICA8L2ZzLWxpc3QtY29sdW1uPlxuXG4gIDxmcy1saXN0LWNvbHVtbiBbc2hvd109XCJlbnZpcm9ubWVudFNob3dcIj5cbiAgICA8bmctdGVtcGxhdGUgZnMtbGlzdC1oZWFkZXI+e3tlbnZpcm9ubWVudExhYmVsfX08L25nLXRlbXBsYXRlPlxuICAgIDxuZy10ZW1wbGF0ZSBmcy1saXN0LWNlbGwgbGV0LXJvdz1cInJvd1wiPlxuICAgICAge3tyb3cuZW52aXJvbm1lbnQ/Lm5hbWV9fVxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvZnMtbGlzdC1jb2x1bW4+XG5cbiAgPGZzLWxpc3QtY29sdW1uPlxuICAgIDxuZy10ZW1wbGF0ZSBmcy1saXN0LWhlYWRlcj5Sb2xlczwvbmctdGVtcGxhdGU+XG4gICAgPG5nLXRlbXBsYXRlIGZzLWxpc3QtY2VsbCBsZXQtcm93PVwicm93XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZnMtY29sdW1uXCI+XG4gICAgICAgIDxkaXYgZGl2ICpuZ0Zvcj1cImxldCBhY2xFbnRyeSBvZiByb3cuYWNsRW50cmllc1wiPlxuICAgICAgICAgIDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cInJvdy5sZXZlbFwiPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ2FwcCdcIj5cbiAgICAgICAgICAgICAgPGZzLWFjbC1yb2xlLXBvcG92ZXIgW2FjbFJvbGVdPVwiYWNsRW50cnkuYWNsUm9sZVwiIG9iamVjdE5hbWU9XCJBcHBcIj57e2FjbEVudHJ5LmFjbFJvbGUubmFtZX19PC9mcy1hY2wtcm9sZS1wb3BvdmVyPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaERlZmF1bHQ+XG4gICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJyb3cub2JqZWN0XCI+XG4gICAgICAgICAgICAgICAgPGZzLWFjbC1yb2xlLXBvcG92ZXIgW2FjbFJvbGVdPVwiYWNsRW50cnkuYWNsUm9sZVwiPnt7YWNsRW50cnkuYWNsUm9sZS5uYW1lfX08L2ZzLWFjbC1yb2xlLXBvcG92ZXI+XG4gICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9mcy1saXN0LWNvbHVtbj5cbjwvZnMtbGlzdD5cbiJdfQ==