backend: Add refresh participant token endpoint and refactor token generation logic
This commit is contained in:
parent
cf1c4c5438
commit
c72315d90a
@ -4,34 +4,20 @@ import { LoggerService } from '../services/logger.service.js';
|
||||
import { TokenOptions } from '@typings-ce';
|
||||
import { OpenViduMeetError } from '../models/index.js';
|
||||
import { ParticipantService } from '../services/participant.service.js';
|
||||
import { RoomService } from '../services/room.service.js';
|
||||
import { MEET_PARTICIPANT_TOKEN_EXPIRATION, PARTICIPANT_TOKEN_COOKIE_NAME } from '../environment.js';
|
||||
import { getCookieOptions } from '../utils/cookie-utils.js';
|
||||
|
||||
export const generateParticipantToken = async (req: Request, res: Response) => {
|
||||
const logger = container.get(LoggerService);
|
||||
const tokenOptions: TokenOptions = req.body;
|
||||
const { roomName, secret, participantName } = tokenOptions;
|
||||
const { roomName } = tokenOptions;
|
||||
const participantService = container.get(ParticipantService);
|
||||
|
||||
try {
|
||||
const roomService = container.get(RoomService);
|
||||
const participantService = container.get(ParticipantService);
|
||||
|
||||
// Check if participant with same participantName exists in the room
|
||||
const participantExists = await participantService.participantExists(roomName, participantName);
|
||||
|
||||
if (participantExists) {
|
||||
logger.verbose(`Participant ${participantName} already exists in room ${roomName}`);
|
||||
return res.status(409).json({ message: 'Participant already exists' });
|
||||
}
|
||||
|
||||
logger.verbose(`Generating participant token for room ${roomName}`);
|
||||
|
||||
const secretRole = await roomService.getRoomSecretRole(roomName, secret);
|
||||
const token = await participantService.generateParticipantToken(secretRole, tokenOptions);
|
||||
const token = await participantService.generateOrRefreshParticipantToken(tokenOptions);
|
||||
|
||||
res.cookie(PARTICIPANT_TOKEN_COOKIE_NAME, token, getCookieOptions('/', MEET_PARTICIPANT_TOKEN_EXPIRATION));
|
||||
|
||||
logger.verbose(`Participant token generated for room ${roomName}`);
|
||||
return res.status(200).json({ token });
|
||||
} catch (error) {
|
||||
@ -40,6 +26,25 @@ export const generateParticipantToken = async (req: Request, res: Response) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const refreshParticipantToken = async (req: Request, res: Response) => {
|
||||
const logger = container.get(LoggerService);
|
||||
const tokenOptions: TokenOptions = req.body;
|
||||
const { roomName } = tokenOptions;
|
||||
const participantService = container.get(ParticipantService);
|
||||
|
||||
try {
|
||||
logger.verbose(`Refreshing participant token for room ${roomName}`);
|
||||
const token = await participantService.generateOrRefreshParticipantToken(tokenOptions, true);
|
||||
|
||||
res.cookie(PARTICIPANT_TOKEN_COOKIE_NAME, token, getCookieOptions('/', MEET_PARTICIPANT_TOKEN_EXPIRATION));
|
||||
logger.verbose(`Participant token refreshed for room ${roomName}`);
|
||||
return res.status(200).json({ token });
|
||||
} catch (error) {
|
||||
logger.error(`Error refreshing participant token for room: ${roomName}`);
|
||||
return handleError(res, error);
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteParticipant = async (req: Request, res: Response) => {
|
||||
const logger = container.get(LoggerService);
|
||||
const participantService = container.get(ParticipantService);
|
||||
|
||||
@ -11,6 +11,7 @@ participantsInternalRouter.use(bodyParser.urlencoded({ extended: true }));
|
||||
participantsInternalRouter.use(bodyParser.json());
|
||||
|
||||
participantsInternalRouter.post('/token', validateParticipantTokenRequest, participantCtrl.generateParticipantToken);
|
||||
participantsInternalRouter.post('/token/refresh', validateParticipantTokenRequest, participantCtrl.refreshParticipantToken);
|
||||
|
||||
export const participantsRouter = Router();
|
||||
participantsRouter.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
@ -24,7 +24,6 @@ import {
|
||||
import { LoggerService } from './logger.service.js';
|
||||
import {
|
||||
errorLivekitIsNotAvailable,
|
||||
errorParticipantAlreadyExists,
|
||||
errorParticipantNotFound,
|
||||
errorRoomNotFound,
|
||||
internalError
|
||||
@ -132,17 +131,6 @@ export class LiveKitService {
|
||||
role: ParticipantRole
|
||||
): Promise<string> {
|
||||
const { roomName, participantName } = options;
|
||||
|
||||
try {
|
||||
if (await this.participantExists(roomName, participantName)) {
|
||||
this.logger.error(`Participant ${participantName} already exists in room ${roomName}`);
|
||||
throw errorParticipantAlreadyExists(participantName, roomName);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(`Error checking participant existence, ${JSON.stringify(error)}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.info(`Generating token for ${participantName} in room ${roomName}`);
|
||||
|
||||
const at = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, {
|
||||
|
||||
@ -3,17 +3,39 @@ 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';
|
||||
|
||||
@injectable()
|
||||
export class ParticipantService {
|
||||
constructor(
|
||||
@inject(LoggerService) protected logger: LoggerService,
|
||||
@inject(RoomService) protected roomService: RoomService,
|
||||
@inject(LiveKitService) protected livekitService: LiveKitService
|
||||
) {}
|
||||
|
||||
async generateParticipantToken(role: ParticipantRole, options: TokenOptions): Promise<string> {
|
||||
const permissions = this.getParticipantPermissions(role, options.roomName);
|
||||
async generateOrRefreshParticipantToken(options: TokenOptions, refresh = false): Promise<string> {
|
||||
const { roomName, participantName, secret } = options;
|
||||
|
||||
// Check if participant with same participantName exists in the room
|
||||
const participantExists = await this.participantExists(roomName, participantName);
|
||||
|
||||
if (!refresh && participantExists) {
|
||||
this.logger.verbose(`Participant ${participantName} already exists in room ${roomName}`);
|
||||
throw errorParticipantAlreadyExists(participantName, roomName);
|
||||
}
|
||||
|
||||
if (refresh && !participantExists) {
|
||||
this.logger.verbose(`Participant ${participantName} does not exist in room ${roomName}`);
|
||||
throw errorParticipantNotFound(participantName, roomName);
|
||||
}
|
||||
|
||||
const role = await this.roomService.getRoomSecretRole(roomName, secret);
|
||||
return this.generateParticipantToken(role, options);
|
||||
}
|
||||
|
||||
protected async generateParticipantToken(role: ParticipantRole, options: TokenOptions): Promise<string> {
|
||||
const permissions = this.getParticipantPermissions(role, options.roomName);
|
||||
return this.livekitService.generateToken(options, permissions, role);
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@ export class RoomService {
|
||||
@inject(LoggerService) protected logger: LoggerService,
|
||||
@inject(GlobalPreferencesService) protected globalPrefService: GlobalPreferencesService,
|
||||
@inject(LiveKitService) protected livekitService: LiveKitService,
|
||||
@inject(ParticipantService) protected participantService: ParticipantService,
|
||||
@inject(SystemEventService) protected systemEventService: SystemEventService,
|
||||
@inject(TaskSchedulerService) protected taskSchedulerService: TaskSchedulerService
|
||||
) {}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user