diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index bb321d3b772d0bc8a53c9b099ddf52e87709755e..d4838e24289ac083a5f9e8a783f997624cdc4a58 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -5,13 +5,30 @@ import { LoginScreenComponent } from './login-screen/login-screen.component'; import { RoomComponent } from './room/room.component'; import { CreatorHomeScreenComponent } from './creator-home-screen/creator-home-screen.component'; import { ParticipantHomeScreenComponent } from './participant-home-screen/participant-home-screen.component'; +import { AuthenticationGuard } from './authentication.guard'; +import { UserRole } from './user-roles.enum'; const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', component: LoginScreenComponent }, - { path: 'creator', component: CreatorHomeScreenComponent }, - { path: 'room/:roomId', component: RoomComponent }, - { path: 'participant', component: ParticipantHomeScreenComponent }, + { + path: 'creator', + component: CreatorHomeScreenComponent, + canActivate: [AuthenticationGuard], + data: { roles: [UserRole.CREATOR] } + }, + { + path: 'participant', + component: ParticipantHomeScreenComponent, + canActivate: [AuthenticationGuard], + data: { roles: [UserRole.PARTICIPANT] } + }, + { + path: 'room/:roomId', + component: RoomComponent, + canActivate: [AuthenticationGuard], + data: { roles: [UserRole.PARTICIPANT, UserRole.CREATOR] } + }, { path: '**', component: PageNotFoundComponent } ]; diff --git a/src/app/authentication.guard.ts b/src/app/authentication.guard.ts index 603935c9260f39e6966742a718c6636d4da76296..5e0393aab1dae9a0233e4c362ad73c012611443b 100644 --- a/src/app/authentication.guard.ts +++ b/src/app/authentication.guard.ts @@ -6,6 +6,7 @@ import 'rxjs/add/operator/map'; import 'rxjs/add/observable/of'; import 'rxjs/add/operator/catch'; import { NotificationService } from './notification.service'; +import { UserRole } from './user-roles.enum'; @Injectable() export class AuthenticationGuard implements CanActivate { @@ -16,13 +17,15 @@ export class AuthenticationGuard implements CanActivate { canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { - return this.authenticationService.isLoggedIn().map(isLoggedIn => { - if (!isLoggedIn) { - this.notificationService.show(`You're not authorized to view this page.`); - // TODO: redirect to error page - this.router.navigate(['/']); + return this.authenticationService.getUser().map(user => { + const requiredRoles = next.data['roles'] as Array<UserRole>; + if (user && requiredRoles.includes(user.role)) { + return true; } - return isLoggedIn; + this.notificationService.show(`You're not authorized to view this page.`); + // TODO: redirect to error page + this.router.navigate(['/']); + return false; }); } } diff --git a/src/app/authentication.service.ts b/src/app/authentication.service.ts index 7b9fbda82025ce0271b918ebff5ebcf38ebb819d..7f5349c3d8550d1b5f9cf516763c1af02eafc0ff 100644 --- a/src/app/authentication.service.ts +++ b/src/app/authentication.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { User } from './user'; import { Observable } from 'rxjs/Observable'; import { of } from 'rxjs/observable/of'; +import { UserRole } from './user-roles.enum'; // TODO: connect to API // TODO: persist user data (shouldn't get lost on page refresh) @@ -11,8 +12,8 @@ export class AuthenticationService { constructor() { } - login(email: string, password: string, isCreator: boolean): Observable<boolean> { - this.mockUser = new User(1, '', email, isCreator); + login(email: string, password: string, role: UserRole): Observable<boolean> { + this.mockUser = new User(1, '', email, role); return of(true); } @@ -36,8 +37,8 @@ export class AuthenticationService { return of(this.mockUser !== undefined); } - isCreator(): Observable<boolean> { - return of(this.mockUser.isCreator); + getRole(): Observable<UserRole> { + return of(this.mockUser.role); } } diff --git a/src/app/login-screen/login-screen.component.html b/src/app/login-screen/login-screen.component.html index e9fcc948524fbb064de86f65b40f0eeb1c2bddd5..bf7e56ddf25da5bc8418c908210d40e7645bd4f0 100644 --- a/src/app/login-screen/login-screen.component.html +++ b/src/app/login-screen/login-screen.component.html @@ -4,7 +4,7 @@ <mat-tab label="Creator"> <div fxLayout="column" fxLayoutAlign="start" fxLayoutGap="20px"> <div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="5px"> - <app-login fxFill [isCreator]="true"></app-login> + <app-login fxFill [role]="UserRole.CREATOR"></app-login> </div> <div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="5px"> <button mat-button color="primary" (click)="openRegisterDialog()">Register</button> @@ -15,7 +15,7 @@ <mat-tab label="Participant"> <div fxLayout="column" fxLayoutAlign="start" fxLayoutGap="20px"> <div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="5px"> - <app-login fxFill [isCreator]="false"></app-login> + <app-login fxFill [role]="UserRole.PARTICIPANT"></app-login> </div> <div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="5px"> <button mat-button color="primary" (click)="openRegisterDialog()">Register</button> diff --git a/src/app/login-screen/login-screen.component.ts b/src/app/login-screen/login-screen.component.ts index 5184b73dcc3ae1fa7d398cf1787355af2d8bfdb1..4de62b9a8c31316a2cbd42e1b23c3b2027c5de40 100644 --- a/src/app/login-screen/login-screen.component.ts +++ b/src/app/login-screen/login-screen.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material'; import { RegisterComponent } from '../register/register.component'; import { PasswordResetComponent } from '../password-reset/password-reset.component'; +import { UserRole } from '../user-roles.enum'; @Component({ selector: 'app-login-screen', @@ -9,6 +10,8 @@ import { PasswordResetComponent } from '../password-reset/password-reset.compone styleUrls: ['./login-screen.component.scss'] }) export class LoginScreenComponent implements OnInit { + // Make UserRole available to the template + UserRole = UserRole; constructor(public dialog: MatDialog) { } diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts index 1d62bf3ea2737e985aceb559b6377215f2767aca..8267b2d4e90f39e8c3bcde3a4288f0a9f97b18d4 100644 --- a/src/app/login/login.component.ts +++ b/src/app/login/login.component.ts @@ -4,6 +4,7 @@ import { Router } from '@angular/router'; import { NotificationService } from '../notification.service'; import { ErrorStateMatcher } from '@angular/material'; import { FormControl, FormGroupDirective, NgForm, ReactiveFormsModule, Validators } from '@angular/forms'; +import { UserRole } from '../user-roles.enum'; export class LoginErrorStateMatcher implements ErrorStateMatcher { isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { @@ -18,8 +19,7 @@ export class LoginErrorStateMatcher implements ErrorStateMatcher { styleUrls: ['./login.component.scss'] }) export class LoginComponent implements OnInit { - - @Input() isCreator: boolean; + @Input() role: UserRole; usernameFormControl = new FormControl('', [Validators.required]); passwordFormControl = new FormControl('', [Validators.required]); @@ -39,7 +39,7 @@ export class LoginComponent implements OnInit { password = password.trim(); if (username !== '' && password !== '') { - this.authenticationService.login(username, password, this.isCreator).subscribe(loginSuccessful => this.checkLogin(loginSuccessful)); + this.authenticationService.login(username, password, this.role).subscribe(loginSuccessful => this.checkLogin(loginSuccessful)); } else { this.notificationService.show('Login failed!'); } @@ -48,7 +48,7 @@ export class LoginComponent implements OnInit { private checkLogin(loginSuccessful: boolean) { if (loginSuccessful) { this.notificationService.show('Login successful!'); - if (this.isCreator) { + if (this.role === UserRole.CREATOR) { this.router.navigate(['creator']); } else { this.router.navigate(['participant']); diff --git a/src/app/user-roles.enum.ts b/src/app/user-roles.enum.ts new file mode 100644 index 0000000000000000000000000000000000000000..71cc81615fd88fadfe5fb63677983a1c5e4d3714 --- /dev/null +++ b/src/app/user-roles.enum.ts @@ -0,0 +1,4 @@ +export enum UserRole { + PARTICIPANT, + CREATOR +} diff --git a/src/app/user.ts b/src/app/user.ts index 3283b2d7981295529a7e3d3c96058896fea06724..e9d2a88612425cdf57eb5b6b0c43f42b40a7adc1 100644 --- a/src/app/user.ts +++ b/src/app/user.ts @@ -1,13 +1,15 @@ +import { UserRole } from './user-roles.enum'; + export class User { id: number; name: string; email: string; - isCreator: boolean; + role: UserRole; - constructor(id: number, name: string, email: string, isCreator: boolean) { + constructor(id: number, name: string, email: string, role: UserRole) { this.id = id; this.name = name; this.email = email; - this.isCreator = isCreator; + this.role = role; } }