Skip to content

Commit af8f7e1

Browse files
authored
DSM-PEPPER-963 user administration services (#2175)
* DSM-/PEPPER-948-download-of-Onc-History-upload-template initial * DSM-PEPPER-948-download-of-Onc-History-upload-template backend integrated * DSM-PEPPER-948-download-of-Onc-History-upload-template linter fix * DSM-PEPPER-948-download-of-Onc-History-upload-template color adjusted * DSM-PEPPER-948-download-of-Onc-History-upload-template naming fixed * DSM-PEPPER-948-download-of-Onc-History-upload-template first step * DSM-PEPPER-948-download-of-Onc-History-upload-template comparison on place * DSM-PEPPER-948-download-of-Onc-History-upload-template only available roles in comparison * DSM-PEPPER-948-download-of-Onc-History-upload-template other color user * DSM-PEPPER-948-download-of-Onc-History-upload-template add user added * DSM-PEPPER-948-download-of-Onc-History-upload-template user is adding * DSM-PEPPER-948-download-of-Onc-History-upload-template safety v1 * DSM-PEPPER-948-download-of-Onc-History-upload-template more improvements * DSM-PEPPER-963-user-administration-services disabled checkbox * DSM-PEPPER-963-user-administration-services backend integration v1 * DSM-PEPPER-963-user-administration-services backend integration v2 * DSM-PEPPER-963-user-administration-services linter fix * DSM-PEPPER-963-user-administration-services panel title width expanded * DSM-PEPPER-963-user-administration-services integrated backend and made some adjustments * DSM-PEPPER-963-user-administration-services backend integration and error handling finished * DSM-PEPPER-963-user-administration-services removed consoles * DSM-PEPPER-963-user-administration-services sorted and logout * DSM-PEPPER-963-user-administration-services if error don't display * DSM-PEPPER-963-user-administration-services guards and edit user updated * DSM-PEPPER-963-user-administration-services linter fix * DSM-PEPPER-963-user-administration-services confirmation modal generalized * DSM-PEPPER-963-user-administration-services linter fix * DSM-PEPPER-963-user-administration-services unit test adjusted * DSM-PEPPER-963-user-administration-services removed commented code
1 parent a33d902 commit af8f7e1

39 files changed

+1717
-18
lines changed

ddp-workspace/projects/ddp-dsm-ui/src/app/ALL-STUDIES/all-studies.module.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,13 @@ import {UploadFileComponent} from '../sharedLearningUpload/components/uploadFile
145145
import {FilesTableComponent} from '../sharedLearningUpload/components/filesTable/filesTable.component';
146146
import {
147147
ConfirmationModalComponent
148-
} from '../sharedLearningUpload/components/confirmationModal/confirmationModal.component';
148+
} from '../Shared/components/confirmationModal/confirmationModal.component';
149149
import {OncHistoryUploadComponent} from '../oncHistoryUpload/oncHistoryUpload.component';
150150
import {OncHistoryUploadGuard} from '../guards/oncHistoryUpload.guard';
151+
import {
152+
UsersAndPermissionsCanActivateGuard,
153+
UsersAndPermissionsCanLoadGuard
154+
} from '../guards/usersAndPermissions.guard';
151155

152156

153157
PlotlyModule.plotlyjs = PlotlyJS;
@@ -301,7 +305,9 @@ PlotlyModule.plotlyjs = PlotlyJS;
301305
Statics,
302306
Language,
303307
DashboardStatisticsService,
304-
OncHistoryUploadGuard
308+
OncHistoryUploadGuard,
309+
UsersAndPermissionsCanLoadGuard,
310+
UsersAndPermissionsCanActivateGuard
305311
],
306312
exports: [RouterModule, MatFormFieldModule, MatInputModule]
307313
})

ddp-workspace/projects/ddp-dsm-ui/src/app/ALL-STUDIES/all-studies.routing.module.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ import {DashboardStatisticsComponent} from '../dashboard-statistics/dashboard-st
3838
import {ScannerComponent} from '../scanner/scanner.component';
3939
import {OncHistoryUploadComponent} from '../oncHistoryUpload/oncHistoryUpload.component';
4040
import {OncHistoryUploadGuard} from '../guards/oncHistoryUpload.guard';
41+
import {
42+
UsersAndPermissionsCanActivateGuard,
43+
UsersAndPermissionsCanLoadGuard
44+
} from '../guards/usersAndPermissions.guard';
4145

4246

4347

