From e45aa91d90e9a86861e3731dad286b5e3d5cb6e6 Mon Sep 17 00:00:00 2001 From: juancarmore Date: Tue, 10 Feb 2026 12:47:51 +0100 Subject: [PATCH] frontend: rename RoomMemberContextService references and implement RoomMemberContextAdapter for improved context management --- .../guards/validate-room-access.guard.ts | 6 ++-- .../pages/meeting/meeting.component.ts | 2 +- .../services/meeting-event-handler.service.ts | 9 +++-- .../meeting/services/meeting-lobby.service.ts | 10 +++--- .../meeting-webcomponent-manager.service.ts | 6 ++-- .../room-recordings.component.ts | 4 +-- .../recordings/services/recording.service.ts | 6 ++-- .../src/lib/domains/room-members/index.ts | 1 + .../room-member-error-handler.service.ts | 12 +++---- .../domains/room-members/providers/index.ts | 1 + .../providers/room-member-context.provider.ts | 12 +++++++ .../services/room-member-context.service.ts | 36 ++++++++++++------- .../src/lib/shared/adapters/index.ts | 1 + .../adapters/room-member-context.adapter.ts | 17 +++++++++ .../src/lib/shared/index.ts | 1 + .../shared/interceptors/http.interceptor.ts | 9 +++-- .../shared/services/token-storage.service.ts | 24 +------------ meet-ce/frontend/src/app/app.config.ts | 2 ++ 18 files changed, 92 insertions(+), 67 deletions(-) create mode 100644 meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/providers/index.ts create mode 100644 meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/providers/room-member-context.provider.ts create mode 100644 meet-ce/frontend/projects/shared-meet-components/src/lib/shared/adapters/index.ts create mode 100644 meet-ce/frontend/projects/shared-meet-components/src/lib/shared/adapters/room-member-context.adapter.ts diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/guards/validate-room-access.guard.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/guards/validate-room-access.guard.ts index 40bd6001..5fcc81f3 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/guards/validate-room-access.guard.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/guards/validate-room-access.guard.ts @@ -33,7 +33,7 @@ export const validateRoomRecordingsAccessGuard: CanActivateFn = async ( * @returns True if access is granted, or UrlTree for redirection */ const validateRoomAccessInternal = async (pageUrl: string, validateRecordingPermissions = false) => { - const roomMemberService = inject(RoomMemberContextService); + const roomMemberContextService = inject(RoomMemberContextService); const navigationService = inject(NavigationService); const meetingContextService = inject(MeetingContextService); @@ -45,14 +45,14 @@ const validateRoomAccessInternal = async (pageUrl: string, validateRecordingPerm } try { - await roomMemberService.generateToken(roomId, { + await roomMemberContextService.generateToken(roomId, { secret, joinMeeting: false }); // Perform recording validation if requested if (validateRecordingPermissions) { - if (!roomMemberService.hasPermission('canRetrieveRecordings')) { + if (!roomMemberContextService.hasPermission('canRetrieveRecordings')) { // If the user does not have permission to retrieve recordings, redirect to the error page return navigationService.redirectToErrorPage(NavigationErrorReason.FORBIDDEN_RECORDING_ACCESS); } diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/pages/meeting/meeting.component.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/pages/meeting/meeting.component.ts index 78172544..e3ad0a22 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/pages/meeting/meeting.component.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/pages/meeting/meeting.component.ts @@ -63,7 +63,7 @@ export class MeetingComponent implements OnInit { protected isMeetingLeft = signal(false); protected features: Signal; - protected participantService = inject(RoomMemberContextService); + protected roomMemberContextService = inject(RoomMemberContextService); protected roomFeatureService = inject(RoomFeatureService); protected ovThemeService = inject(OpenViduThemeService); protected configService = inject(GlobalConfigService); diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-event-handler.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-event-handler.service.ts index 3f27d12d..6637e2e7 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-event-handler.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-event-handler.service.ts @@ -40,7 +40,7 @@ export class MeetingEventHandlerService { protected meetingContext = inject(MeetingContextService); protected roomFeatureService = inject(RoomFeatureService); protected recordingService = inject(RecordingService); - protected roomMemberService = inject(RoomMemberContextService); + protected roomMemberContextService = inject(RoomMemberContextService); protected sessionStorageService = inject(SessionStorageService); protected tokenStorageService = inject(TokenStorageService); protected wcManagerService = inject(MeetingWebComponentManagerService); @@ -158,8 +158,7 @@ export class MeetingEventHandlerService { this.wcManagerService.sendMessageToParent(message); // Clear participant identity and token - this.roomMemberService.clearParticipantIdentity(); - this.tokenStorageService.clearRoomMemberToken(); + this.roomMemberContextService.clearContext(); // Clean up room secret and e2ee key (if any), except on browser unload) if (event.reason !== ParticipantLeftReason.BROWSER_UNLOAD) { @@ -257,7 +256,7 @@ export class MeetingEventHandlerService { const { participantIdentity, newRole, secret } = event; const roomId = this.meetingContext.roomId(); const local = this.meetingContext.localParticipant(); - const participantName = this.roomMemberService.getParticipantName(); + const participantName = this.roomMemberContextService.getParticipantName(); // Check if the role update is for the local participant if (local && participantIdentity === local.identity) { @@ -269,7 +268,7 @@ export class MeetingEventHandlerService { try { // Refresh participant token with new role - await this.roomMemberService.generateToken(roomId, { + await this.roomMemberContextService.generateToken(roomId, { secret, joinMeeting: true, participantName, diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-lobby.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-lobby.service.ts index 894cb50b..8542b248 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-lobby.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-lobby.service.ts @@ -46,7 +46,7 @@ export class MeetingLobbyService { protected meetingService: MeetingService = inject(MeetingService); protected recordingService: RecordingService = inject(RecordingService); protected authService: AuthService = inject(AuthService); - protected roomMemberService: RoomMemberContextService = inject(RoomMemberContextService); + protected roomMemberContextService: RoomMemberContextService = inject(RoomMemberContextService); protected navigationService: NavigationService = inject(NavigationService); protected appCtxService: AppContextService = inject(AppContextService); protected wcManagerService: MeetingWebComponentManagerService = inject(MeetingWebComponentManagerService); @@ -290,7 +290,7 @@ export class MeetingLobbyService { */ protected async checkForRecordings(): Promise { try { - const canRetrieveRecordings = this.roomMemberService.hasPermission('canRetrieveRecordings'); + const canRetrieveRecordings = this.roomMemberContextService.hasPermission('canRetrieveRecordings'); if (!canRetrieveRecordings) { this._state.update((state) => ({ ...state, showRecordingCard: false })); @@ -332,7 +332,7 @@ export class MeetingLobbyService { */ protected async initializeParticipantName(): Promise { // Apply participant name from RoomMemberService if set, otherwise use authenticated username - const currentParticipantName = this.roomMemberService.getParticipantName(); + const currentParticipantName = this.roomMemberContextService.getParticipantName(); const username = await this.authService.getUserName(); const participantName = currentParticipantName || username; @@ -350,7 +350,7 @@ export class MeetingLobbyService { try { const roomId = this._state().roomId; const roomSecret = this.meetingContextService.roomSecret(); - const roomMemberToken = await this.roomMemberService.generateToken( + const roomMemberToken = await this.roomMemberContextService.generateToken( roomId!, { secret: roomSecret, @@ -359,7 +359,7 @@ export class MeetingLobbyService { }, this.e2eeKeyValue() ); - const updatedName = this.roomMemberService.getParticipantName()!; + const updatedName = this.roomMemberContextService.getParticipantName()!; this.setParticipantName(updatedName); this._state.update((state) => ({ ...state, roomMemberToken })); } catch (error: any) { diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-webcomponent-manager.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-webcomponent-manager.service.ts index f97abeed..0d3fa3f7 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-webcomponent-manager.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-webcomponent-manager.service.ts @@ -26,7 +26,7 @@ export class MeetingWebComponentManagerService { protected log; protected readonly meetingContextService = inject(MeetingContextService); - protected readonly roomMemberService = inject(RoomMemberContextService); + protected readonly roomMemberContextService = inject(RoomMemberContextService); protected readonly openviduService = inject(OpenViduService); protected readonly meetingService = inject(MeetingService); protected readonly loggerService = inject(LoggerService); @@ -122,7 +122,7 @@ export class MeetingWebComponentManagerService { switch (command) { case WebComponentCommand.END_MEETING: // Only participants with canEndMeeting permission can end the meeting - if (!this.roomMemberService.hasPermission('canEndMeeting')) { + if (!this.roomMemberContextService.hasPermission('canEndMeeting')) { this.log.w( 'End meeting command received but participant does not have permissions to end the meeting' ); @@ -144,7 +144,7 @@ export class MeetingWebComponentManagerService { break; case WebComponentCommand.KICK_PARTICIPANT: // Only participants with canKickParticipants permission can kick participants - if (!this.roomMemberService.hasPermission('canKickParticipants')) { + if (!this.roomMemberContextService.hasPermission('canKickParticipants')) { this.log.w( 'Kick participant command received but participant does not have permissions to kick participants' ); diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/recordings/pages/room-recordings/room-recordings.component.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/recordings/pages/room-recordings/room-recordings.component.ts index 659b81db..41a24032 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/recordings/pages/room-recordings/room-recordings.component.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/recordings/pages/room-recordings/room-recordings.component.ts @@ -46,7 +46,7 @@ export class RoomRecordingsComponent implements OnInit { protected readonly loggerService = inject(LoggerService); protected readonly recordingService = inject(RecordingService); - protected readonly roomMemberService = inject(RoomMemberContextService); + protected readonly roomMemberContextService = inject(RoomMemberContextService); protected readonly notificationService = inject(NotificationService); protected readonly navigationService = inject(NavigationService); protected readonly meetingContextService = inject(MeetingContextService); @@ -58,7 +58,7 @@ export class RoomRecordingsComponent implements OnInit { async ngOnInit() { this.roomId = this.route.snapshot.paramMap.get('room-id')!; - this.canDeleteRecordings = this.roomMemberService.hasPermission('canDeleteRecordings'); + this.canDeleteRecordings = this.roomMemberContextService.hasPermission('canDeleteRecordings'); // Load recordings const delayLoader = setTimeout(() => { diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/recordings/services/recording.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/recordings/services/recording.service.ts index 82f19309..4fb4b2fa 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/recordings/services/recording.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/recordings/services/recording.service.ts @@ -4,6 +4,7 @@ import { MeetRecordingFilters, MeetRecordingInfo } from '@openvidu-meet/typings' import { LoggerService } from 'openvidu-components-angular'; import { HttpService } from '../../../shared/services/http.service'; import { TokenStorageService } from '../../../shared/services/token-storage.service'; +import { RoomMemberContextService } from '../../room-members/services/room-member-context.service'; import { RecordingShareDialogComponent } from '../components/recording-share-dialog/recording-share-dialog.component'; @Injectable({ @@ -19,6 +20,7 @@ export class RecordingService { protected loggerService: LoggerService, private httpService: HttpService, protected tokenStorageService: TokenStorageService, + protected roomMemberContextService: RoomMemberContextService, protected dialog: MatDialog ) { this.log = this.loggerService.get('OpenVidu Meet - RecordingManagerService'); @@ -130,7 +132,7 @@ export class RecordingService { params.append('accessToken', accessToken); } - const roomMemberToken = this.tokenStorageService.getRoomMemberToken(); + const roomMemberToken = this.roomMemberContextService.getRoomMemberToken(); if (roomMemberToken) { params.append('roomMemberToken', roomMemberToken); } @@ -226,7 +228,7 @@ export class RecordingService { params.append('accessToken', accessToken); } - const roomMemberToken = this.tokenStorageService.getRoomMemberToken(); + const roomMemberToken = this.roomMemberContextService.getRoomMemberToken(); if (roomMemberToken) { params.append('roomMemberToken', roomMemberToken); } diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/index.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/index.ts index 45732831..c287d65a 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/index.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/index.ts @@ -1,2 +1,3 @@ export * from './interceptor-handlers'; +export * from './providers'; export * from './services'; diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/interceptor-handlers/room-member-error-handler.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/interceptor-handlers/room-member-error-handler.service.ts index f10c9ff0..e92364a7 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/interceptor-handlers/room-member-error-handler.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/interceptor-handlers/room-member-error-handler.service.ts @@ -6,7 +6,6 @@ import { HttpErrorHandler, HttpErrorNotifierService } from '../../../shared/services/http-error-notifier.service'; -import { TokenStorageService } from '../../../shared/services/token-storage.service'; import { MeetingContextService } from '../../meeting/services/meeting-context.service'; import { RoomMemberContextService } from '../services/room-member-context.service'; @@ -19,9 +18,8 @@ import { RoomMemberContextService } from '../services/room-member-context.servic providedIn: 'root' }) export class RoomMemberInterceptorErrorHandlerService implements HttpErrorHandler { - private readonly roomMemberService = inject(RoomMemberContextService); + private readonly roomMemberContextService = inject(RoomMemberContextService); private readonly meetingContextService = inject(MeetingContextService); - private readonly tokenStorageService = inject(TokenStorageService); private readonly httpErrorNotifier = inject(HttpErrorNotifierService); /** @@ -77,12 +75,12 @@ export class RoomMemberInterceptorErrorHandlerService implements HttpErrorHandle return throwError(() => originalError); } - const participantName = this.roomMemberService.getParticipantName(); - const participantIdentity = this.roomMemberService.getParticipantIdentity(); + const participantName = this.roomMemberContextService.getParticipantName(); + const participantIdentity = this.roomMemberContextService.getParticipantIdentity(); const joinMeeting = !!participantIdentity; // Grant join permission if identity is set return from( - this.roomMemberService.generateToken(roomId, { + this.roomMemberContextService.generateToken(roomId, { secret, joinMeeting, participantName, @@ -92,7 +90,7 @@ export class RoomMemberInterceptorErrorHandlerService implements HttpErrorHandle switchMap(() => { console.log('Room member token refreshed'); // Update the request with the new token - const newToken = this.tokenStorageService.getRoomMemberToken(); + const newToken = this.roomMemberContextService.getRoomMemberToken(); const updatedRequest = newToken ? originalRequest.clone({ setHeaders: { diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/providers/index.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/providers/index.ts new file mode 100644 index 00000000..8f3fb2c8 --- /dev/null +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/providers/index.ts @@ -0,0 +1 @@ +export * from './room-member-context.provider'; diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/providers/room-member-context.provider.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/providers/room-member-context.provider.ts new file mode 100644 index 00000000..b2ac3a22 --- /dev/null +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/providers/room-member-context.provider.ts @@ -0,0 +1,12 @@ +import { Provider } from '@angular/core'; +import { ROOM_MEMBER_CONTEXT_ADAPTER } from '../../../shared/adapters/room-member-context.adapter'; +import { RoomMemberContextService } from '../services/room-member-context.service'; + +/** + * Provides the RoomMemberContextAdapter using the existing RoomMemberContextService. + * This allows shared guards to use the adapter interface without depending on domain services. + */ +export const ROOM_MEMBER_CONTEXT_ADAPTER_PROVIDER: Provider = { + provide: ROOM_MEMBER_CONTEXT_ADAPTER, + useExisting: RoomMemberContextService +}; diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/services/room-member-context.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/services/room-member-context.service.ts index 164685a1..e5f59a1b 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/services/room-member-context.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/room-members/services/room-member-context.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@angular/core'; import { MeetRoomMemberPermissions, - MeetRoomMemberRole, MeetRoomMemberTokenMetadata, MeetRoomMemberTokenOptions } from '@openvidu-meet/typings'; @@ -17,9 +16,9 @@ import { RoomMemberService } from './room-member.service'; export class RoomMemberContextService { protected readonly PARTICIPANT_NAME_KEY = 'ovMeet-participantName'; + protected roomMemberToken?: string; protected participantName?: string; protected participantIdentity?: string; - protected role: MeetRoomMemberRole = MeetRoomMemberRole.SPEAKER; protected permissions?: MeetRoomMemberPermissions; protected log; @@ -34,6 +33,15 @@ export class RoomMemberContextService { this.log = this.loggerService.get('OpenVidu Meet - RoomMemberContextService'); } + /** + * Retrieves the current room member token. + * + * @returns The room member token, or undefined if not set + */ + getRoomMemberToken(): string | undefined { + return this.roomMemberToken; + } + /** * Sets the participant's display name and stores it in localStorage. * @@ -62,13 +70,6 @@ export class RoomMemberContextService { return this.participantIdentity; } - /** - * Clears the participant's identity. - */ - clearParticipantIdentity(): void { - this.participantIdentity = undefined; - } - /** * Checks if the current room member has a specific permission. * @@ -96,13 +97,13 @@ export class RoomMemberContextService { } const { token } = await this.roomMemberService.generateRoomMemberToken(roomId, tokenOptions); - this.tokenStorageService.setRoomMemberToken(token); + this.roomMemberToken = token; await this.updateContextFromToken(token); return token; } /** - * Updates the room member context (role and permissions) based on the provided token. + * Updates the room member context based on the provided token. * * @param token - The room member token * @throws Error if the token is invalid or expired. @@ -118,15 +119,24 @@ export class RoomMemberContextService { this.participantIdentity = decodedToken.sub; } - this.role = metadata.baseRole; this.permissions = metadata.effectivePermissions; // Update feature configuration - this.roomFeatureService.setRoomMemberRole(this.role); + this.roomFeatureService.setRoomMemberRole(metadata.baseRole); this.roomFeatureService.setRoomMemberPermissions(this.permissions); } catch (error) { this.log.e('Error decoding room member token:', error); throw new Error('Invalid room member token'); } } + + /** + * Clears the room member context, including token, participant info, role, and permissions. + */ + clearContext(): void { + this.roomMemberToken = undefined; + this.participantName = undefined; + this.participantIdentity = undefined; + this.permissions = undefined; + } } diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/adapters/index.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/adapters/index.ts new file mode 100644 index 00000000..bbdf143a --- /dev/null +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/adapters/index.ts @@ -0,0 +1 @@ +export * from './room-member-context.adapter'; diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/adapters/room-member-context.adapter.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/adapters/room-member-context.adapter.ts new file mode 100644 index 00000000..4ca15fe4 --- /dev/null +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/adapters/room-member-context.adapter.ts @@ -0,0 +1,17 @@ +import { InjectionToken } from '@angular/core'; + +/** + * Adapter interface for room member context, providing necessary methods to access room member information. + * This allows shared services to interact with room member context without directly depending on domain services. + */ +export interface RoomMemberContextAdapter { + /** + * Retrieves the current room member token. + */ + getRoomMemberToken(): string; +} + +/** + * Injection token for the RoomMemberContextAdapter + */ +export const ROOM_MEMBER_CONTEXT_ADAPTER = new InjectionToken('ROOM_MEMBER_CONTEXT_ADAPTER'); diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/index.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/index.ts index 3c4c359a..7019bf96 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/index.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/index.ts @@ -1,3 +1,4 @@ +export * from './adapters'; export * from './components'; export * from './guards'; export * from './interceptors'; diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/interceptors/http.interceptor.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/interceptors/http.interceptor.ts index ffb8abca..e1ba461b 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/interceptors/http.interceptor.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/interceptors/http.interceptor.ts @@ -2,6 +2,7 @@ import { HttpErrorResponse, HttpHandlerFn, HttpInterceptorFn, HttpRequest } from import { inject } from '@angular/core'; import { Router } from '@angular/router'; import { catchError, throwError } from 'rxjs'; +import { ROOM_MEMBER_CONTEXT_ADAPTER, RoomMemberContextAdapter } from '../adapters'; import { HttpErrorNotifierService, TokenStorageService } from '../services'; /** @@ -11,7 +12,8 @@ import { HttpErrorNotifierService, TokenStorageService } from '../services'; */ const addAuthHeadersIfNeeded = ( req: HttpRequest, - tokenStorageService: TokenStorageService + tokenStorageService: TokenStorageService, + roomMemberContextService: RoomMemberContextAdapter ): HttpRequest => { const headers: { [key: string]: string } = {}; @@ -22,7 +24,7 @@ const addAuthHeadersIfNeeded = ( } // Add room member token header if available - const roomMemberToken = tokenStorageService.getRoomMemberToken(); + const roomMemberToken = roomMemberContextService.getRoomMemberToken(); if (roomMemberToken) { headers['x-room-member-token'] = `Bearer ${roomMemberToken}`; } @@ -42,12 +44,13 @@ const addAuthHeadersIfNeeded = ( export const httpInterceptor: HttpInterceptorFn = (req: HttpRequest, next: HttpHandlerFn) => { const router = inject(Router); const tokenStorageService = inject(TokenStorageService); + const roomMemberContextService = inject(ROOM_MEMBER_CONTEXT_ADAPTER); const httpErrorNotifier = inject(HttpErrorNotifierService); const pageUrl = router.currentNavigation()?.finalUrl?.toString() || router.url; // Add all authorization headers if tokens exist - req = addAuthHeadersIfNeeded(req, tokenStorageService); + req = addAuthHeadersIfNeeded(req, tokenStorageService, roomMemberContextService); return next(req).pipe( catchError((error: HttpErrorResponse) => { diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/token-storage.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/token-storage.service.ts index 079e775f..1147bc0e 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/token-storage.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/shared/services/token-storage.service.ts @@ -1,8 +1,7 @@ import { Injectable } from '@angular/core'; /** - * Service to manage JWT token storage when using header-based authentication. - * Tokens are stored in localStorage/sessionStorage when authTransportMode is 'header'. + * Service to manage JWT token storage for authentication */ @Injectable({ providedIn: 'root' @@ -10,9 +9,6 @@ import { Injectable } from '@angular/core'; export class TokenStorageService { private readonly ACCESS_TOKEN_KEY = 'ovMeet-accessToken'; private readonly REFRESH_TOKEN_KEY = 'ovMeet-refreshToken'; - private readonly ROOM_MEMBER_TOKEN_KEY = 'ovMeet-roomMemberToken'; - - // ACCESS AND REFRESH TOKEN METHODS // Saves the access token to localStorage setAccessToken(token: string): void { @@ -39,22 +35,4 @@ export class TokenStorageService { localStorage.removeItem(this.ACCESS_TOKEN_KEY); localStorage.removeItem(this.REFRESH_TOKEN_KEY); } - - // ROOM MEMBER TOKEN METHODS - // Uses sessionStorage instead of localStorage to ensure token is not shared across browser tabs - - // Saves the room member token to sessionStorage - setRoomMemberToken(token: string): void { - sessionStorage.setItem(this.ROOM_MEMBER_TOKEN_KEY, token); - } - - // Retrieves the room member token from sessionStorage - getRoomMemberToken(): string | null { - return sessionStorage.getItem(this.ROOM_MEMBER_TOKEN_KEY); - } - - // Removes the room member token from sessionStorage - clearRoomMemberToken(): void { - sessionStorage.removeItem(this.ROOM_MEMBER_TOKEN_KEY); - } } diff --git a/meet-ce/frontend/src/app/app.config.ts b/meet-ce/frontend/src/app/app.config.ts index f56269fb..04c1aa6b 100644 --- a/meet-ce/frontend/src/app/app.config.ts +++ b/meet-ce/frontend/src/app/app.config.ts @@ -16,6 +16,7 @@ import { CustomParticipantModel, httpInterceptor, MeetingLayoutService, + ROOM_MEMBER_CONTEXT_ADAPTER_PROVIDER, RoomMemberInterceptorErrorHandlerService, ThemeService } from '@openvidu-meet/shared-components'; @@ -38,6 +39,7 @@ export const appConfig: ApplicationConfig = { provideAppInitializer(() => inject(RoomMemberInterceptorErrorHandlerService).init()), importProvidersFrom(OpenViduComponentsModule.forRoot(ovComponentsconfig)), { provide: LayoutService, useClass: MeetingLayoutService }, + ROOM_MEMBER_CONTEXT_ADAPTER_PROVIDER, provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(ceRoutes), provideAnimationsAsync(),