diff --git a/backend/src/controllers/global-preferences/security-preferences.controller.ts b/backend/src/controllers/global-preferences/security-preferences.controller.ts index 50a1927..92a5c87 100644 --- a/backend/src/controllers/global-preferences/security-preferences.controller.ts +++ b/backend/src/controllers/global-preferences/security-preferences.controller.ts @@ -1,4 +1,4 @@ -import { SecurityPreferencesDTO, UpdateSecurityPreferencesDTO } from '@typings-ce'; +import { SecurityPreferences } from '@typings-ce'; import { Request, Response } from 'express'; import { container } from '../../config/index.js'; import { handleError } from '../../models/error.model.js'; @@ -9,29 +9,15 @@ export const updateSecurityPreferences = async (req: Request, res: Response) => const globalPrefService = container.get(MeetStorageService); logger.verbose(`Updating security preferences: ${JSON.stringify(req.body)}`); - const securityPreferences = req.body as UpdateSecurityPreferencesDTO; + const securityPreferences = req.body as SecurityPreferences; try { const globalPreferences = await globalPrefService.getGlobalPreferences(); + const currentAuth = globalPreferences.securityPreferences.authentication; + const newAuth = securityPreferences.authentication; - if (securityPreferences.roomCreationPolicy) { - globalPreferences.securityPreferences.roomCreationPolicy = { - allowRoomCreation: securityPreferences.roomCreationPolicy.allowRoomCreation, - requireAuthentication: - securityPreferences.roomCreationPolicy.requireAuthentication === undefined - ? globalPreferences.securityPreferences.roomCreationPolicy.requireAuthentication - : securityPreferences.roomCreationPolicy.requireAuthentication - }; - } - - if (securityPreferences.authentication) { - const currentAuth = globalPreferences.securityPreferences.authentication; - const newAuth = securityPreferences.authentication; - - currentAuth.authMode = newAuth.authMode; - currentAuth.method.type = newAuth.method.type; - } - + currentAuth.authMethod = newAuth.authMethod; + currentAuth.authModeToAccessRoom = newAuth.authModeToAccessRoom; await globalPrefService.saveGlobalPreferences(globalPreferences); return res.status(200).json({ message: 'Security preferences updated successfully' }); @@ -48,19 +34,8 @@ export const getSecurityPreferences = async (_req: Request, res: Response) => { try { const preferences = await preferenceService.getGlobalPreferences(); - - // Convert the preferences to the DTO format by removing credentials const securityPreferences = preferences.securityPreferences; - const securityPreferencesDTO: SecurityPreferencesDTO = { - roomCreationPolicy: securityPreferences.roomCreationPolicy, - authentication: { - authMode: securityPreferences.authentication.authMode, - method: { - type: securityPreferences.authentication.method.type - } - } - }; - return res.status(200).json(securityPreferencesDTO); + return res.status(200).json(securityPreferences); } catch (error) { handleError(res, error, 'getting security preferences'); } diff --git a/backend/src/middlewares/participant.middleware.ts b/backend/src/middlewares/participant.middleware.ts index 1c93281..0ee2fc8 100644 --- a/backend/src/middlewares/participant.middleware.ts +++ b/backend/src/middlewares/participant.middleware.ts @@ -25,22 +25,22 @@ export const configureParticipantTokenAuth = async (req: Request, res: Response, return handleError(res, error, 'getting room role by secret'); } - let authMode: AuthMode; + let authModeToAccessRoom: AuthMode; try { const { securityPreferences } = await globalPrefService.getGlobalPreferences(); - authMode = securityPreferences.authentication.authMode; + authModeToAccessRoom = securityPreferences.authentication.authModeToAccessRoom; } catch (error) { return handleError(res, error, 'checking authentication preferences'); } const authValidators = []; - if (authMode === AuthMode.NONE) { + if (authModeToAccessRoom === AuthMode.NONE) { authValidators.push(allowAnonymous); } else { - const isModeratorsOnlyMode = authMode === AuthMode.MODERATORS_ONLY && role === ParticipantRole.MODERATOR; - const isAllUsersMode = authMode === AuthMode.ALL_USERS; + const isModeratorsOnlyMode = authModeToAccessRoom === AuthMode.MODERATORS_ONLY && role === ParticipantRole.MODERATOR; + const isAllUsersMode = authModeToAccessRoom === AuthMode.ALL_USERS; if (isModeratorsOnlyMode || isAllUsersMode) { authValidators.push(tokenAndRoleValidator(UserRole.USER)); diff --git a/backend/src/middlewares/request-validators/preferences-validator.middleware.ts b/backend/src/middlewares/request-validators/preferences-validator.middleware.ts index f2ae982..cfd0a9b 100644 --- a/backend/src/middlewares/request-validators/preferences-validator.middleware.ts +++ b/backend/src/middlewares/request-validators/preferences-validator.middleware.ts @@ -1,11 +1,10 @@ import { - AuthenticationPreferencesDTO, + AuthenticationPreferences, AuthMode, AuthType, - RoomCreationPolicy, - SingleUserAuthDTO, - UpdateSecurityPreferencesDTO, - ValidAuthMethodDTO, + SecurityPreferences, + SingleUserAuth, + ValidAuthMethod, WebhookPreferences } from '@typings-ce'; import { NextFunction, Request, Response } from 'express'; @@ -36,41 +35,20 @@ const AuthModeSchema: z.ZodType = z.enum([AuthMode.NONE, AuthMode.MODE const AuthTypeSchema: z.ZodType = z.enum([AuthType.SINGLE_USER]); -const SingleUserAuthDTOSchema: z.ZodType = z.object({ +const SingleUserAuthSchema: z.ZodType = z.object({ type: AuthTypeSchema }); -const ValidAuthMethodDTOSchema: z.ZodType = SingleUserAuthDTOSchema; +const ValidAuthMethodSchema: z.ZodType = SingleUserAuthSchema; -const AuthenticationPreferencesDTOSchema: z.ZodType = z.object({ - authMode: AuthModeSchema, - method: ValidAuthMethodDTOSchema +const AuthenticationPreferencesSchema: z.ZodType = z.object({ + authMethod: ValidAuthMethodSchema, + authModeToAccessRoom: AuthModeSchema }); -const RoomCreationPolicySchema: z.ZodType = z - .object({ - allowRoomCreation: z.boolean(), - requireAuthentication: z.boolean().optional() - }) - .refine( - (data) => { - // If allowRoomCreation is true, requireAuthentication must be provided - return !data.allowRoomCreation || data.requireAuthentication !== undefined; - }, - { - message: 'requireAuthentication is required when allowRoomCreation is true', - path: ['requireAuthentication'] - } - ); - -const UpdateSecurityPreferencesDTOSchema: z.ZodType = z - .object({ - authentication: AuthenticationPreferencesDTOSchema.optional(), - roomCreationPolicy: RoomCreationPolicySchema.optional() - }) - .refine((data) => Object.keys(data).length > 0, { - message: 'At least one field must be provided for the update' - }); +const SecurityPreferencesSchema: z.ZodType = z.object({ + authentication: AuthenticationPreferencesSchema +}); export const validateWebhookPreferences = (req: Request, res: Response, next: NextFunction) => { const { success, error, data } = WebhookPreferencesSchema.safeParse(req.body); @@ -84,7 +62,7 @@ export const validateWebhookPreferences = (req: Request, res: Response, next: Ne }; export const validateSecurityPreferences = (req: Request, res: Response, next: NextFunction) => { - const { success, error, data } = UpdateSecurityPreferencesDTOSchema.safeParse(req.body); + const { success, error, data } = SecurityPreferencesSchema.safeParse(req.body); if (!success) { return rejectUnprocessableRequest(res, error); diff --git a/backend/src/middlewares/room.middleware.ts b/backend/src/middlewares/room.middleware.ts index 5a2f402..78a2700 100644 --- a/backend/src/middlewares/room.middleware.ts +++ b/backend/src/middlewares/room.middleware.ts @@ -8,39 +8,7 @@ import { rejectRequestFromMeetError } from '../models/error.model.js'; import { MeetStorageService, RoomService } from '../services/index.js'; -import { allowAnonymous, apiKeyValidator, tokenAndRoleValidator, withAuth } from './auth.middleware.js'; - -/** - * Middleware that configures authentication for creating a room based on global settings. - * - * - Admin role and API key authentication methods are always allowed. - * - If room creation is allowed and requires authentication, the user must have a valid token. - * - If room creation is allowed and does not require authentication, anonymous users are allowed. - */ -export const configureCreateRoomAuth = async (req: Request, res: Response, next: NextFunction) => { - const globalPrefService = container.get(MeetStorageService); - let allowRoomCreation: boolean; - let requireAuthentication: boolean | undefined; - - try { - const { securityPreferences } = await globalPrefService.getGlobalPreferences(); - ({ allowRoomCreation, requireAuthentication } = securityPreferences.roomCreationPolicy); - } catch (error) { - return handleError(res, error, 'checking room creation policy'); - } - - const authValidators = [apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)]; - - if (allowRoomCreation) { - if (requireAuthentication) { - authValidators.push(tokenAndRoleValidator(UserRole.USER)); - } else { - authValidators.push(allowAnonymous); - } - } - - return withAuth(...authValidators)(req, res, next); -}; +import { allowAnonymous, tokenAndRoleValidator, withAuth } from './auth.middleware.js'; /** * Middleware that configures authorization for accessing a specific room. @@ -79,7 +47,7 @@ export const configureRoomAuthorization = async (req: Request, res: Response, ne }; /** - * Middleware to configure authentication based on participant role and authentication mode + * Middleware to configure authentication based on participant role and authentication mode to access a room * for generating a token for retrieving/deleting recordings. * * - If the authentication mode is MODERATORS_ONLY and the participant role is MODERATOR, configure user authentication. @@ -114,22 +82,22 @@ export const configureRecordingTokenAuth = async (req: Request, res: Response, n return handleError(res, error, 'getting room role by secret'); } - let authMode: AuthMode; + let authModeToAccessRoom: AuthMode; try { const { securityPreferences } = await storageService.getGlobalPreferences(); - authMode = securityPreferences.authentication.authMode; + authModeToAccessRoom = securityPreferences.authentication.authModeToAccessRoom; } catch (error) { return handleError(res, error, 'checking authentication preferences'); } const authValidators = []; - if (authMode === AuthMode.NONE) { + if (authModeToAccessRoom === AuthMode.NONE) { authValidators.push(allowAnonymous); } else { - const isModeratorsOnlyMode = authMode === AuthMode.MODERATORS_ONLY && role === ParticipantRole.MODERATOR; - const isAllUsersMode = authMode === AuthMode.ALL_USERS; + const isModeratorsOnlyMode = authModeToAccessRoom === AuthMode.MODERATORS_ONLY && role === ParticipantRole.MODERATOR; + const isAllUsersMode = authModeToAccessRoom === AuthMode.ALL_USERS; if (isModeratorsOnlyMode || isAllUsersMode) { authValidators.push(tokenAndRoleValidator(UserRole.USER)); diff --git a/backend/src/routes/room.routes.ts b/backend/src/routes/room.routes.ts index 28ae036..9be50fd 100644 --- a/backend/src/routes/room.routes.ts +++ b/backend/src/routes/room.routes.ts @@ -3,8 +3,8 @@ import bodyParser from 'body-parser'; import { Router } from 'express'; import * as roomCtrl from '../controllers/room.controller.js'; import { + allowAnonymous, apiKeyValidator, - configureCreateRoomAuth, configureRecordingTokenAuth, configureRoomAuthorization, participantTokenValidator, @@ -24,7 +24,12 @@ roomRouter.use(bodyParser.urlencoded({ extended: true })); roomRouter.use(bodyParser.json()); // Room Routes -roomRouter.post('/', configureCreateRoomAuth, withValidRoomOptions, roomCtrl.createRoom); +roomRouter.post( + '/', + withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)), + withValidRoomOptions, + roomCtrl.createRoom +); roomRouter.get( '/', withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)), @@ -56,7 +61,6 @@ export const internalRoomRouter = Router(); internalRoomRouter.use(bodyParser.urlencoded({ extended: true })); internalRoomRouter.use(bodyParser.json()); -// Room preferences internalRoomRouter.put( '/:roomId', withAuth(tokenAndRoleValidator(UserRole.ADMIN)), @@ -64,7 +68,6 @@ internalRoomRouter.put( withValidRoomPreferences, roomCtrl.updateRoomPreferences ); - internalRoomRouter.post( '/:roomId/recording-token', configureRecordingTokenAuth, @@ -72,7 +75,15 @@ internalRoomRouter.post( withValidRoomSecret, roomCtrl.generateRecordingToken ); - -// Roles and permissions -internalRoomRouter.get('/:roomId/roles', withValidRoomId, roomCtrl.getRoomRolesAndPermissions); -internalRoomRouter.get('/:roomId/roles/:secret', withValidRoomId, roomCtrl.getRoomRoleAndPermissions); +internalRoomRouter.get( + '/:roomId/roles', + withAuth(allowAnonymous), + withValidRoomId, + roomCtrl.getRoomRolesAndPermissions +); +internalRoomRouter.get( + '/:roomId/roles/:secret', + withAuth(allowAnonymous), + withValidRoomId, + roomCtrl.getRoomRoleAndPermissions +); diff --git a/typings/src/auth-preferences.ts b/typings/src/auth-preferences.ts index 7d7bc4d..84808e5 100644 --- a/typings/src/auth-preferences.ts +++ b/typings/src/auth-preferences.ts @@ -1,6 +1,6 @@ export interface AuthenticationPreferences { - authMode: AuthMode; - method: ValidAuthMethod; + authMethod: ValidAuthMethod; + authModeToAccessRoom: AuthMode; } /** @@ -33,7 +33,6 @@ export const enum AuthType { */ export interface SingleUserAuth extends AuthMethod { type: AuthType.SINGLE_USER; - credentials: SingleUserCredentials; } /** @@ -57,14 +56,6 @@ export interface SingleUserAuth extends AuthMethod { */ export type ValidAuthMethod = SingleUserAuth /* | MultiUserAuth | OAuthOnlyAuth */; -/** - * Configuration for a single user login method. - */ -export interface SingleUserCredentials { - username: string; - passwordHash: string; -} - /** * Configuration for OAuth authentication. */ @@ -82,13 +73,3 @@ export interface SingleUserCredentials { // GOOGLE = 'google', // GITHUB = 'github' // } - -// DTOs -export interface AuthenticationPreferencesDTO { - authMode: AuthMode; - method: ValidAuthMethodDTO; -} - -export type ValidAuthMethodDTO = SingleUserAuthDTO; - -export type SingleUserAuthDTO = Omit; diff --git a/typings/src/global-preferences.ts b/typings/src/global-preferences.ts index 6b7416d..bce0ffb 100644 --- a/typings/src/global-preferences.ts +++ b/typings/src/global-preferences.ts @@ -1,4 +1,4 @@ -import { AuthenticationPreferences, AuthenticationPreferencesDTO } from './auth-preferences.js'; +import { AuthenticationPreferences } from './auth-preferences.js'; /** * Represents global preferences for OpenVidu Meet. @@ -18,19 +18,4 @@ export interface WebhookPreferences { export interface SecurityPreferences { authentication: AuthenticationPreferences; - roomCreationPolicy: RoomCreationPolicy; - // e2eEncryption: {}; } - -export interface RoomCreationPolicy { - allowRoomCreation: boolean; - requireAuthentication?: boolean; -} - -// DTOs -export interface SecurityPreferencesDTO { - authentication: AuthenticationPreferencesDTO; - roomCreationPolicy: RoomCreationPolicy; -} - -export type UpdateSecurityPreferencesDTO = Partial;