@@ -94,6 +98,12 @@ export const AppRoutes: Routes = [
9498
{path: 'oncHistoryUpload', component: OncHistoryUploadComponent, canActivate: [AuthGuard, OncHistoryUploadGuard]},
9599

96100
{path: 'userSettings', component: UserSettingComponent, canActivate: [AuthGuard]},
101+
{path: 'usersAndPermissions',
102+
canActivate: [UsersAndPermissionsCanActivateGuard],
103+
canLoad: [UsersAndPermissionsCanLoadGuard],
104+
loadChildren: () =>
105+
import('../usersAndPermissions/usersAndPermissions.module').then(m => m.UsersAndPermissionsModule)
106+
},
97107

98108
// Permalink
99109
{
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<main id="confirmationModal" class="confirmationModal">
22
<section class="confirmationModal-content">
3-
<p>Are you sure you want to delete {{fileName}}?</p>
3+
<p>Are you sure you want to delete {{name}}?</p>
44
<i><span>Warning:</span> this action can't be undone</i>
55
</section>
66
<section class="confirmationModal-buttons">
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@use 'commonStyles' as common;
1+
@use 'projects/ddp-dsm-ui/src/styles/commonStyles' as common;
22

33
$yes-color: #FF595E;
44
$no-color: #5FA8D3;
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
99
export class ConfirmationModalComponent {
1010
constructor(
1111
private readonly dialogRef: MatDialogRef<ConfirmationModalComponent>,
12-
@Inject(MAT_DIALOG_DATA) private data: {fileName: string},
12+
@Inject(MAT_DIALOG_DATA) private data: {name: string},
1313
) {}
1414

1515
public confirmationAnswerIs(doIt: boolean): void {
1616
this.dialogRef.close(doIt);
1717
}
1818

19-
public get fileName(): string {
20-
return this.data.fileName;
19+
public get name(): string {
20+
return this.data.name;
2121
}
2222
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe('ConfirmationModalComponent', () => {
1919
},
2020
{
2121
provide: MAT_DIALOG_DATA,
22-
useValue: {fileName: 'testFile.pdf'}
22+
useValue: {name: 'testFile.pdf'}
2323
}
2424
]
2525
}).compileComponents();
@@ -38,12 +38,12 @@ describe('ConfirmationModalComponent', () => {
3838
expect(component).toBeTruthy('Component has not been instantiated');
3939
});
4040

41-
it('should display file name', () => {
41+
it('should display name', () => {
4242
const fileName = componentHTML
4343
.query(By.css('section.confirmationModal-content p'))
4444
.nativeElement.textContent;
4545

46-
expect(fileName).toContain('testFile.pdf', 'File name is not displayed');
46+
expect(fileName).toContain('testFile.pdf', 'Name is not displayed');
4747
});
4848

4949
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {Injectable} from '@angular/core';
2+
import {
3+
ActivatedRouteSnapshot,
4+
CanActivate,
5+
CanLoad,
6+
Route,
7+
RouterStateSnapshot,
8+
UrlSegment,
9+
UrlTree
10+
} from '@angular/router';
11+
import {RoleService} from '../services/role.service';
12+
13+
@Injectable()
14+
export class UsersAndPermissionsCanLoadGuard implements CanLoad {
15+
constructor(private readonly roleService: RoleService) {}
16+
17+
canLoad(route: Route, segments: UrlSegment[]): boolean | UrlTree {
18+
return this.roleService.isStudyUserAdmin || this.roleService.isPepperAdmin;
19+
}
20+
}
21+
22+
23+
@Injectable()
24+
export class UsersAndPermissionsCanActivateGuard implements CanActivate {
25+
constructor(private readonly roleService: RoleService) {}
26+
27+
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
28+
return this.roleService.isStudyUserAdmin || this.roleService.isPepperAdmin;
29+
}
30+
}

ddp-workspace/projects/ddp-dsm-ui/src/app/interceptors/Http-interceptor.service.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,26 @@ import {Observable, throwError} from 'rxjs';
99
import {catchError} from 'rxjs/operators';
1010
import {Injectable} from '@angular/core';
1111
import {ErrorsService} from '../services/errors.service';
12+
import {Auth} from '../services/auth.service';
1213

1314
@Injectable()
1415
export class HttpInterceptorService implements HttpInterceptor {
1516
private readonly ignoreStatuses: number[] = [401];
1617

17-
constructor(private errorsService: ErrorsService) {}
18+
constructor(private readonly errorsService: ErrorsService,
19+
private readonly authService: Auth) {}
1820

1921
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
2022
return next.handle(req).pipe(
2123
catchError((error: any) => {
22-
error instanceof HttpErrorResponse &&
23-
!this.ignoreStatuses.includes(error?.status) &&
24-
this.errorsService.openSnackbar(error);
24+
25+
26+
if(error instanceof HttpErrorResponse) {
27+
!this.ignoreStatuses.includes(error?.status) &&
28+
this.errorsService.openSnackbar(error);
29+
30+
error?.status === 401 && this.authService.doLogout();
31+
}
2532

2633
return throwError(() => error);
2734
})

ddp-workspace/projects/ddp-dsm-ui/src/app/navigation/navigation.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
<li *ngIf="hasRole().allowedToDownloadNDI()"><a href="#" [routerLink]="['ndi']"> NDI Upload </a></li>
8686
<li *ngIf="showOncHistoryUploadPage(selectedStudy | async)"><a [routerLink]="['oncHistoryUpload']">Onc History Upload</a></li>
8787
<li ><a href="#" [routerLink]="['drugList']"> Drug List </a></li>
88+
<li *ngIf="hasRole().isPepperAdmin || hasRole().isStudyUserAdmin"><a href="#" [routerLink]="['usersAndPermissions']"> Users And Permissions </a></li>
8889
</ul>
8990
</li>
9091
</ul>

ddp-workspace/projects/ddp-dsm-ui/src/app/services/dsm.service.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import {IDateRange} from '../dashboard-statistics/interfaces/IDateRange';
2121
import {StatisticsEnum} from '../dashboard-statistics/enums/statistics.enum';
2222
import {SomaticResultSignedUrlRequest} from '../sharedLearningUpload/interfaces/somaticResultSignedUrlRequest';
2323
import {SendToParticipantRequest} from '../sharedLearningUpload/interfaces/sendToParticipant';
24+
import {AddUsersRequest, RemoveUsersRequest} from '../usersAndPermissions/interfaces/addRemoveUsers';
25+
import {EditUsers} from '../usersAndPermissions/interfaces/editUsers';
26+
import {EditUserRoles} from '../usersAndPermissions/interfaces/role';
2427

2528
declare var DDP_ENV: any;
2629

@@ -458,6 +461,60 @@ export class DSMService {
458461
);
459462
}
460463

464+
public getUsers(realm: string): Observable<any> {
465+
const url = this.baseUrl + DSMService.UI + 'admin/userRole';
466+
const map: { name: string; value: any }[] = [];
467+
map.push({name: DSMService.REALM, value: realm});
468+
return this.http.get(url, this.buildQueryHeader(map)).pipe(
469+
catchError(this.handleError)
470+
);
471+
}
472+
473+
public addUser(realm: string, addUsers: AddUsersRequest): Observable<any> {
474+
const url = this.baseUrl + DSMService.UI + 'admin/user';
475+
const map: { name: string; value: any }[] = [];
476+
map.push({name: DSMService.REALM, value: realm});
477+
return this.http.post(url, addUsers, this.buildQueryHeader(map)).pipe(
478+
catchError(this.handleError)
479+
);
480+
}
481+
482+
public removeUser(realm: string, removeUsers: RemoveUsersRequest): Observable<any> {
483+
const url = this.baseUrl + DSMService.UI + 'admin/user';
484+
const map: { name: string; value: any }[] = [];
485+
map.push({name: DSMService.REALM, value: realm});
486+
return this.http.post(url, removeUsers, this.buildQueryHeader(map)).pipe(
487+
catchError(this.handleError)
488+
);
489+
}
490+
491+
public editUsers(realm: string, editUser: EditUsers): Observable<any> {
492+
const url = this.baseUrl + DSMService.UI + 'admin/user';
493+
const map: { name: string; value: any }[] = [];
494+
map.push({name: DSMService.REALM, value: realm});
495+
return this.http.put(url, editUser, this.buildQueryHeader(map)).pipe(
496+
catchError(this.handleError)
497+
);
498+
}
499+
500+
public editUsersRoles(realm: string, userRoles: EditUserRoles): Observable<any> {
501+
const url = this.baseUrl + DSMService.UI + 'admin/userRole';
502+
const map: { name: string; value: any }[] = [];
503+
map.push({name: DSMService.REALM, value: realm});
504+
return this.http.put(url, userRoles, this.buildQueryHeader(map)).pipe(
505+
catchError(this.handleError)
506+
);
507+
}
508+
509+
public availableRoles(realm: string): Observable<any> {
510+
const url = this.baseUrl + DSMService.UI + 'admin/studyRole';
511+
const map: { name: string; value: any }[] = [];
512+
map.push({name: DSMService.REALM, value: realm});
513+
return this.http.get(url, this.buildQueryHeader(map)).pipe(
514+
catchError(this.handleError)
515+
);
516+
}
517+
461518
public getMedicalRecord(participantId: string, institutionId: string): Observable<any> {
462519
const url = this.baseUrl + DSMService.UI + 'participant/' + participantId + '/institution/' + institutionId;
463520
return this.http.get(url, this.buildHeader()).pipe(

0 commit comments

Comments
 (0)