@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.
- package/app/components/acl-entries/acl-entries.component.d.ts +33 -33
- package/app/components/acl-entry/acl-entry.component.d.ts +31 -31
- package/app/components/acl-object-roles/acl-object-roles.component.d.ts +18 -18
- package/app/components/acl-permission-popover/acl-permission-popover.component.d.ts +12 -12
- package/app/components/acl-role/acl-role.component.d.ts +56 -56
- package/app/components/acl-role-popover/acl-role-popover.component.d.ts +13 -13
- package/app/components/acl-roles/acl-roles.component.d.ts +38 -38
- package/app/consts/acl-role-accesses.d.ts +5 -5
- package/app/enums/acl-role-access.d.ts +6 -6
- package/app/fs-app-acl.module.d.ts +33 -33
- package/app/injectors/app-acl-config.injector.d.ts +2 -2
- package/app/interfaces/acl-entry-data.d.ts +11 -11
- package/app/interfaces/acl-entry.d.ts +18 -18
- package/app/interfaces/acl-level.d.ts +3 -3
- package/app/interfaces/acl-object-entry.d.ts +11 -11
- package/app/interfaces/acl-object-role.d.ts +6 -6
- package/app/interfaces/acl-object.d.ts +4 -4
- package/app/interfaces/acl-permission.d.ts +7 -7
- package/app/interfaces/acl-role-config.d.ts +5 -5
- package/app/interfaces/acl-role.d.ts +16 -16
- package/app/interfaces/app-acl-config.d.ts +7 -7
- package/app/interfaces/index.d.ts +2 -2
- package/app/interfaces/name-value.d.ts +4 -4
- package/app/interfaces/role-config.d.ts +12 -12
- package/app/pipes/acl-role-permission-available.pipe.d.ts +7 -7
- package/app/pipes/bulk-options-filter.pipe.d.ts +13 -13
- package/app/pipes/index.d.ts +2 -2
- package/app/services/app-acl.service.d.ts +16 -16
- package/esm2020/app/components/acl-entries/acl-entries.component.mjs +173 -173
- package/esm2020/app/components/acl-entry/acl-entry.component.mjs +92 -92
- package/esm2020/app/components/acl-object-roles/acl-object-roles.component.mjs +52 -52
- package/esm2020/app/components/acl-permission-popover/acl-permission-popover.component.mjs +28 -28
- package/esm2020/app/components/acl-role/acl-role.component.mjs +253 -253
- package/esm2020/app/components/acl-role-popover/acl-role-popover.component.mjs +33 -33
- package/esm2020/app/components/acl-roles/acl-roles.component.mjs +169 -169
- package/esm2020/app/consts/acl-role-accesses.mjs +7 -7
- package/esm2020/app/enums/acl-role-access.mjs +7 -7
- package/esm2020/app/fs-app-acl.module.mjs +127 -129
- package/esm2020/app/injectors/app-acl-config.injector.mjs +2 -2
- package/esm2020/app/interfaces/acl-entry-data.mjs +1 -1
- package/esm2020/app/interfaces/acl-entry.mjs +1 -1
- package/esm2020/app/interfaces/acl-level.mjs +1 -1
- package/esm2020/app/interfaces/acl-object-entry.mjs +1 -1
- package/esm2020/app/interfaces/acl-object-role.mjs +1 -1
- package/esm2020/app/interfaces/acl-object.mjs +1 -1
- package/esm2020/app/interfaces/acl-permission.mjs +1 -1
- package/esm2020/app/interfaces/acl-role-config.mjs +1 -1
- package/esm2020/app/interfaces/acl-role.mjs +1 -1
- package/esm2020/app/interfaces/app-acl-config.mjs +1 -1
- package/esm2020/app/interfaces/index.mjs +2 -2
- package/esm2020/app/interfaces/name-value.mjs +1 -1
- package/esm2020/app/interfaces/role-config.mjs +1 -1
- package/esm2020/app/pipes/acl-role-permission-available.pipe.mjs +20 -20
- package/esm2020/app/pipes/bulk-options-filter.pipe.mjs +26 -26
- package/esm2020/app/pipes/index.mjs +2 -2
- package/esm2020/app/services/app-acl.service.mjs +50 -50
- package/esm2020/firestitch-app-acl.mjs +4 -4
- package/esm2020/public_api.mjs +10 -10
- package/fesm2015/firestitch-app-acl.mjs +887 -889
- package/fesm2015/firestitch-app-acl.mjs.map +1 -1
- package/fesm2020/firestitch-app-acl.mjs +900 -902
- package/fesm2020/firestitch-app-acl.mjs.map +1 -1
- package/{firestitch-app-acl.d.ts → index.d.ts} +5 -5
- package/package.json +3 -3
- 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
|
+
}
|
package/app/pipes/index.d.ts
CHANGED
|
@@ -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 "@
|
|
15
|
-
import * as i5 from "@firestitch/
|
|
16
|
-
import * as i6 from "
|
|
17
|
-
import * as i7 from "
|
|
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: "
|
|
154
|
-
FsAclEntriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
155
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
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
|
-
}] } });
|
|
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==
|