Skip to content

Commit be16bd1

Browse files
permissions revamp (#647)
- added support for granular permissions - Administration sections are only visible if the User has the appropriate Permissions
1 parent 26586c7 commit be16bd1

File tree

104 files changed

+4475
-1556
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+4475
-1556
lines changed

src/app/app.module.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ import { AppAdminSubscriptionSearchComponent } from './components/admin-app/app-
103103
import { EditSubscriptionComponent } from './components/admin-app/app-admin-subscription-search/edit-subscription/edit-subscription.component';
104104
import { CreateApplicationDialogComponent } from './components/shared/create-application-dialog/create-application-dialog.component';
105105
import { ResizableModule } from 'angular-resizable-element';
106+
import { SystemRolesComponent } from './components/admin-app/admin-roles/roles/roles.component';
107+
import { AdminRolesComponent } from './components/admin-app/admin-roles/admin-roles.component';
108+
import { NameDialogComponent } from './components/shared/name-dialog/name-dialog.component';
109+
import { TeamRolesComponent } from './components/admin-app/admin-roles/team-roles/team-roles.component';
106110

107111
@NgModule({
108112
exports: [
@@ -190,6 +194,10 @@ export const myCustomTooltipDefaults: MatTooltipDefaultOptions = {
190194
AppAdminSubscriptionSearchComponent,
191195
EditSubscriptionComponent,
192196
CreateApplicationDialogComponent,
197+
NameDialogComponent,
198+
SystemRolesComponent,
199+
AdminRolesComponent,
200+
TeamRolesComponent,
193201
],
194202
imports: [
195203
BrowserModule,

src/app/components/admin-app/admin-app.component.html

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
class="appbarmenu-container"
99
#sidenav
1010
mode="side"
11-
[opened]="loggedInUserService.isSuperUser$ | async"
11+
[opened]="true"
1212
>
1313
<mat-list class="appitems-container">
1414
<mat-list-item class="appslist">
@@ -23,28 +23,34 @@ <h2 class="icon-text">Administration</h2>
2323
</a>
2424
<mat-divider></mat-divider>
2525
</mat-list-item>
26-
<mat-list-item *ngFor="let sectionItem of sectionItems">
27-
<button
28-
mat-button
29-
(click)="sectionChangedFn(sectionItem.section)"
30-
class="px-0 w-100"
31-
>
32-
<div class="d-flex align-items-center">
33-
<mat-icon
34-
*ngIf="sectionItem.svgIcon"
35-
class="lefticon player-icon-small"
36-
svgIcon="{{ sectionItem.icon }}"
37-
></mat-icon>
38-
<img
39-
*ngIf="!sectionItem.svgIcon"
40-
class="lefticon"
41-
src="{{ sectionItem.icon }}"
42-
alt="{{ sectionItem.name }}"
43-
/>
44-
<div>{{ sectionItem.name }}</div>
45-
</div>
46-
</button>
47-
</mat-list-item>
26+
<ng-container *ngFor="let sectionItem of sectionItems">
27+
<ng-container *ngIf="permissions$ | async as permissions">
28+
<mat-list-item *ngIf="permissions.includes(sectionItem.permission)">
29+
<ng-container>
30+
<button
31+
mat-button
32+
(click)="sectionChangedFn(sectionItem.section)"
33+
class="px-0 w-100"
34+
>
35+
<div class="d-flex align-items-center">
36+
<mat-icon
37+
*ngIf="sectionItem.svgIcon"
38+
class="lefticon player-icon-small"
39+
svgIcon="{{ sectionItem.icon }}"
40+
></mat-icon>
41+
<img
42+
*ngIf="!sectionItem.svgIcon"
43+
class="lefticon"
44+
src="{{ sectionItem.icon }}"
45+
alt="{{ sectionItem.name }}"
46+
/>
47+
<div>{{ sectionItem.name }}</div>
48+
</div>
49+
</button>
50+
</ng-container>
51+
</mat-list-item>
52+
</ng-container>
53+
</ng-container>
4854
</mat-list>
4955
<img
5056
class="crucible-logo"
@@ -78,9 +84,10 @@ <h2 class="icon-text">Administration</h2>
7884
*ngSwitchCase="Section.ADMIN_APP_TEMP"
7985
></app-admin-app-template-search>
8086

81-
<app-admin-role-permission-search
87+
<app-admin-roles
88+
class="w-100"
8289
*ngSwitchCase="Section.ADMIN_ROLE_PERM"
83-
></app-admin-role-permission-search>
90+
></app-admin-roles>
8491

8592
<app-admin-subscription-search
8693
*ngSwitchCase="Section.ADMIN_SUBS"

src/app/components/admin-app/admin-app.component.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import {
1010
ComnAuthQuery,
1111
} from '@cmusei/crucible-common';
1212
import { RouterQuery } from '@datorama/akita-ng-router-store';
13-
import { Observable, Subject } from 'rxjs';
14-
import { takeUntil } from 'rxjs/operators';
13+
import { combineLatest, Observable, Subject } from 'rxjs';
14+
import { map, takeUntil } from 'rxjs/operators';
1515
import { TopbarView } from '../shared/top-bar/topbar.models';
1616
import { LoggedInUserService } from '../../services/logged-in-user/logged-in-user.service';
17+
import { UserPermissionsService } from '../../services/permissions/user-permissions.service';
18+
import { SystemPermission } from '../../generated/player-api';
1719

1820
@Component({
1921
selector: 'app-admin-app',
@@ -25,55 +27,77 @@ export class AdminAppComponent implements OnInit, OnDestroy {
2527
public topbarColor = '#4c7aa2';
2628
public topbarTextColor = '#FFFFFF';
2729
public TopbarView = TopbarView;
28-
public queryParams: any = {
29-
section: Section.ADMIN_VIEWS,
30-
};
30+
public queryParams: any;
3131
Section = Section;
3232
unsubscribe$: Subject<null> = new Subject<null>();
3333
theme$: Observable<Theme>;
34-
public section$: Observable<Section> =
35-
this.routerQuery.selectQueryParams('section');
3634
public title = '';
35+
public permissions$ = this.permissionsService.permissions$;
3736

3837
public sectionItems: Array<SectionItem> = [
3938
{
4039
name: 'Views',
4140
section: Section.ADMIN_VIEWS,
4241
icon: 'ic_crucible_player',
4342
svgIcon: true,
43+
permission: SystemPermission.ViewViews,
4444
},
4545
{
4646
name: 'Users',
4747
section: Section.ADMIN_USERS,
4848
icon: 'assets/img/SP_Icon_User.png',
4949
svgIcon: false,
50+
permission: SystemPermission.ViewUsers,
5051
},
5152
{
5253
name: 'Application Templates',
5354
section: Section.ADMIN_APP_TEMP,
5455
icon: 'assets/img/SP_Icon_Intel.png',
5556
svgIcon: false,
57+
permission: SystemPermission.ViewApplications,
5658
},
5759
{
58-
name: 'Roles / Permissions',
60+
name: 'Roles',
5961
section: Section.ADMIN_ROLE_PERM,
6062
icon: 'assets/img/SP_Icon_Alert.png',
6163
svgIcon: false,
64+
permission: SystemPermission.ViewRoles,
6265
},
6366
{
6467
name: 'Subscriptions',
6568
section: Section.ADMIN_SUBS,
6669
icon: 'assets/img/subscription.png',
6770
svgIcon: false,
71+
permission: SystemPermission.ViewWebhookSubscriptions,
6872
},
6973
];
7074

75+
public section$: Observable<Section> = combineLatest([
76+
this.routerQuery.selectQueryParams('section'),
77+
this.permissions$,
78+
]).pipe(
79+
map(([queryParam, permissions]) => {
80+
if (
81+
queryParam &&
82+
Object.values(Section).includes(queryParam as Section)
83+
) {
84+
return queryParam as Section;
85+
} else {
86+
const sectionItem = this.sectionItems.find((x) =>
87+
permissions.includes(x.permission)
88+
);
89+
return sectionItem?.section;
90+
}
91+
})
92+
);
93+
7194
constructor(
7295
private settingsService: ComnSettingsService,
7396
private router: Router,
7497
private routerQuery: RouterQuery,
7598
private authQuery: ComnAuthQuery,
76-
public loggedInUserService: LoggedInUserService
99+
public loggedInUserService: LoggedInUserService,
100+
public permissionsService: UserPermissionsService
77101
) {
78102
this.theme$ = this.authQuery.userTheme$;
79103
}
@@ -91,7 +115,7 @@ export class AdminAppComponent implements OnInit, OnDestroy {
91115
if (sectionEnum != null) {
92116
this.sectionChangedFn(sectionEnum);
93117
} else {
94-
this.sectionChangedFn(Section.ADMIN_VIEWS);
118+
//this.sectionChangedFn(Section.ADMIN_VIEWS);
95119
}
96120
});
97121

@@ -148,4 +172,5 @@ export interface SectionItem {
148172
icon: string;
149173
section: Section;
150174
svgIcon: boolean;
175+
permission: SystemPermission;
151176
}

src/app/components/admin-app/admin-role-permission-search/admin-role-permission-search.component.ts

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { Component, OnInit, ViewChild } from '@angular/core';
55
import { MatSort, MatSortable } from '@angular/material/sort';
66
import { MatLegacyTableDataSource as MatTableDataSource } from '@angular/material/legacy-table';
77
import {
8+
CreatePermissionCommand,
89
Permission,
910
PermissionService,
10-
PermissionForm,
1111
} from '../../../generated/player-api';
12-
import { Role, RoleService, RoleForm } from '../../../generated/player-api';
12+
import { Role, RoleService } from '../../../generated/player-api';
1313
import { DialogService } from '../../../services/dialog/dialog.service';
1414
import { UntypedFormControl } from '@angular/forms';
1515

@@ -61,9 +61,10 @@ export class AdminRolePermissionSearchComponent implements OnInit {
6161
);
6262
this.filterPermissionString = '';
6363
this.permissionService.getPermissions().subscribe((permissions) => {
64-
this.permissionDataSource.data = permissions.sort((k1, k2) =>
65-
k1.key.toLowerCase() < k2.key.toLowerCase() ? -1 : 1
66-
);
64+
this.permissionDataSource.data = permissions;
65+
// permissions.sort((k1, k2) =>
66+
// k1.key.toLowerCase() < k2.key.toLowerCase() ? -1 : 1
67+
// );
6768
});
6869

6970
this.roleDataSource = new MatTableDataSource<Role>(new Array<Role>());
@@ -83,9 +84,9 @@ export class AdminRolePermissionSearchComponent implements OnInit {
8384
if (!permission.key) {
8485
return;
8586
}
86-
const newPermission: PermissionForm = {
87-
key: permission.key,
88-
value: permission.value,
87+
const newPermission: CreatePermissionCommand = {
88+
name: permission.key,
89+
// value: permission.value,
8990
description: permission.description,
9091
};
9192
this.permissionService.createPermission(newPermission).subscribe(() => {
@@ -101,16 +102,15 @@ export class AdminRolePermissionSearchComponent implements OnInit {
101102
.createPermission('Edit Permission', permission)
102103
.subscribe((enteredInfo) => {
103104
permission = enteredInfo['permission'];
104-
if (!permission.key) {
105+
if (!permission.name) {
105106
return;
106107
}
107-
const newPermission: PermissionForm = {
108-
key: permission.key,
109-
value: permission.value,
110-
description: permission.description,
111-
};
112108
this.permissionService
113-
.updatePermission(permission.id, newPermission)
109+
.updatePermission(permission.id, {
110+
name: permission.name,
111+
// value: permission.value,
112+
description: permission.description,
113+
})
114114
.subscribe(() => {
115115
this.permissionService.getPermissions().subscribe((permissions) => {
116116
this.permissionDataSource.data = permissions;
@@ -126,14 +126,10 @@ export class AdminRolePermissionSearchComponent implements OnInit {
126126
break;
127127
}
128128
case 'delete': {
129-
// Delete permission
130-
const permissionName = !permission.value
131-
? permission.key
132-
: permission.key + '(' + permission.value + ')';
133129
this.dialogService
134130
.confirm(
135131
'Delete Permission',
136-
'Are you sure you want to delete ' + permissionName + '?'
132+
'Are you sure you want to delete ' + permission.name + '?'
137133
)
138134
.subscribe((confirmed) => {
139135
if (confirmed) {
@@ -181,14 +177,16 @@ export class AdminRolePermissionSearchComponent implements OnInit {
181177
if (!enteredInfo['name']) {
182178
return;
183179
}
184-
const newRole: RoleForm = {
185-
name: enteredInfo['name'],
186-
};
187-
this.roleService.createRole(newRole).subscribe(() => {
188-
this.roleService.getRoles().subscribe((roles) => {
189-
this.roleDataSource.data = roles;
180+
181+
this.roleService
182+
.createRole({
183+
name: enteredInfo['name'],
184+
})
185+
.subscribe(() => {
186+
this.roleService.getRoles().subscribe((roles) => {
187+
this.roleDataSource.data = roles;
188+
});
190189
});
191-
});
192190
});
193191
}
194192

@@ -203,14 +201,16 @@ export class AdminRolePermissionSearchComponent implements OnInit {
203201
if (!enteredInfo['name']) {
204202
return;
205203
}
206-
const newRole: RoleForm = {
207-
name: enteredInfo['name'],
208-
};
209-
this.roleService.updateRole(role.id, newRole).subscribe((result) => {
210-
this.roleService.getRoles().subscribe((roles) => {
211-
this.roleDataSource.data = roles;
204+
205+
this.roleService
206+
.updateRole(role.id, {
207+
name: enteredInfo['name'],
208+
})
209+
.subscribe((result) => {
210+
this.roleService.getRoles().subscribe((roles) => {
211+
this.roleDataSource.data = roles;
212+
});
212213
});
213-
});
214214
});
215215
}
216216

src/app/components/admin-app/admin-role-permission-search/create-permission-dialog/create-permission-dialog.component.html

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,9 @@ <h1 mat-dialog-title>{{ title }}</h1>
1212
placeholder="Name"
1313
tabIndex="1"
1414
name="key"
15-
[(ngModel)]="permission.key"
15+
[(ngModel)]="permission.name"
1616
/> </mat-form-field
1717
><br />
18-
<mat-form-field>
19-
<input
20-
matInput
21-
placeholder="Value"
22-
tabIndex="2"
23-
name="value"
24-
[(ngModel)]="permission.value"
25-
/> </mat-form-field
2618
><br />
2719
<mat-form-field>
2820
<input

src/app/components/admin-app/admin-role-permission-search/select-role-permissions-dialog/select-role-permissions-dialog.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ <h1 mat-dialog-title>Select Permissions for {{ role.name }}</h1>
1111
[value]="item.id"
1212
(click)="updateSelection(item.id)"
1313
>
14-
{{ item.key }}
14+
{{ item.key ?? item.name }}
1515
</mat-list-option>
1616
</mat-selection-list>
1717
<p>Options selected: {{ selectedPermissions.length }}</p>

src/app/components/admin-app/admin-role-permission-search/select-role-permissions-dialog/select-role-permissions-dialog.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export class SelectRolePermissionsDialogComponent implements OnInit {
3030
* Initialization
3131
*/
3232
ngOnInit() {
33-
this.permissions.sort(function (a, b) {
34-
return a.key.toLowerCase().localeCompare(b.key.toLowerCase());
35-
});
33+
// this.permissions.sort(function (a, b) {
34+
// return a.key.toLowerCase().localeCompare(b.key.toLowerCase());
35+
// });
3636
this.role.permissions.forEach((permission) => {
3737
this.selectedPermissions.push(permission.id);
3838
});

0 commit comments

Comments
 (0)