From f4f107f01d423e1f3d8d2f2e0a65dbcd8ef63de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20K=C3=A4sler?= <tom.kaesler@mni.thm.de> Date: Fri, 2 Aug 2019 01:09:16 +0200 Subject: [PATCH] Refactor auth system and auth guard --- .../_dialogs/room-edit/room-edit.component.ts | 2 +- .../creator/creator-routing.module.ts | 8 +++++ .../room-create/room-create.component.ts | 20 ++++++++---- .../shared/room-join/room-join.component.ts | 14 +++++--- src/app/guards/authentication.guard.ts | 7 ++-- src/app/models/events/room-created.ts | 13 ++++++++ .../{messages => events}/room-deleted.ts | 0 src/app/models/events/room-joined.ts | 13 ++++++++ .../services/http/authentication.service.ts | 29 +++++++++++++++-- src/app/services/http/room.service.ts | 32 +++++++++++++++---- 10 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 src/app/models/events/room-created.ts rename src/app/models/{messages => events}/room-deleted.ts (100%) create mode 100644 src/app/models/events/room-joined.ts diff --git a/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts b/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts index 17e932faf..1f5cf486d 100644 --- a/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts +++ b/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts @@ -8,7 +8,7 @@ import { RoomService } from '../../../../services/http/room.service'; import { Router } from '@angular/router'; import { RoomCreatorPageComponent } from '../../room-creator-page/room-creator-page.component'; import { EventService } from '../../../../services/util/event.service'; -import { RoomDeleted } from '../../../../models/messages/room-deleted'; +import { RoomDeleted } from '../../../../models/events/room-deleted'; @Component({ selector: 'app-room-edit', diff --git a/src/app/components/creator/creator-routing.module.ts b/src/app/components/creator/creator-routing.module.ts index eef47c99d..61db32fe6 100644 --- a/src/app/components/creator/creator-routing.module.ts +++ b/src/app/components/creator/creator-routing.module.ts @@ -15,41 +15,49 @@ const routes: Routes = [ { path: 'room/:roomId', component: RoomCreatorPageComponent, + canActivate: [AuthenticationGuard], data: { roles: [UserRole.CREATOR] } }, { path: 'room/:roomId/create-content', component: ContentCreatePageComponent, canActivate: [AuthenticationGuard], + data: { roles: [UserRole.CREATOR] } }, { path: 'room/:roomId/statistics', component: StatisticsPageComponent, canActivate: [AuthenticationGuard], + data: { roles: [UserRole.CREATOR] } }, { path: 'room/:roomId/statistics/:contentId', component: StatisticComponent, + canActivate: [AuthenticationGuard], data: { roles: [UserRole.CREATOR] } }, { path: 'room/:roomId/comments', component: CommentPageComponent, + canActivate: [AuthenticationGuard], data: { roles: [UserRole.CREATOR] } }, { path: 'room/:roomId/feedback-barometer', component: FeedbackBarometerPageComponent, + canActivate: [AuthenticationGuard], data: { roles: [UserRole.CREATOR] } }, { path: 'room/:roomId/:contentGroup', component: ContentListComponent, + canActivate: [AuthenticationGuard], data: { roles: [UserRole.CREATOR] } }, { path: 'room/:roomId/:contentGroup/presentation', component: ContentPresentationComponent, + canActivate: [AuthenticationGuard], data: { roles: [UserRole.CREATOR] } } ]; diff --git a/src/app/components/shared/_dialogs/room-create/room-create.component.ts b/src/app/components/shared/_dialogs/room-create/room-create.component.ts index 5d25a5be0..7f99231ac 100644 --- a/src/app/components/shared/_dialogs/room-create/room-create.component.ts +++ b/src/app/components/shared/_dialogs/room-create/room-create.component.ts @@ -1,10 +1,12 @@ import { Component, Inject, OnInit } from '@angular/core'; import { RoomService } from '../../../../services/http/room.service'; import { Room } from '../../../../models/room'; +import { UserRole } from '../../../../models/user-roles.enum'; import { Router } from '@angular/router'; import { NotificationService } from '../../../../services/util/notification.service'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; import { ContentService } from '../../../../services/http/content.service'; +import { AuthenticationService } from '../../../../services/http/authentication.service'; import { TranslateService } from '@ngx-translate/core'; import { TSMap } from 'typescript-map'; @@ -19,13 +21,16 @@ export class RoomCreateComponent implements OnInit { room: Room; roomId: string; - constructor(private roomService: RoomService, - private contentService: ContentService, - private router: Router, - private notification: NotificationService, - public dialogRef: MatDialogRef<RoomCreateComponent>, - private translateService: TranslateService, - @Inject(MAT_DIALOG_DATA) public data: any) { + constructor( + private roomService: RoomService, + private contentService: ContentService, + private router: Router, + private notification: NotificationService, + public dialogRef: MatDialogRef<RoomCreateComponent>, + private translateService: TranslateService, + private authService: AuthenticationService, + @Inject(MAT_DIALOG_DATA) public data: any + ) { } ngOnInit() { @@ -57,6 +62,7 @@ export class RoomCreateComponent implements OnInit { this.translateService.get('home-page.created-1').subscribe(msg => { msg1 = msg; }); this.translateService.get('home-page.created-2').subscribe(msg => { msg2 = msg; }); this.notification.show(msg1 + longRoomName + msg2); + this.authService.setAccess(room.shortId, UserRole.CREATOR); this.router.navigate([`/creator/room/${this.room.shortId}`]); this.dialogRef.close(); }); diff --git a/src/app/components/shared/room-join/room-join.component.ts b/src/app/components/shared/room-join/room-join.component.ts index 4d9ab6ebe..302f4ed94 100644 --- a/src/app/components/shared/room-join/room-join.component.ts +++ b/src/app/components/shared/room-join/room-join.component.ts @@ -25,11 +25,13 @@ export class RoomJoinComponent implements OnInit { matcher = new RegisterErrorStateMatcher(); - constructor(private roomService: RoomService, - private router: Router, - public notificationService: NotificationService, - private translateService: TranslateService, - public authenticationService: AuthenticationService) { + constructor( + private roomService: RoomService, + private router: Router, + public notificationService: NotificationService, + private translateService: TranslateService, + public authenticationService: AuthenticationService + ) { } ngOnInit() { @@ -93,6 +95,8 @@ export class RoomJoinComponent implements OnInit { this.router.navigate([`/creator/room/${this.room.shortId}/comments`]); } else { this.roomService.addToHistory(this.room.id); + this.authenticationService.setAccess(this.room.shortId, UserRole.PARTICIPANT); + this.router.navigate([`/participant/room/${this.room.shortId}/comments`]); } } diff --git a/src/app/guards/authentication.guard.ts b/src/app/guards/authentication.guard.ts index 5f4e5e726..aca9dbf90 100644 --- a/src/app/guards/authentication.guard.ts +++ b/src/app/guards/authentication.guard.ts @@ -15,17 +15,18 @@ export class AuthenticationGuard implements CanActivate { private router: Router) { } - canActivate(next: ActivatedRouteSnapshot, + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { // Get active user const user: User = this.authenticationService.getUser(); // Get roles having access to this route // undefined if every logged in user should have access regardless of its role - const requiredRoles = next.data['roles'] as Array<UserRole>; + const requiredRoles = route.data['roles'] as Array<UserRole>; // Allow access when user is logged in AND // the route doesn't require a specific role OR // the user's role is one of the required roles - if (user && (!requiredRoles || requiredRoles.includes(user.role))) { + console.log(requiredRoles[0]); + if (this.authenticationService.hasAccess(route.params.roomId, requiredRoles[0])) { return true; } diff --git a/src/app/models/events/room-created.ts b/src/app/models/events/room-created.ts new file mode 100644 index 000000000..3bc9ea5da --- /dev/null +++ b/src/app/models/events/room-created.ts @@ -0,0 +1,13 @@ +export class RoomCreated { + type: string; + payload: { + id: string; + }; + + constructor(id: string) { + this.type = 'RoomCreated'; + this.payload = { + id: id + }; + } +} diff --git a/src/app/models/messages/room-deleted.ts b/src/app/models/events/room-deleted.ts similarity index 100% rename from src/app/models/messages/room-deleted.ts rename to src/app/models/events/room-deleted.ts diff --git a/src/app/models/events/room-joined.ts b/src/app/models/events/room-joined.ts new file mode 100644 index 000000000..204688915 --- /dev/null +++ b/src/app/models/events/room-joined.ts @@ -0,0 +1,13 @@ +export class RoomJoined { + type: string; + payload: { + id: string; + }; + + constructor(id: string) { + this.type = 'RoomJoined'; + this.payload = { + id: id + }; + } +} diff --git a/src/app/services/http/authentication.service.ts b/src/app/services/http/authentication.service.ts index cb5eccd37..e867a10d2 100644 --- a/src/app/services/http/authentication.service.ts +++ b/src/app/services/http/authentication.service.ts @@ -4,6 +4,7 @@ import { User } from '../../models/user'; import { Observable , of , BehaviorSubject } from 'rxjs'; import { UserRole } from '../../models/user-roles.enum'; import { DataStoreService } from '../util/data-store.service'; +import { EventService } from '../util/event.service'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { ClientAuthentication } from '../../models/client-authentication'; @@ -26,12 +27,26 @@ export class AuthenticationService { headers: new HttpHeaders({}) }; - constructor(private dataStoreService: DataStoreService, - private http: HttpClient) { + private roomAccess = new Map(); + + constructor( + private dataStoreService: DataStoreService, + public eventService: EventService, + private http: HttpClient + ) { if (dataStoreService.has(this.STORAGE_KEY)) { // Load user data from local data store if available this.user.next(JSON.parse(dataStoreService.get(this.STORAGE_KEY))); } + this.eventService.on<any>('RoomJoined').subscribe(payload => { + this.roomAccess.set(payload.id, UserRole.PARTICIPANT); + }); + this.eventService.on<any>('RoomDeleted').subscribe(payload => { + this.roomAccess.delete(payload.id); + }); + this.eventService.on<any>('RoomCreated').subscribe(payload => { + this.roomAccess.set(payload.id, UserRole.CREATOR); + }); } /* @@ -149,4 +164,14 @@ export class AuthenticationService { getUserAsSubject(): BehaviorSubject<User> { return this.user; } + + hasAccess(roomId: string, role: UserRole): boolean { + const usersRole = this.roomAccess.get(roomId); + console.log(usersRole); + return (usersRole && (usersRole === role)); + } + + setAccess(roomId: string, role: UserRole): void { + this.roomAccess.set(roomId, role); + } } diff --git a/src/app/services/http/room.service.ts b/src/app/services/http/room.service.ts index 36fcdb516..333519ec3 100644 --- a/src/app/services/http/room.service.ts +++ b/src/app/services/http/room.service.ts @@ -1,10 +1,14 @@ import { Injectable } from '@angular/core'; import { Room } from '../../models/room'; +import { RoomJoined } from '../../models/events/room-joined'; +import { RoomCreated } from '../../models/events/room-created'; +import { UserRole } from '../../models/user-roles.enum'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; import { catchError, tap, map } from 'rxjs/operators'; import { AuthenticationService } from './authentication.service'; import { BaseHttpService } from './base-http.service'; +import { EventService } from '../util/event.service'; import { TSMap } from 'typescript-map'; const httpOptions = { @@ -21,8 +25,11 @@ export class RoomService extends BaseHttpService { }; private joinDate = new Date(Date.now()); - constructor(private http: HttpClient, - private authService: AuthenticationService) { + constructor( + private http: HttpClient, + private eventService: EventService, + private authService: AuthenticationService + ) { super(); } @@ -32,7 +39,11 @@ export class RoomService extends BaseHttpService { properties: { ownerId: this.authService.getUser().id }, externalFilters: {} }).pipe( - tap(() => ''), + tap((rooms) => { + for (const r of rooms) { + this.authService.setAccess(r.shortId, UserRole.CREATOR); + } + }), catchError(this.handleError('getCreatorRooms', [])) ); } @@ -43,7 +54,11 @@ export class RoomService extends BaseHttpService { properties: {}, externalFilters: { inHistoryOfUserId: this.authService.getUser().id } }).pipe( - tap(() => ''), + tap((rooms) => { + for (const r of rooms) { + this.authService.setAccess(r.shortId, UserRole.PARTICIPANT); + } + }), catchError(this.handleError('getParticipantRooms', [])) ); } @@ -53,7 +68,12 @@ export class RoomService extends BaseHttpService { delete room.revision; const connectionUrl = this.apiUrl.base + this.apiUrl.rooms + '/'; room.ownerId = this.authService.getUser().id; - return this.http.post<Room>(connectionUrl, room, httpOptions); + return this.http.post<Room>(connectionUrl, room, httpOptions).pipe( + tap(returnedRoom => { + this.authService.setAccess(returnedRoom.shortId, UserRole.PARTICIPANT); + }), + catchError(this.handleError<Room>(`add Room ${room}`)) + ); } getRoom(id: string): Observable<Room> { @@ -78,7 +98,7 @@ export class RoomService extends BaseHttpService { addToHistory(roomId: string): void { const connectionUrl = `${ this.apiUrl.base + this.apiUrl.user }/${ this.authService.getUser().id }/roomHistory`; - this.http.post(connectionUrl, { roomId: roomId, lastVisit: this.joinDate.getTime() }, httpOptions).subscribe(); + this.http.post(connectionUrl, { roomId: roomId, lastVisit: this.joinDate.getTime() }, httpOptions).subscribe(() => {}); } updateRoom(updatedRoom: Room): Observable<Room> { -- GitLab