backend: Refactor middlewares and routes to configure authentication
This commit is contained in:
parent
042f7f2fd4
commit
147a334868
@ -104,3 +104,38 @@ export const apiKeyValidator = async (req: Request) => {
|
|||||||
throw errorInvalidApiKey();
|
throw errorInvalidApiKey();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Allow anonymous access
|
||||||
|
export const allowAnonymous = async (req: Request) => {
|
||||||
|
const anonymousUser = {
|
||||||
|
username: 'anonymous',
|
||||||
|
role: UserRole.USER
|
||||||
|
};
|
||||||
|
|
||||||
|
req.session = req.session || {};
|
||||||
|
req.session.user = anonymousUser;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const configureProfileAuth = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const logger = container.get(LoggerService);
|
||||||
|
const globalPrefService = container.get(GlobalPreferencesService);
|
||||||
|
let requireAuthForRoomCreation: boolean;
|
||||||
|
let authMode: AuthMode;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { securityPreferences } = await globalPrefService.getGlobalPreferences();
|
||||||
|
requireAuthForRoomCreation = securityPreferences.roomCreationPolicy.requireAuthentication;
|
||||||
|
authMode = securityPreferences.authentication.authMode;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error checking authentication preferences:' + error);
|
||||||
|
return res.status(500).json({ message: 'Internal server error' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const authValidators = [tokenAndRoleValidator(UserRole.ADMIN)];
|
||||||
|
|
||||||
|
if (requireAuthForRoomCreation || authMode !== AuthMode.NONE) {
|
||||||
|
authValidators.push(tokenAndRoleValidator(UserRole.USER));
|
||||||
|
}
|
||||||
|
|
||||||
|
return withAuth(...authValidators)(req, res, next);
|
||||||
|
};
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
export * from './auth.middleware.js';
|
export * from './auth.middleware.js';
|
||||||
|
export * from './room.middleware.js';
|
||||||
|
export * from './participant.middleware.js';
|
||||||
export * from './recording.middleware.js';
|
export * from './recording.middleware.js';
|
||||||
export * from './content-type.middleware.js';
|
export * from './content-type.middleware.js';
|
||||||
export * from './request-validators/participant-validator.middleware.js';
|
export * from './request-validators/participant-validator.middleware.js';
|
||||||
|
|||||||
67
backend/src/middlewares/participant.middleware.ts
Normal file
67
backend/src/middlewares/participant.middleware.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
import { AuthMode, ParticipantRole, UserRole, TokenOptions } from '@typings-ce';
|
||||||
|
import { container } from '../config/dependency-injector.config.js';
|
||||||
|
import { GlobalPreferencesService, LoggerService, RoomService } from '../services/index.js';
|
||||||
|
import { allowAnonymous, tokenAndRoleValidator, withAuth } from './auth.middleware.js';
|
||||||
|
|
||||||
|
export const configureTokenAuth = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const logger = container.get(LoggerService);
|
||||||
|
const globalPrefService = container.get(GlobalPreferencesService);
|
||||||
|
const roomService = container.get(RoomService);
|
||||||
|
|
||||||
|
let role: ParticipantRole;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { roomName, secret } = req.body as TokenOptions;
|
||||||
|
role = await roomService.getRoomSecretRole(roomName, secret);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error getting room secret role', error);
|
||||||
|
return res.status(500).json({ message: 'Internal server error' });
|
||||||
|
}
|
||||||
|
|
||||||
|
let authMode: AuthMode;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { securityPreferences } = await globalPrefService.getGlobalPreferences();
|
||||||
|
authMode = securityPreferences.authentication.authMode;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error checking authentication preferences', error);
|
||||||
|
return res.status(500).json({ message: 'Internal server error' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const authValidators = [];
|
||||||
|
|
||||||
|
if (authMode === AuthMode.NONE) {
|
||||||
|
authValidators.push(allowAnonymous);
|
||||||
|
} else {
|
||||||
|
const isModeratorsOnlyMode = authMode === AuthMode.MODERATORS_ONLY && role === ParticipantRole.MODERATOR;
|
||||||
|
const isAllUsersMode = authMode === AuthMode.ALL_USERS;
|
||||||
|
|
||||||
|
if (isModeratorsOnlyMode || isAllUsersMode) {
|
||||||
|
authValidators.push(tokenAndRoleValidator(UserRole.USER));
|
||||||
|
} else {
|
||||||
|
authValidators.push(allowAnonymous);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return withAuth(...authValidators)(req, res, next);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const withModeratorPermissions = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const roomName = req.query.roomName as string;
|
||||||
|
const payload = req.session?.tokenClaims;
|
||||||
|
|
||||||
|
if (!payload) {
|
||||||
|
return res.status(403).json({ message: 'Insufficient permissions to access this resource' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const sameRoom = payload.video?.room === roomName;
|
||||||
|
const metadata = JSON.parse(payload.metadata || '{}');
|
||||||
|
const role = metadata.role as ParticipantRole;
|
||||||
|
|
||||||
|
if (!sameRoom || role !== ParticipantRole.MODERATOR) {
|
||||||
|
return res.status(403).json({ message: 'Insufficient permissions to access this resource' });
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
@ -3,23 +3,26 @@ import { Request, Response, NextFunction } from 'express';
|
|||||||
import { OpenViduMeetPermissions, OpenViduMeetRoom } from '@typings-ce';
|
import { OpenViduMeetPermissions, OpenViduMeetRoom } from '@typings-ce';
|
||||||
import { LoggerService } from '../services/logger.service.js';
|
import { LoggerService } from '../services/logger.service.js';
|
||||||
import { RoomService } from '../services/room.service.js';
|
import { RoomService } from '../services/room.service.js';
|
||||||
|
import { RecordingHelper } from '../helpers/recording.helper.js';
|
||||||
|
|
||||||
export const withRecordingEnabledAndCorrectPermissions = async (req: Request, res: Response, next: NextFunction) => {
|
export const withRecordingEnabled = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger = container.get(LoggerService);
|
const logger = container.get(LoggerService);
|
||||||
|
const roomIdParam = req.body.roomId;
|
||||||
|
let roomId: string;
|
||||||
|
|
||||||
// TODO: Think how to get the roomName from the request
|
// Extract roomId from body or from recordingId
|
||||||
const roomName = req.body.roomName;
|
if (roomIdParam) {
|
||||||
const payload = req.session?.tokenClaims;
|
roomId = roomIdParam as string;
|
||||||
|
} else {
|
||||||
if (!payload) {
|
const recordingId = req.params.recordingId as string;
|
||||||
return res.status(403).json({ message: 'Insufficient permissions to access this resource' });
|
({ roomId } = RecordingHelper.extractInfoFromRecordingId(recordingId));
|
||||||
}
|
}
|
||||||
|
|
||||||
let room: OpenViduMeetRoom;
|
let room: OpenViduMeetRoom;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const roomService = container.get(RoomService);
|
const roomService = container.get(RoomService);
|
||||||
room = await roomService.getOpenViduRoom(roomName);
|
room = await roomService.getOpenViduRoom(roomId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Error checking recording preferences:' + error);
|
logger.error('Error checking recording preferences:' + error);
|
||||||
return res.status(403).json({ message: 'Recording is disabled in this room' });
|
return res.status(403).json({ message: 'Recording is disabled in this room' });
|
||||||
@ -37,7 +40,28 @@ export const withRecordingEnabledAndCorrectPermissions = async (req: Request, re
|
|||||||
return res.status(403).json({ message: 'Recording is disabled in this room' });
|
return res.status(403).json({ message: 'Recording is disabled in this room' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const sameRoom = payload.video?.room === roomName;
|
return next();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const withCorrectPermissions = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const roomIdParam = req.body.roomId;
|
||||||
|
let roomId: string;
|
||||||
|
|
||||||
|
// Extract roomId from body or from recordingId
|
||||||
|
if (roomIdParam) {
|
||||||
|
roomId = roomIdParam as string;
|
||||||
|
} else {
|
||||||
|
const recordingId = req.params.recordingId as string;
|
||||||
|
({ roomId } = RecordingHelper.extractInfoFromRecordingId(recordingId));
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = req.session?.tokenClaims;
|
||||||
|
|
||||||
|
if (!payload) {
|
||||||
|
return res.status(403).json({ message: 'Insufficient permissions to access this resource' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const sameRoom = payload.video?.room === roomId;
|
||||||
const metadata = JSON.parse(payload.metadata || '{}');
|
const metadata = JSON.parse(payload.metadata || '{}');
|
||||||
const permissions = metadata.permissions as OpenViduMeetPermissions | undefined;
|
const permissions = metadata.permissions as OpenViduMeetPermissions | undefined;
|
||||||
const canRecord = permissions?.canRecord === true;
|
const canRecord = permissions?.canRecord === true;
|
||||||
|
|||||||
33
backend/src/middlewares/room.middleware.ts
Normal file
33
backend/src/middlewares/room.middleware.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { container } from '../config/dependency-injector.config.js';
|
||||||
|
import { NextFunction, Request, Response } from 'express';
|
||||||
|
import { LoggerService } from '../services/logger.service.js';
|
||||||
|
import { GlobalPreferencesService } from '../services/index.js';
|
||||||
|
import { allowAnonymous, apiKeyValidator, tokenAndRoleValidator, withAuth } from './auth.middleware.js';
|
||||||
|
import { UserRole } from '@typings-ce';
|
||||||
|
|
||||||
|
export const configureRoomAuth = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const logger = container.get(LoggerService);
|
||||||
|
const globalPrefService = container.get(GlobalPreferencesService);
|
||||||
|
let allowRoomCreation: boolean;
|
||||||
|
let requireAuthentication: boolean;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { securityPreferences } = await globalPrefService.getGlobalPreferences();
|
||||||
|
({ allowRoomCreation, requireAuthentication } = securityPreferences.roomCreationPolicy);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error checking room creation policy:' + error);
|
||||||
|
return res.status(500).json({ message: 'Internal server error' });
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
@ -3,8 +3,7 @@ import { Router } from 'express';
|
|||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
import * as authCtrl from '../controllers/auth.controller.js';
|
import * as authCtrl from '../controllers/auth.controller.js';
|
||||||
import rateLimit from 'express-rate-limit';
|
import rateLimit from 'express-rate-limit';
|
||||||
import { tokenAndRoleValidator, withAuth } from '../middlewares/auth.middleware.js';
|
import { configureProfileAuth } from '../middlewares/auth.middleware.js';
|
||||||
import { Role } from '@typings-ce';
|
|
||||||
import { validateLoginRequest } from '../middlewares/request-validators/auth-validator.middleware.js';
|
import { validateLoginRequest } from '../middlewares/request-validators/auth-validator.middleware.js';
|
||||||
|
|
||||||
export const authRouter = Router();
|
export const authRouter = Router();
|
||||||
@ -23,8 +22,4 @@ authRouter.use(bodyParser.json());
|
|||||||
authRouter.post('/login', validateLoginRequest, loginLimiter, authCtrl.login);
|
authRouter.post('/login', validateLoginRequest, loginLimiter, authCtrl.login);
|
||||||
authRouter.post('/logout', authCtrl.logout);
|
authRouter.post('/logout', authCtrl.logout);
|
||||||
authRouter.post('/refresh', authCtrl.refreshToken);
|
authRouter.post('/refresh', authCtrl.refreshToken);
|
||||||
authRouter.get(
|
authRouter.get('/profile', configureProfileAuth, authCtrl.getProfile);
|
||||||
'/profile',
|
|
||||||
withAuth(tokenAndRoleValidator(Role.ADMIN), tokenAndRoleValidator(Role.USER)),
|
|
||||||
authCtrl.getProfile
|
|
||||||
);
|
|
||||||
|
|||||||
@ -5,19 +5,29 @@ import {
|
|||||||
validateParticipantDeletionRequest,
|
validateParticipantDeletionRequest,
|
||||||
validateParticipantTokenRequest
|
validateParticipantTokenRequest
|
||||||
} from '../middlewares/request-validators/participant-validator.middleware.js';
|
} from '../middlewares/request-validators/participant-validator.middleware.js';
|
||||||
|
import { configureTokenAuth, withModeratorPermissions } from '../middlewares/participant.middleware.js';
|
||||||
|
import { participantTokenValidator, withAuth } from '../middlewares/auth.middleware.js';
|
||||||
|
|
||||||
export const internalParticipantsRouter = Router();
|
export const internalParticipantsRouter = Router();
|
||||||
internalParticipantsRouter.use(bodyParser.urlencoded({ extended: true }));
|
internalParticipantsRouter.use(bodyParser.urlencoded({ extended: true }));
|
||||||
internalParticipantsRouter.use(bodyParser.json());
|
internalParticipantsRouter.use(bodyParser.json());
|
||||||
|
|
||||||
internalParticipantsRouter.post('/token', validateParticipantTokenRequest, participantCtrl.generateParticipantToken);
|
internalParticipantsRouter.post(
|
||||||
|
'/token',
|
||||||
|
validateParticipantTokenRequest,
|
||||||
|
configureTokenAuth,
|
||||||
|
participantCtrl.generateParticipantToken
|
||||||
|
);
|
||||||
internalParticipantsRouter.post(
|
internalParticipantsRouter.post(
|
||||||
'/token/refresh',
|
'/token/refresh',
|
||||||
validateParticipantTokenRequest,
|
validateParticipantTokenRequest,
|
||||||
|
configureTokenAuth,
|
||||||
participantCtrl.refreshParticipantToken
|
participantCtrl.refreshParticipantToken
|
||||||
);
|
);
|
||||||
internalParticipantsRouter.delete(
|
internalParticipantsRouter.delete(
|
||||||
'/:participantName',
|
'/:participantName',
|
||||||
|
withAuth(participantTokenValidator),
|
||||||
validateParticipantDeletionRequest,
|
validateParticipantDeletionRequest,
|
||||||
|
withModeratorPermissions,
|
||||||
participantCtrl.deleteParticipant
|
participantCtrl.deleteParticipant
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,16 +1,18 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
import * as recordingCtrl from '../controllers/recording.controller.js';
|
import * as recordingCtrl from '../controllers/recording.controller.js';
|
||||||
import { Role } from '@typings-ce';
|
import { UserRole } from '@typings-ce';
|
||||||
import {
|
import {
|
||||||
withAuth,
|
withAuth,
|
||||||
participantTokenValidator,
|
participantTokenValidator,
|
||||||
tokenAndRoleValidator,
|
tokenAndRoleValidator,
|
||||||
withRecordingEnabledAndCorrectPermissions,
|
withRecordingEnabled,
|
||||||
|
withCorrectPermissions,
|
||||||
withValidGetRecordingsRequest,
|
withValidGetRecordingsRequest,
|
||||||
withValidRecordingBulkDeleteRequest,
|
withValidRecordingBulkDeleteRequest,
|
||||||
withValidRecordingId,
|
withValidRecordingId,
|
||||||
withValidStartRecordingRequest
|
withValidStartRecordingRequest,
|
||||||
|
apiKeyValidator
|
||||||
} from '../middlewares/index.js';
|
} from '../middlewares/index.js';
|
||||||
|
|
||||||
export const recordingRouter = Router();
|
export const recordingRouter = Router();
|
||||||
@ -20,28 +22,44 @@ recordingRouter.use(bodyParser.json());
|
|||||||
// Recording Routes
|
// Recording Routes
|
||||||
recordingRouter.post(
|
recordingRouter.post(
|
||||||
'/',
|
'/',
|
||||||
withAuth(participantTokenValidator),
|
|
||||||
withRecordingEnabledAndCorrectPermissions,
|
|
||||||
withValidStartRecordingRequest,
|
withValidStartRecordingRequest,
|
||||||
|
withRecordingEnabled,
|
||||||
|
withAuth(participantTokenValidator),
|
||||||
|
withCorrectPermissions,
|
||||||
recordingCtrl.startRecording
|
recordingCtrl.startRecording
|
||||||
);
|
);
|
||||||
recordingRouter.put(
|
recordingRouter.put(
|
||||||
'/:recordingId',
|
'/:recordingId',
|
||||||
|
withValidRecordingId,
|
||||||
|
withRecordingEnabled,
|
||||||
withAuth(participantTokenValidator),
|
withAuth(participantTokenValidator),
|
||||||
/* withRecordingEnabledAndCorrectPermissions,*/ withValidRecordingId,
|
withCorrectPermissions,
|
||||||
recordingCtrl.stopRecording
|
recordingCtrl.stopRecording
|
||||||
);
|
);
|
||||||
|
|
||||||
recordingRouter.delete(
|
recordingRouter.delete(
|
||||||
'/:recordingId',
|
'/:recordingId',
|
||||||
withAuth(tokenAndRoleValidator(Role.ADMIN), participantTokenValidator),
|
|
||||||
/*withRecordingEnabledAndCorrectPermissions,*/
|
|
||||||
withValidRecordingId,
|
withValidRecordingId,
|
||||||
|
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)),
|
||||||
recordingCtrl.deleteRecording
|
recordingCtrl.deleteRecording
|
||||||
);
|
);
|
||||||
recordingRouter.get('/:recordingId', withValidRecordingId, recordingCtrl.getRecording);
|
recordingRouter.get(
|
||||||
recordingRouter.get('/', withValidGetRecordingsRequest, recordingCtrl.getRecordings);
|
'/:recordingId',
|
||||||
recordingRouter.delete('/', withValidRecordingBulkDeleteRequest, recordingCtrl.bulkDeleteRecordings);
|
withValidRecordingId,
|
||||||
|
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)),
|
||||||
|
recordingCtrl.getRecording
|
||||||
|
);
|
||||||
|
recordingRouter.get(
|
||||||
|
'/',
|
||||||
|
withValidGetRecordingsRequest,
|
||||||
|
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)),
|
||||||
|
recordingCtrl.getRecordings
|
||||||
|
);
|
||||||
|
recordingRouter.delete(
|
||||||
|
'/',
|
||||||
|
withValidRecordingBulkDeleteRequest,
|
||||||
|
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)),
|
||||||
|
recordingCtrl.bulkDeleteRecordings
|
||||||
|
);
|
||||||
|
|
||||||
// Internal Recording Routes
|
// Internal Recording Routes
|
||||||
export const internalRecordingRouter = Router();
|
export const internalRecordingRouter = Router();
|
||||||
@ -50,7 +68,7 @@ internalRecordingRouter.use(bodyParser.json());
|
|||||||
|
|
||||||
internalRecordingRouter.get(
|
internalRecordingRouter.get(
|
||||||
'/:recordingId/stream',
|
'/:recordingId/stream',
|
||||||
withAuth(participantTokenValidator),
|
withValidRecordingId,
|
||||||
/*withRecordingEnabledAndCorrectPermissions,*/ withValidRecordingId,
|
withAuth(tokenAndRoleValidator(UserRole.ADMIN)),
|
||||||
recordingCtrl.streamRecording
|
recordingCtrl.streamRecording
|
||||||
);
|
);
|
||||||
|
|||||||
@ -6,7 +6,8 @@ import {
|
|||||||
validateGetRoomQueryParams,
|
validateGetRoomQueryParams,
|
||||||
validateRoomRequest
|
validateRoomRequest
|
||||||
} from '../middlewares/request-validators/room-validator.middleware.js';
|
} from '../middlewares/request-validators/room-validator.middleware.js';
|
||||||
import { Role } from '@typings-ce';
|
import { UserRole } from '@typings-ce';
|
||||||
|
import { configureRoomAuth } from '../middlewares/room.middleware.js';
|
||||||
|
|
||||||
export const roomRouter = Router();
|
export const roomRouter = Router();
|
||||||
|
|
||||||
@ -14,25 +15,20 @@ roomRouter.use(bodyParser.urlencoded({ extended: true }));
|
|||||||
roomRouter.use(bodyParser.json());
|
roomRouter.use(bodyParser.json());
|
||||||
|
|
||||||
// Room Routes
|
// Room Routes
|
||||||
roomRouter.post(
|
roomRouter.post('/', configureRoomAuth, validateRoomRequest, roomCtrl.createRoom);
|
||||||
'/',
|
|
||||||
withAuth(apiKeyValidator, tokenAndRoleValidator(Role.ADMIN), tokenAndRoleValidator(Role.USER)),
|
|
||||||
validateRoomRequest,
|
|
||||||
roomCtrl.createRoom
|
|
||||||
);
|
|
||||||
roomRouter.get(
|
roomRouter.get(
|
||||||
'/',
|
'/',
|
||||||
withAuth(apiKeyValidator, tokenAndRoleValidator(Role.ADMIN)),
|
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)),
|
||||||
validateGetRoomQueryParams,
|
validateGetRoomQueryParams,
|
||||||
roomCtrl.getRooms
|
roomCtrl.getRooms
|
||||||
);
|
);
|
||||||
roomRouter.get(
|
roomRouter.get(
|
||||||
'/:roomName',
|
'/:roomName',
|
||||||
withAuth(apiKeyValidator, tokenAndRoleValidator(Role.ADMIN), tokenAndRoleValidator(Role.USER)),
|
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN), tokenAndRoleValidator(UserRole.USER)),
|
||||||
validateGetRoomQueryParams,
|
validateGetRoomQueryParams,
|
||||||
roomCtrl.getRoom
|
roomCtrl.getRoom
|
||||||
);
|
);
|
||||||
roomRouter.delete('/:roomName', withAuth(apiKeyValidator, tokenAndRoleValidator(Role.ADMIN)), roomCtrl.deleteRooms);
|
roomRouter.delete('/:roomName', withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)), roomCtrl.deleteRooms);
|
||||||
|
|
||||||
// Room preferences
|
// Room preferences
|
||||||
roomRouter.put('/', withAuth(apiKeyValidator, tokenAndRoleValidator(Role.ADMIN)), roomCtrl.updateRoomPreferences);
|
roomRouter.put('/', withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)), roomCtrl.updateRoomPreferences);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user