frontend: add recording access guard and update HttpService for recording retrieval

This commit is contained in:
juancarmore 2025-06-14 11:37:44 +02:00
parent d2371120d8
commit a5f283401a
3 changed files with 59 additions and 5 deletions

View File

@ -98,3 +98,42 @@ export const checkParticipantRoleAndAuthGuard: CanActivateFn = async (
// Allow access to the room
return true;
};
export const checkRecordingAuthGuard: CanActivateFn = async (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) => {
const httpService = inject(HttpService);
const navigationService = inject(NavigationService);
const recordingId = route.params['recording-id'];
const secret = route.queryParams['secret'];
if (!secret) {
// If no secret is provided, redirect to the error page
return navigationService.createRedirectionToErrorPage(ErrorReason.MISSING_RECORDING_SECRET);
}
try {
// Attempt to access the recording to check if the secret is valid
await httpService.getRecording(recordingId, secret);
return true;
} catch (error: any) {
console.error('Error checking recording access:', error);
switch (error.status) {
case 400:
// Invalid secret
return navigationService.createRedirectionToErrorPage(ErrorReason.INVALID_RECORDING_SECRET);
case 401:
// Unauthorized access
// Redirect to the login page with query param to redirect back to the recording
return navigationService.createRedirectionToLoginPage(state.url);
case 404:
// Recording not found
return navigationService.createRedirectionToErrorPage(ErrorReason.INVALID_RECORDING);
default:
// Internal error
return navigationService.createRedirectionToErrorPage(ErrorReason.INTERNAL_ERROR);
}
}
};

View File

@ -2,6 +2,7 @@ import { Routes } from '@angular/router';
import {
applicationModeGuard,
checkParticipantRoleAndAuthGuard,
checkRecordingAuthGuard,
checkUserAuthenticatedGuard,
checkUserNotAuthenticatedGuard,
extractRecordingQueryParamsGuard,
@ -20,7 +21,8 @@ import {
RoomFormComponent,
RoomRecordingsComponent,
RoomsComponent,
VideoRoomComponent
VideoRoomComponent,
ViewRecordingComponent
} from '../pages';
export const baseRoutes: Routes = [
@ -95,6 +97,11 @@ export const baseRoutes: Routes = [
)
]
},
{
path: 'recording/:recording-id',
component: ViewRecordingComponent,
canActivate: [runGuardsSerially(applicationModeGuard, checkRecordingAuthGuard)]
},
{ path: 'disconnected', component: DisconnectedComponent },
{ path: 'error', component: ErrorComponent },

View File

@ -110,10 +110,6 @@ export class HttpService {
return this.postRequest(`${this.INTERNAL_API_PATH_PREFIX}/rooms/${roomId}/recording-token`, { secret });
}
getRecordingMediaUrl(recordingId: string): string {
return `${this.API_PATH_PREFIX}/recordings/${recordingId}/media`;
}
getRecordings(filters?: MeetRecordingFilters): Promise<{
recordings: MeetRecordingInfo[];
pagination: {
@ -145,6 +141,18 @@ export class HttpService {
return this.getRequest(path);
}
getRecording(recordingId: string, secret?: string): Promise<MeetRecordingInfo> {
let path = `${this.API_PATH_PREFIX}/recordings/${recordingId}`;
if (secret) {
path += `?secret=${secret}`;
}
return this.getRequest<MeetRecordingInfo>(path);
}
getRecordingMediaUrl(recordingId: string): string {
return `${this.API_PATH_PREFIX}/recordings/${recordingId}/media`;
}
startRecording(roomId: string): Promise<MeetRecordingInfo> {
return this.postRequest(`${this.INTERNAL_API_PATH_PREFIX}/recordings`, { roomId });
}