Skip to content

Commit e303077

Browse files
committed
feat(admin): disable adding user realated attrbiutes to active service
* added logic to check if consent is required for service * if consent is required user related attributes are disabled in add req. att. dialog * added tooltip to such attributes * added alert to inform users that it is prefered to add attributes when service is disabled
1 parent 3bc5079 commit e303077

File tree

8 files changed

+91
-8
lines changed

8 files changed

+91
-8
lines changed

apps/admin-gui/src/app/shared/components/attr-def-list/attr-def-list.component.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
(click)="$event.stopPropagation()"
3030
[aria-label]="checkboxLabel(row)"
3131
[checked]="selection.isSelected(row)"
32+
[disabled]="row.namespace | consentRelatedAttribute:serviceEnabled:consentRequired"
33+
[matTooltip]="'ADMIN.ATTRIBUTES.CONSENT_RELATED_DISABLED' | translate"
34+
[matTooltipDisabled]="!(row.namespace | consentRelatedAttribute:serviceEnabled:consentRequired)"
35+
matTooltipPosition="left"
3236
color="primary">
3337
</mat-checkbox>
3438
</td>

apps/admin-gui/src/app/shared/components/attr-def-list/attr-def-list.component.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
TableWrapperComponent,
2424
} from '@perun-web-apps/perun/utils';
2525
import { GuiAuthResolver, TableCheckbox } from '@perun-web-apps/perun/services';
26+
import { ConsentRelatedAttributePipe } from '../../pipes/consent-related-attribute.pipe';
2627

