diff --git a/backend/src/services/livekit.service.ts b/backend/src/services/livekit.service.ts index 54cc230..da75c21 100644 --- a/backend/src/services/livekit.service.ts +++ b/backend/src/services/livekit.service.ts @@ -174,28 +174,6 @@ export class LiveKitService { } } - async generateToken( - options: TokenOptions, - permissions: ParticipantPermissions, - role: ParticipantRole - ): Promise { - const { roomId, participantName } = options; - this.logger.info(`Generating token for ${participantName} in room ${roomId}`); - - const at = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, { - identity: participantName, - name: participantName, - ttl: MEET_PARTICIPANT_TOKEN_EXPIRATION, - metadata: JSON.stringify({ - livekitUrl: LIVEKIT_URL, - role, - permissions: permissions.openvidu - }) - }); - at.addGrant(permissions.livekit); - return at.toJwt(); - } - async startRoomComposite( roomName: string, output: EncodedFileOutput | StreamOutput, diff --git a/backend/src/services/participant.service.ts b/backend/src/services/participant.service.ts index 5c552f6..aad27cf 100644 --- a/backend/src/services/participant.service.ts +++ b/backend/src/services/participant.service.ts @@ -1,17 +1,16 @@ import { injectable, inject } from 'inversify'; -import { LiveKitService } from './livekit.service.js'; -import { LoggerService } from './logger.service.js'; import { ParticipantPermissions, ParticipantRole, TokenOptions } from '@typings-ce'; import { ParticipantInfo } from 'livekit-server-sdk'; -import { RoomService } from './room.service.js'; import { errorParticipantAlreadyExists, errorParticipantNotFound } from '../models/index.js'; +import { LiveKitService, LoggerService, RoomService, TokenService } from './index.js'; @injectable() export class ParticipantService { constructor( @inject(LoggerService) protected logger: LoggerService, @inject(RoomService) protected roomService: RoomService, - @inject(LiveKitService) protected livekitService: LiveKitService + @inject(LiveKitService) protected livekitService: LiveKitService, + @inject(TokenService) protected tokenService: TokenService ) {} async generateOrRefreshParticipantToken(options: TokenOptions, refresh = false): Promise { @@ -38,7 +37,7 @@ export class ParticipantService { protected async generateParticipantToken(role: ParticipantRole, options: TokenOptions): Promise { const permissions = this.getParticipantPermissions(role, options.roomId); - return this.livekitService.generateToken(options, permissions, role); + return this.tokenService.generateParticipantToken(options, permissions, role); } async getParticipant(roomId: string, participantName: string): Promise { diff --git a/backend/src/services/storage/storage.service.ts b/backend/src/services/storage/storage.service.ts index 77a2035..2774225 100644 --- a/backend/src/services/storage/storage.service.ts +++ b/backend/src/services/storage/storage.service.ts @@ -1,4 +1,4 @@ -import { AuthMode, AuthType, GlobalPreferences, MeetRoom, MeetRoomPreferences } from '@typings-ce'; +import { AuthMode, AuthType, GlobalPreferences, MeetRoom } from '@typings-ce'; import { LoggerService } from '../logger.service.js'; import { StorageProvider } from './storage.interface.js'; import { StorageFactory } from './storage.factory.js'; diff --git a/backend/src/services/token.service.ts b/backend/src/services/token.service.ts index 38c0f02..956de57 100644 --- a/backend/src/services/token.service.ts +++ b/backend/src/services/token.service.ts @@ -2,31 +2,69 @@ import { MEET_ACCESS_TOKEN_EXPIRATION, MEET_REFRESH_TOKEN_EXPIRATION, LIVEKIT_API_KEY, - LIVEKIT_API_SECRET + LIVEKIT_API_SECRET, + MEET_PARTICIPANT_TOKEN_EXPIRATION, + LIVEKIT_URL } from '../environment.js'; -import { injectable } from '../config/dependency-injector.config.js'; -import { AccessToken, AccessTokenOptions, ClaimGrants, TokenVerifier } from 'livekit-server-sdk'; -import { User } from '@typings-ce'; +import { inject, injectable } from '../config/dependency-injector.config.js'; +import { AccessToken, AccessTokenOptions, ClaimGrants, TokenVerifier, VideoGrant } from 'livekit-server-sdk'; +import { ParticipantPermissions, ParticipantRole, TokenOptions, User } from '@typings-ce'; +import { LoggerService } from './index.js'; @injectable() export class TokenService { + constructor(@inject(LoggerService) protected logger: LoggerService) {} + async generateAccessToken(user: User): Promise { - return await this.generateJwtToken(user, MEET_ACCESS_TOKEN_EXPIRATION); - } - - async generateRefreshToken(user: User): Promise { - return await this.generateJwtToken(user, MEET_REFRESH_TOKEN_EXPIRATION); - } - - private async generateJwtToken(user: User, expiration: string): Promise { - const options: AccessTokenOptions = { + const tokenOptions: AccessTokenOptions = { identity: user.username, - ttl: expiration, + ttl: MEET_ACCESS_TOKEN_EXPIRATION, metadata: JSON.stringify({ role: user.role }) }; - const at = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, options); + return await this.generateJwtToken(tokenOptions); + } + + async generateRefreshToken(user: User): Promise { + const tokenOptions: AccessTokenOptions = { + identity: user.username, + ttl: MEET_REFRESH_TOKEN_EXPIRATION, + metadata: JSON.stringify({ + role: user.role + }) + }; + return await this.generateJwtToken(tokenOptions); + } + + async generateParticipantToken( + participantOptions: TokenOptions, + permissions: ParticipantPermissions, + role: ParticipantRole + ): Promise { + const { roomId, participantName } = participantOptions; + this.logger.info(`Generating token for ${participantName} in room ${roomId}`); + + const tokenOptions: AccessTokenOptions = { + identity: participantName, + name: participantName, + ttl: MEET_PARTICIPANT_TOKEN_EXPIRATION, + metadata: JSON.stringify({ + livekitUrl: LIVEKIT_URL, + role, + permissions: permissions.openvidu + }) + }; + return await this.generateJwtToken(tokenOptions, permissions.livekit); + } + + private async generateJwtToken(tokenOptions: AccessTokenOptions, grants?: VideoGrant): Promise { + const at = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, tokenOptions); + + if (grants) { + at.addGrant(grants); + } + return await at.toJwt(); }