frontend: enhance HTTP service methods to support custom headers for requests. Update meeting, recording and room services to utilize participant role header.

This commit is contained in:
juancarmore 2025-07-11 01:46:06 +02:00
parent 82592e1f6c
commit 6dd074df57
5 changed files with 49 additions and 21 deletions

View File

@ -1,4 +1,4 @@
import { HttpClient } from '@angular/common/http';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { lastValueFrom } from 'rxjs';
@ -13,20 +13,27 @@ export class HttpService {
constructor(protected http: HttpClient) {}
async getRequest<T>(path: string): Promise<T> {
return lastValueFrom(this.http.get<T>(path));
async getRequest<T>(path: string, headers?: Record<string, string>): Promise<T> {
const options = headers ? { headers: new HttpHeaders(headers) } : {};
return lastValueFrom(this.http.get<T>(path, options));
}
async postRequest<T>(path: string, body: any = {}): Promise<T> {
return lastValueFrom(this.http.post<T>(path, body));
async postRequest<T>(path: string, body: any = {}, headers?: Record<string, string>): Promise<T> {
const options = headers ? { headers: new HttpHeaders(headers) } : {};
return lastValueFrom(this.http.post<T>(path, body, options));
}
async putRequest<T>(path: string, body: any = {}): Promise<T> {
return lastValueFrom(this.http.put<T>(path, body));
async putRequest<T>(path: string, body: any = {}, headers?: Record<string, string>): Promise<T> {
const options = headers ? { headers: new HttpHeaders(headers) } : {};
return lastValueFrom(this.http.put<T>(path, body, options));
}
async deleteRequest<T>(path: string): Promise<T> {
return lastValueFrom(this.http.delete<T>(path, { observe: 'response' })).then((response) => ({
async deleteRequest<T>(path: string, headers?: Record<string, string>): Promise<T> {
const options = {
observe: 'response' as const,
...(headers ? { headers: new HttpHeaders(headers) } : {})
};
return lastValueFrom(this.http.delete<T>(path, options)).then((response) => ({
...(response.body as T),
statusCode: response.status
}));

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { HttpService } from '@lib/services';
import { HttpService, ParticipantTokenService } from '@lib/services';
import { LoggerService } from 'openvidu-components-angular';
@Injectable({
@ -12,7 +12,8 @@ export class MeetingService {
constructor(
protected loggerService: LoggerService,
protected httpService: HttpService
protected httpService: HttpService,
protected participantService: ParticipantTokenService
) {
this.log = this.loggerService.get('OpenVidu Meet - MeetingService');
}
@ -25,7 +26,8 @@ export class MeetingService {
*/
async endMeeting(roomId: string): Promise<any> {
const path = `${this.MEETINGS_API}/${roomId}`;
return this.httpService.deleteRequest(path);
const headers = this.participantService.getParticipantRoleHeader();
return this.httpService.deleteRequest(path, headers);
}
/**
@ -37,7 +39,8 @@ export class MeetingService {
*/
async kickParticipant(roomId: string, participantId: string): Promise<void> {
const path = `${this.MEETINGS_API}/${roomId}/participants/${participantId}`;
await this.httpService.deleteRequest(path);
const headers = this.participantService.getParticipantRoleHeader();
await this.httpService.deleteRequest(path, headers);
this.log.d(`Participant '${participantId}' kicked from room ${roomId}`);
}
}

View File

@ -70,12 +70,15 @@ export class ParticipantTokenService {
protected updateParticipantTokenInfo(token: string): void {
try {
const decodedToken = getValidDecodedToken(token);
const roleAndPermissions = decodedToken.metadata.roles?.find(
(r: { role: ParticipantRole; permissions: ParticipantPermissions }) => r.role === this.participantRole
);
this.currentTokenInfo = {
token: token,
role: decodedToken.metadata.role,
role: roleAndPermissions.role,
permissions: {
livekit: decodedToken.video,
openvidu: decodedToken.metadata.permissions
openvidu: roleAndPermissions.permissions
}
};
this.participantRole = this.currentTokenInfo.role;
@ -108,4 +111,8 @@ export class ParticipantTokenService {
getParticipantPermissions(): ParticipantPermissions | undefined {
return this.currentTokenInfo?.permissions;
}
getParticipantRoleHeader(): Record<string, string> {
return { 'x-participant-role': this.getParticipantRole() };
}
}

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ShareRecordingDialogComponent } from '@lib/components';
import { HttpService } from '@lib/services';
import { HttpService, ParticipantTokenService } from '@lib/services';
import { MeetRecordingFilters, MeetRecordingInfo, RecordingPermissions } from '@lib/typings/ce';
import { getValidDecodedToken } from '@lib/utils';
import { ActionService, LoggerService } from 'openvidu-components-angular';
@ -23,6 +23,7 @@ export class RecordingManagerService {
constructor(
protected loggerService: LoggerService,
private httpService: HttpService,
protected participantService: ParticipantTokenService,
private actionService: ActionService,
protected dialog: MatDialog
) {
@ -37,7 +38,8 @@ export class RecordingManagerService {
*/
async startRecording(roomId: string): Promise<MeetRecordingInfo> {
try {
return this.httpService.postRequest(this.INTERNAL_RECORDINGS_API, { roomId });
const headers = this.participantService.getParticipantRoleHeader();
return this.httpService.postRequest(this.INTERNAL_RECORDINGS_API, { roomId }, headers);
} catch (error) {
console.error('Error starting recording:', error);
throw error;
@ -57,7 +59,8 @@ export class RecordingManagerService {
try {
const path = `${this.INTERNAL_RECORDINGS_API}/${recordingId}/stop`;
return this.httpService.postRequest(path);
const headers = this.participantService.getParticipantRoleHeader();
return this.httpService.postRequest(path, {}, headers);
} catch (error) {
console.error('Error stopping recording:', error);
throw error;

View File

@ -1,5 +1,10 @@
import { Injectable } from '@angular/core';
import { FeatureConfigurationService, HttpService, SessionStorageService } from '@lib/services';
import {
FeatureConfigurationService,
HttpService,
ParticipantTokenService,
SessionStorageService
} from '@lib/services';
import {
MeetRoom,
MeetRoomFilters,
@ -26,6 +31,7 @@ export class RoomService {
constructor(
protected loggerService: LoggerService,
protected httpService: HttpService,
protected participantService: ParticipantTokenService,
protected featureConfService: FeatureConfigurationService,
protected sessionStorageService: SessionStorageService
) {
@ -102,7 +108,8 @@ export class RoomService {
*/
async getRoom(roomId: string): Promise<MeetRoom> {
let path = `${this.ROOMS_API}/${roomId}`;
return this.httpService.getRequest(path);
const headers = this.participantService.getParticipantRoleHeader();
return this.httpService.getRequest(path, headers);
}
/**
@ -148,7 +155,8 @@ export class RoomService {
try {
const path = `${this.INTERNAL_ROOMS_API}/${roomId}/preferences`;
const preferences = await this.httpService.getRequest<MeetRoomPreferences>(path);
const headers = this.participantService.getParticipantRoleHeader();
const preferences = await this.httpService.getRequest<MeetRoomPreferences>(path, headers);
if (!preferences) {
this.log.w('Room preferences not found for roomId:', roomId);