diff --git a/frontend/projects/shared-meet-components/src/lib/guards/index.ts b/frontend/projects/shared-meet-components/src/lib/guards/index.ts index 6a41215..5d5b240 100644 --- a/frontend/projects/shared-meet-components/src/lib/guards/index.ts +++ b/frontend/projects/shared-meet-components/src/lib/guards/index.ts @@ -2,4 +2,4 @@ export * from './auth.guard'; export * from './extract-query-params.guard'; export * from './remove-secret.guard'; export * from './run-serially.guard'; -export * from './validate-recording-access.guard'; +export * from './validate-access.guard'; diff --git a/frontend/projects/shared-meet-components/src/lib/guards/validate-recording-access.guard.ts b/frontend/projects/shared-meet-components/src/lib/guards/validate-access.guard.ts similarity index 56% rename from frontend/projects/shared-meet-components/src/lib/guards/validate-recording-access.guard.ts rename to frontend/projects/shared-meet-components/src/lib/guards/validate-access.guard.ts index e55c633..740ee66 100644 --- a/frontend/projects/shared-meet-components/src/lib/guards/validate-recording-access.guard.ts +++ b/frontend/projects/shared-meet-components/src/lib/guards/validate-access.guard.ts @@ -1,10 +1,10 @@ import { inject } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot } from '@angular/router'; import { ErrorReason } from '@lib/models'; -import { NavigationService, RecordingManagerService, RoomService } from '@lib/services'; +import { NavigationService, ParticipantTokenService, RecordingManagerService, RoomService } from '@lib/services'; /** - * Guard to validate the access to recordings. + * Guard to validate the access to recordings of a room by generating a recording token. */ export const validateRecordingAccessGuard: CanActivateFn = async ( _route: ActivatedRouteSnapshot, @@ -32,7 +32,7 @@ export const validateRecordingAccessGuard: CanActivateFn = async ( switch (error.status) { case 400: // Invalid secret - return navigationService.redirectToErrorPage(ErrorReason.INVALID_RECORDING_SECRET); + return navigationService.redirectToErrorPage(ErrorReason.INVALID_ROOM_SECRET); case 403: // Recording access is configured for admins only return navigationService.redirectToErrorPage(ErrorReason.RECORDINGS_ADMIN_ONLY_ACCESS); @@ -44,3 +44,38 @@ export const validateRecordingAccessGuard: CanActivateFn = async ( } } }; + +/** + * Guard to validate access to a room by generating a participant token. + */ +export const validateRoomAccessGuard: CanActivateFn = async ( + _route: ActivatedRouteSnapshot, + _state: RouterStateSnapshot +) => { + const roomService = inject(RoomService); + const participantTokenService = inject(ParticipantTokenService); + const navigationService = inject(NavigationService); + + const roomId = roomService.getRoomId(); + const secret = roomService.getRoomSecret(); + + try { + await participantTokenService.generateToken({ + roomId, + secret + }); + return true; + } catch (error: any) { + console.error('Error generating participant token:', error); + switch (error.status) { + case 400: + // Invalid secret + return navigationService.redirectToErrorPage(ErrorReason.INVALID_ROOM_SECRET); + case 404: + // Room not found + return navigationService.redirectToErrorPage(ErrorReason.INVALID_ROOM); + default: + return navigationService.redirectToErrorPage(ErrorReason.INTERNAL_ERROR); + } + } +}; diff --git a/frontend/projects/shared-meet-components/src/lib/interceptors/http.interceptor.ts b/frontend/projects/shared-meet-components/src/lib/interceptors/http.interceptor.ts index e10902d..83253ff 100644 --- a/frontend/projects/shared-meet-components/src/lib/interceptors/http.interceptor.ts +++ b/frontend/projects/shared-meet-components/src/lib/interceptors/http.interceptor.ts @@ -49,7 +49,7 @@ export const httpInterceptor: HttpInterceptorFn = (req: HttpRequest, ne const secret = roomService.getRoomSecret(); const participantName = participantTokenService.getParticipantName(); - return from(participantTokenService.refreshParticipantToken({ roomId, participantName, secret })).pipe( + return from(participantTokenService.refreshParticipantToken({ roomId, secret, participantName })).pipe( switchMap(() => { console.log('Participant token refreshed'); return next(req); diff --git a/frontend/projects/shared-meet-components/src/lib/routes/base-routes.ts b/frontend/projects/shared-meet-components/src/lib/routes/base-routes.ts index b9d84dc..9213120 100644 --- a/frontend/projects/shared-meet-components/src/lib/routes/base-routes.ts +++ b/frontend/projects/shared-meet-components/src/lib/routes/base-routes.ts @@ -8,7 +8,8 @@ import { extractRoomQueryParamsGuard, removeRoomSecretGuard, runGuardsSerially, - validateRecordingAccessGuard + validateRecordingAccessGuard, + validateRoomAccessGuard } from '@lib/guards'; import { ConsoleComponent, @@ -16,13 +17,13 @@ import { EndMeetingComponent, ErrorComponent, LoginComponent, + MeetingComponent, OverviewComponent, RecordingsComponent, RoomRecordingsComponent, RoomsComponent, RoomWizardComponent, UsersPermissionsComponent, - MeetingComponent, ViewRecordingComponent } from '@lib/pages'; @@ -36,7 +37,12 @@ export const baseRoutes: Routes = [ path: 'room/:room-id', component: MeetingComponent, canActivate: [ - runGuardsSerially(extractRoomQueryParamsGuard, checkParticipantRoleAndAuthGuard, removeRoomSecretGuard) + runGuardsSerially( + extractRoomQueryParamsGuard, + checkParticipantRoleAndAuthGuard, + validateRoomAccessGuard, + removeRoomSecretGuard + ) ] }, { diff --git a/frontend/projects/shared-meet-components/src/lib/services/participant-token.service.ts b/frontend/projects/shared-meet-components/src/lib/services/participant-token.service.ts index fd33387..5066fd1 100644 --- a/frontend/projects/shared-meet-components/src/lib/services/participant-token.service.ts +++ b/frontend/projects/shared-meet-components/src/lib/services/participant-token.service.ts @@ -11,7 +11,7 @@ import { LoggerService } from 'openvidu-components-angular'; export class ParticipantTokenService { protected readonly PARTICIPANTS_API = `${HttpService.INTERNAL_API_PATH_PREFIX}/participants`; - protected participantName: string = ''; + protected participantName?: string; protected participantRole: ParticipantRole = ParticipantRole.PUBLISHER; protected currentTokenInfo?: ParticipantTokenInfo; @@ -29,7 +29,7 @@ export class ParticipantTokenService { this.participantName = participantName; } - getParticipantName(): string { + getParticipantName(): string | undefined { return this.participantName; }