236 lines
6.1 KiB
TypeScript
236 lines
6.1 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { jwtDecode } from 'jwt-decode';
|
|
import { ApplicationMode, ContextData, Edition } from '../../models/context.model';
|
|
import { LoggerService } from 'openvidu-components-angular';
|
|
import {
|
|
AuthMode,
|
|
HttpService,
|
|
OpenViduMeetPermissions,
|
|
ParticipantRole
|
|
} from 'projects/shared-meet-components/src/public-api';
|
|
import { FeatureConfigurationService } from '../feature-configuration/feature-configuration.service';
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
/**
|
|
* Service to manage the context of the application, including embedded mode and token management.
|
|
*/
|
|
export class ContextService {
|
|
private context: ContextData = {
|
|
mode: ApplicationMode.STANDALONE,
|
|
edition: Edition.CE,
|
|
version: '',
|
|
parentDomain: '',
|
|
securityPreferences: undefined,
|
|
openviduLogoUrl: '',
|
|
roomId: '',
|
|
secret: '',
|
|
participantName: '',
|
|
participantToken: '',
|
|
participantRole: ParticipantRole.PUBLISHER,
|
|
participantPermissions: {
|
|
canRecord: false,
|
|
canChat: false,
|
|
canChangeVirtualBackground: false,
|
|
canPublishScreen: false
|
|
},
|
|
recordingPermissions: {
|
|
canRetrieveRecordings: true,
|
|
canDeleteRecordings: false
|
|
},
|
|
leaveRedirectUrl: ''
|
|
};
|
|
|
|
protected log;
|
|
|
|
/**
|
|
* Initializes a new instance of the ContextService class.
|
|
*/
|
|
constructor(
|
|
protected loggerService: LoggerService,
|
|
protected featureConfService: FeatureConfigurationService,
|
|
protected httpService: HttpService
|
|
) {
|
|
this.log = this.loggerService.get('OpenVidu Meet - ContextService');
|
|
}
|
|
|
|
setApplicationMode(mode: ApplicationMode): void {
|
|
this.log.d('Setting application mode', mode);
|
|
this.context.mode = mode;
|
|
}
|
|
|
|
isEmbeddedMode(): boolean {
|
|
return this.context.mode === ApplicationMode.EMBEDDED;
|
|
}
|
|
|
|
isStandaloneMode(): boolean {
|
|
return this.context.mode === ApplicationMode.STANDALONE;
|
|
}
|
|
|
|
getEdition(): Edition {
|
|
return this.context.edition;
|
|
}
|
|
|
|
setVersion(version: string): void {
|
|
this.context.version = version;
|
|
}
|
|
|
|
getVersion(): string {
|
|
return this.context.version;
|
|
}
|
|
|
|
setParentDomain(parentDomain: string): void {
|
|
this.context.parentDomain = parentDomain;
|
|
}
|
|
|
|
getParentDomain(): string {
|
|
return this.context.parentDomain;
|
|
}
|
|
|
|
setOpenViduLogoUrl(openviduLogoUrl: string): void {
|
|
this.context.openviduLogoUrl = openviduLogoUrl;
|
|
}
|
|
|
|
getOpenViduLogoUrl(): string {
|
|
return this.context.openviduLogoUrl;
|
|
}
|
|
|
|
async getAuthModeToAccessRoom(): Promise<AuthMode> {
|
|
await this.getSecurityPreferences();
|
|
return this.context.securityPreferences!.authentication.authModeToAccessRoom;
|
|
}
|
|
|
|
setRoomId(roomId: string): void {
|
|
this.context.roomId = roomId;
|
|
}
|
|
|
|
getRoomId(): string {
|
|
return this.context.roomId;
|
|
}
|
|
|
|
setSecret(secret: string): void {
|
|
this.context.secret = secret;
|
|
}
|
|
|
|
getSecret(): string {
|
|
return this.context.secret;
|
|
}
|
|
|
|
setParticipantName(participantName: string): void {
|
|
this.context.participantName = participantName;
|
|
}
|
|
|
|
getParticipantName(): string {
|
|
return this.context.participantName;
|
|
}
|
|
|
|
/**
|
|
* Sets the participant token in the context and updates feature configuration.
|
|
* @param token - The JWT token to set.
|
|
* @throws Error if the token is invalid or expired.
|
|
*/
|
|
setParticipantTokenAndUpdateContext(token: string): void {
|
|
try {
|
|
const decodedToken = this.getValidDecodedToken(token);
|
|
this.setParticipantToken(token);
|
|
this.setParticipantPermissions(decodedToken.metadata.permissions);
|
|
this.setParticipantRole(decodedToken.metadata.role);
|
|
} catch (error: any) {
|
|
this.log.e('Error setting token in context', error);
|
|
throw new Error('Error setting token', error);
|
|
}
|
|
}
|
|
|
|
setParticipantToken(token: string): void {
|
|
this.context.participantToken = token;
|
|
}
|
|
|
|
getParticipantToken(): string {
|
|
return this.context.participantToken;
|
|
}
|
|
|
|
setParticipantRole(participantRole: ParticipantRole): void {
|
|
this.context.participantRole = participantRole;
|
|
this.featureConfService.setParticipantRole(participantRole);
|
|
}
|
|
|
|
getParticipantRole(): ParticipantRole {
|
|
return this.context.participantRole;
|
|
}
|
|
|
|
isModeratorParticipant(): boolean {
|
|
return this.context.participantRole === ParticipantRole.MODERATOR;
|
|
}
|
|
|
|
setParticipantPermissions(permissions: OpenViduMeetPermissions): void {
|
|
this.context.participantPermissions = permissions;
|
|
this.featureConfService.setParticipantPermissions(permissions);
|
|
}
|
|
|
|
getParticipantPermissions() {
|
|
return this.context.participantPermissions;
|
|
}
|
|
|
|
setRecordingPermissionsFromToken(token: string): void {
|
|
try {
|
|
const decodedToken = this.getValidDecodedToken(token);
|
|
this.context.recordingPermissions = decodedToken.metadata.recordingPermissions;
|
|
this.featureConfService.setRecordingPermissions(decodedToken.metadata.recordingPermissions);
|
|
} catch (error: any) {
|
|
this.log.e('Error setting recording token in context', error);
|
|
throw new Error('Error setting recording token', error);
|
|
}
|
|
}
|
|
|
|
canRetrieveRecordings(): boolean {
|
|
return this.context.recordingPermissions.canRetrieveRecordings;
|
|
}
|
|
|
|
canDeleteRecordings(): boolean {
|
|
return this.context.recordingPermissions.canDeleteRecordings;
|
|
}
|
|
|
|
setLeaveRedirectUrl(leaveRedirectUrl: string): void {
|
|
this.context.leaveRedirectUrl = leaveRedirectUrl;
|
|
}
|
|
|
|
getLeaveRedirectURL(): string {
|
|
return this.context.leaveRedirectUrl;
|
|
}
|
|
|
|
private async getSecurityPreferences() {
|
|
if (!this.context.securityPreferences) {
|
|
try {
|
|
this.context.securityPreferences = await this.httpService.getSecurityPreferences();
|
|
} catch (error) {
|
|
this.log.e('Error getting security preferences', error);
|
|
throw new Error('Error getting security preferences');
|
|
}
|
|
}
|
|
}
|
|
|
|
private getValidDecodedToken(token: string) {
|
|
this.checkIsJWTValid(token);
|
|
const decodedToken: any = jwtDecode(token);
|
|
decodedToken.metadata = JSON.parse(decodedToken.metadata);
|
|
|
|
if (decodedToken.exp && Date.now() >= decodedToken.exp * 1000) {
|
|
throw new Error('Token is expired. Please, request a new one');
|
|
}
|
|
|
|
return decodedToken;
|
|
}
|
|
|
|
private checkIsJWTValid(token: string) {
|
|
if (!token || typeof token !== 'string') {
|
|
throw new Error('Invalid token. Token must be a string');
|
|
}
|
|
|
|
const tokenParts = token.split('.');
|
|
if (tokenParts.length !== 3) {
|
|
throw new Error('Invalid token. Token must be a valid JWT');
|
|
}
|
|
}
|
|
}
|