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 { TokenOptions } from '@typings-ce';
|
||||||
import { OpenViduMeetError } from '../models/index.js';
|
import { OpenViduMeetError } from '../models/index.js';
|
||||||
import { ParticipantService } from '../services/participant.service.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 { MEET_PARTICIPANT_TOKEN_EXPIRATION, PARTICIPANT_TOKEN_COOKIE_NAME } from '../environment.js';
|
||||||
import { getCookieOptions } from '../utils/cookie-utils.js';
|
import { getCookieOptions } from '../utils/cookie-utils.js';
|
||||||
|
|
||||||
export const generateParticipantToken = async (req: Request, res: Response) => {
|
export const generateParticipantToken = async (req: Request, res: Response) => {
|
||||||
const logger = container.get(LoggerService);
|
const logger = container.get(LoggerService);
|
||||||
const tokenOptions: TokenOptions = req.body;
|
const tokenOptions: TokenOptions = req.body;
|
||||||
const { roomName, secret, participantName } = tokenOptions;
|
const { roomName } = tokenOptions;
|
||||||
|
const participantService = container.get(ParticipantService);
|
||||||
|
|
||||||
try {
|
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}`);
|
logger.verbose(`Generating participant token for room ${roomName}`);
|
||||||
|
const token = await participantService.generateOrRefreshParticipantToken(tokenOptions);
|
||||||
const secretRole = await roomService.getRoomSecretRole(roomName, secret);
|
|
||||||
const token = await participantService.generateParticipantToken(secretRole, tokenOptions);
|
|
||||||
|
|
||||||
res.cookie(PARTICIPANT_TOKEN_COOKIE_NAME, token, getCookieOptions('/', MEET_PARTICIPANT_TOKEN_EXPIRATION));
|
res.cookie(PARTICIPANT_TOKEN_COOKIE_NAME, token, getCookieOptions('/', MEET_PARTICIPANT_TOKEN_EXPIRATION));
|
||||||
|
|
||||||
logger.verbose(`Participant token generated for room ${roomName}`);
|
logger.verbose(`Participant token generated for room ${roomName}`);
|
||||||
return res.status(200).json({ token });
|
return res.status(200).json({ token });
|
||||||
} catch (error) {
|
} 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) => {
|
export const deleteParticipant = async (req: Request, res: Response) => {
|
||||||
const logger = container.get(LoggerService);
|
const logger = container.get(LoggerService);
|
||||||
const participantService = container.get(ParticipantService);
|
const participantService = container.get(ParticipantService);
|
||||||
|
|||||||
@ -11,6 +11,7 @@ participantsInternalRouter.use(bodyParser.urlencoded({ extended: true }));
|
|||||||
participantsInternalRouter.use(bodyParser.json());
|
participantsInternalRouter.use(bodyParser.json());
|
||||||
|
|
||||||
participantsInternalRouter.post('/token', validateParticipantTokenRequest, participantCtrl.generateParticipantToken);
|
participantsInternalRouter.post('/token', validateParticipantTokenRequest, participantCtrl.generateParticipantToken);
|
||||||
|
participantsInternalRouter.post('/token/refresh', validateParticipantTokenRequest, participantCtrl.refreshParticipantToken);
|
||||||
|
|
||||||
export const participantsRouter = Router();
|
export const participantsRouter = Router();
|
||||||
participantsRouter.use(bodyParser.urlencoded({ extended: true }));
|
participantsRouter.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|||||||
@ -24,7 +24,6 @@ import {
|
|||||||
import { LoggerService } from './logger.service.js';
|
import { LoggerService } from './logger.service.js';
|
||||||
import {
|
import {
|
||||||
errorLivekitIsNotAvailable,
|
errorLivekitIsNotAvailable,
|
||||||
errorParticipantAlreadyExists,
|
|
||||||
errorParticipantNotFound,
|
errorParticipantNotFound,
|
||||||
errorRoomNotFound,
|
errorRoomNotFound,
|
||||||
internalError
|
internalError
|
||||||
@ -132,17 +131,6 @@ export class LiveKitService {
|
|||||||
role: ParticipantRole
|
role: ParticipantRole
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const { roomName, participantName } = options;
|
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}`);
|
this.logger.info(`Generating token for ${participantName} in room ${roomName}`);
|
||||||
|
|
||||||
const at = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, {
|
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 { LoggerService } from './logger.service.js';
|
||||||
import { ParticipantPermissions, ParticipantRole, TokenOptions } from '@typings-ce';
|
import { ParticipantPermissions, ParticipantRole, TokenOptions } from '@typings-ce';
|
||||||
import { ParticipantInfo } from 'livekit-server-sdk';
|
import { ParticipantInfo } from 'livekit-server-sdk';
|
||||||
|
import { RoomService } from './room.service.js';
|
||||||
|
import { errorParticipantAlreadyExists, errorParticipantNotFound } from '../models/index.js';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ParticipantService {
|
export class ParticipantService {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(LoggerService) protected logger: LoggerService,
|
@inject(LoggerService) protected logger: LoggerService,
|
||||||
|
@inject(RoomService) protected roomService: RoomService,
|
||||||
@inject(LiveKitService) protected livekitService: LiveKitService
|
@inject(LiveKitService) protected livekitService: LiveKitService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async generateParticipantToken(role: ParticipantRole, options: TokenOptions): Promise<string> {
|
async generateOrRefreshParticipantToken(options: TokenOptions, refresh = false): Promise<string> {
|
||||||
const permissions = this.getParticipantPermissions(role, options.roomName);
|
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);
|
return this.livekitService.generateToken(options, permissions, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,6 @@ export class RoomService {
|
|||||||
@inject(LoggerService) protected logger: LoggerService,
|
@inject(LoggerService) protected logger: LoggerService,
|
||||||
@inject(GlobalPreferencesService) protected globalPrefService: GlobalPreferencesService,
|
@inject(GlobalPreferencesService) protected globalPrefService: GlobalPreferencesService,
|
||||||
@inject(LiveKitService) protected livekitService: LiveKitService,
|
@inject(LiveKitService) protected livekitService: LiveKitService,
|
||||||
@inject(ParticipantService) protected participantService: ParticipantService,
|
|
||||||
@inject(SystemEventService) protected systemEventService: SystemEventService,
|
@inject(SystemEventService) protected systemEventService: SystemEventService,
|
||||||
@inject(TaskSchedulerService) protected taskSchedulerService: TaskSchedulerService
|
@inject(TaskSchedulerService) protected taskSchedulerService: TaskSchedulerService
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user