2728
@Component({
2829
selector: 'app-attr-def-list',
@@ -33,7 +34,8 @@ export class AttrDefListComponent implements OnChanges, AfterViewInit {
3334
constructor(
3435
private dialog: MatDialog,
3536
private authResolver: GuiAuthResolver,
36-
private tableCheckbox: TableCheckbox
37+
private tableCheckbox: TableCheckbox,
38+
private consentRelatedPipe: ConsentRelatedAttributePipe
3739
) {}
3840

3941
@Input()
@@ -56,6 +58,8 @@ export class AttrDefListComponent implements OnChanges, AfterViewInit {
5658
tableId: string;
5759
@Input()
5860
disableRouting = false;
61+
@Input() consentRequired = false;
62+
@Input() serviceEnabled = false;
5963

6064
@Output()
6165
refreshEvent = new EventEmitter<void>();
@@ -72,6 +76,9 @@ export class AttrDefListComponent implements OnChanges, AfterViewInit {
7276
private sort: MatSort;
7377
pageSizeOptions = TABLE_ITEMS_COUNT_OPTIONS;
7478

79+
canBeSelected = (row: AttributeDefinition) =>
80+
!this.consentRelatedPipe.transform(row.namespace, this.serviceEnabled, this.consentRequired);
81+
7582
ngOnChanges() {
7683
if (!this.authResolver.isPerunAdminOrObserver()) {
7784
this.displayedColumns = this.displayedColumns.filter((column) => column !== 'id');
@@ -143,12 +150,15 @@ export class AttrDefListComponent implements OnChanges, AfterViewInit {
143150
}
144151

145152
isAllSelected() {
146-
return this.tableCheckbox.isAllSelected(
153+
return this.tableCheckbox.isAllSelectedWithDisabledCheckbox(
147154
this.selection.selected.length,
148155
this.filterValue,
149156
this.child.paginator.pageSize,
150157
this.child.paginator.hasNextPage(),
151-
this.dataSource
158+
this.child.paginator.pageIndex,
159+
this.dataSource,
160+
this.sort,
161+
this.canBeSelected
152162
);
153163
}
154164

@@ -161,7 +171,8 @@ export class AttrDefListComponent implements OnChanges, AfterViewInit {
161171
this.sort,
162172
this.child.paginator.pageSize,
163173
this.child.paginator.pageIndex,
164-
false
174+
true,
175+
this.canBeSelected
165176
);
166177
}
167178

apps/admin-gui/src/app/shared/components/dialogs/add-required-attributes-dialog/add-required-attributes-dialog.component.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
<h1 mat-dialog-title>{{'DIALOGS.ADD_REQUIRED_ATTRIBUTES.TITLE' | translate}}</h1>
33
<mat-spinner *ngIf="loading" class="mr-auto ml-auto"></mat-spinner>
44
<div *ngIf="!loading" mat-dialog-content class="dialog-container">
5+
<app-alert
6+
*ngIf="serviceEnabled$ | async"
7+
[alert_type]="'warn'"
8+
>{{'DIALOGS.ADD_REQUIRED_ATTRIBUTES.ACTIVE_WARN' | translate}}</app-alert
9+
>
510
<perun-web-apps-immediate-filter
611
(filter)="applyFilter($event)"
712
[placeholder]="'DIALOGS.ADD_REQUIRED_ATTRIBUTES.FILTER'">
@@ -10,7 +15,9 @@ <h1 mat-dialog-title>{{'DIALOGS.ADD_REQUIRED_ATTRIBUTES.TITLE' | translate}}</h1
1015
[selection]="selection"
1116
[definitions]="attrDefinitions"
1217
[disableRouting]="true"
13-
[filterValue]="filterValue">
18+
[filterValue]="filterValue"
19+
[serviceEnabled]="serviceEnabled$ | async"
20+
[consentRequired]="consentRequired$ | async">
1421
</app-attr-def-list>
1522
</div>
1623
<div mat-dialog-actions *ngIf="!loading">

apps/admin-gui/src/app/shared/components/dialogs/add-required-attributes-dialog/add-required-attributes-dialog.component.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
33
import {
44
AttributeDefinition,
55
AttributesManagerService,
6+
ConsentHub,
7+
ConsentsManagerService,
8+
FacilitiesManagerService,
9+
Facility,
610
ServicesManagerService,
711
} from '@perun-web-apps/perun/openapi';
812
import { NotificatorService } from '@perun-web-apps/perun/services';
913
import { TranslateService } from '@ngx-translate/core';
1014
import { SelectionModel } from '@angular/cdk/collections';
15+
import { from, Observable } from 'rxjs';
16+
import { concatMap, distinct, map, mergeMap, reduce, startWith } from 'rxjs/operators';
1117

1218
export interface AddRequiredAttributesDialogData {
1319
serviceId: number;
@@ -25,10 +31,29 @@ export class AddRequiredAttributesDialogComponent implements OnInit {
2531
@Inject(MAT_DIALOG_DATA) private data: AddRequiredAttributesDialogData,
2632
private serviceManager: ServicesManagerService,
2733
private attributesManager: AttributesManagerService,
34+
private facilitiesService: FacilitiesManagerService,
35+
private consentHubService: ConsentsManagerService,
2836
private notificator: NotificatorService,
2937
private translate: TranslateService
3038
) {}
3139

40+
consentRequired$: Observable<boolean> = this.facilitiesService
41+
.getAssignedFacilitiesByService(this.data.serviceId)
42+
.pipe(
43+
concatMap(from),
44+
map((facility: Facility) => facility.id),
45+
distinct(),
46+
mergeMap((id: number) => this.consentHubService.getConsentHubByFacility(id)),
47+
reduce((req, hub: ConsentHub) => req || hub.enforceConsents, false),
48+
startWith(true)
49+
);
50+
serviceEnabled$: Observable<boolean> = this.serviceManager
51+
.getServiceById(this.data.serviceId)
52+
.pipe(
53+
map((service) => service.enabled),
54+
startWith(true)
55+
);
56+
3257
theme: string;
3358
serviceId: number;
3459

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Pipe, PipeTransform } from '@angular/core';
2+
import { StoreService } from '@perun-web-apps/perun/services';
3+
4+
@Pipe({
5+
name: 'consentRelatedAttribute',
6+
})
7+
export class ConsentRelatedAttributePipe implements PipeTransform {
8+
private USER_CONSENT_RELATED_ATT_NAMESPACE: string[] = [
9+
'urn:perun:user_facility:attribute-def',
10+
'urn:perun:user:attribute-def',
11+
'urn:perun:member:attribute-def',
12+
'urn:perun:member_group:attribute-def',
13+
'urn:perun:member_resource:attribute-def',
14+
'urn:perun:ues:attribute-def',
15+
];
16+
17+
constructor(private storeService: StoreService) {}
18+
19+
transform(attNamespace: string, serviceEnabled: boolean, enforceHubConsent: boolean): boolean {
20+
const enforceInstanceConsent: boolean = this.storeService.get('enforce_consents') as boolean;
21+
if (!enforceInstanceConsent || !enforceHubConsent || !serviceEnabled) {
22+
return false;
23+
}
24+
25+
// When consent is required mark consent related attributes
26+
return this.USER_CONSENT_RELATED_ATT_NAMESPACE.reduce(
27+
(acc: boolean, namespace) => acc || attNamespace.startsWith(namespace),
28+
false
29+
);
30+
}
31+
}

apps/admin-gui/src/app/shared/shared.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ import { AuditMessageDetailDialogComponent } from './components/dialogs/audit-me
171171
import { ParseEventNamePipe } from './pipes/parse-event-name.pipe';
172172
import { ConsentHubsListComponent } from './components/consent-hubs-list/consent-hubs-list.component';
173173
import { EditEnforceConsentsDialogComponent } from './components/dialogs/edit-enforce-consents-dialog/edit-enforce-consents-dialog.component';
174+
import { ConsentRelatedAttributePipe } from './pipes/consent-related-attribute.pipe';
174175

175176
@NgModule({
176177
imports: [
@@ -435,8 +436,9 @@ import { EditEnforceConsentsDialogComponent } from './components/dialogs/edit-en
435436
ParseEventNamePipe,
436437
ConsentHubsListComponent,
437438
EditEnforceConsentsDialogComponent,
439+
ConsentRelatedAttributePipe,
438440
],
439-
providers: [AnyToStringPipe, ExtSourceTypePipe],
441+
providers: [AnyToStringPipe, ExtSourceTypePipe, ConsentRelatedAttributePipe],
440442
})
441443
export class SharedModule {
442444
constructor(private translate: TranslateService) {

apps/admin-gui/src/assets/config/defaultConfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"skip_oidc": false,
5252
"group_name_secondary_regex": "^[-a-zA-Z.0-9_ ]+$",
5353
"group_name_error_message": "Name cannot be empty and can contain only characters a-z, A-Z, numbers, spaces, dots, '_' and '-'",
54+
"enforce_consents": false,
5455
"footer": {
5556
"columns": [
5657
{

apps/admin-gui/src/assets/i18n/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,8 @@
17191719
"ADD": "Add",
17201720
"CANCEL": "Cancel",
17211721
"SUCCESS": "Required attributes were added.",
1722-
"FILTER": "Filter"
1722+
"FILTER": "Filter",
1723+
"ACTIVE_WARN": "Service is active. Some attributes can only be added to disabled services. Preferably disable service before adding required attributes."
17231724
},
17241725
"REMOVE_REQUIRED_ATTRIBUTES": {
17251726
"TITLE": "Remove required attributes",
@@ -2160,7 +2161,8 @@
21602161
"IMPORT": "Import",
21612162
"DELETE": "Delete",
21622163
"SEARCH": "Filter by Id, name, entity, definition, or type",
2163-
"NO_ATTRIBUTES": "There are no attributes available."
2164+
"NO_ATTRIBUTES": "There are no attributes available.",
2165+
"CONSENT_RELATED_DISABLED": "Attribute requires user's permission. It can only be added, when service is disabled."
21642166
},
21652167
"USERS": {
21662168
"TITLE": "Users",

0 commit comments

Comments
 (0)