import express from 'express'; import * as roomCtrl from '../controllers/roomController.js'; import { authenticate } from '../middleware/auth.js'; const router = express.Router(); // Apply auth to all room routes router.use(authenticate); const NAME_MAX = 100; const DEFAULT_LIMIT = 50; const MAX_LIMIT = 200; function isValidName(name) { if (name === undefined || name === null) { return true; } if (typeof name !== 'string') { return false; } return name.length <= NAME_MAX; } function isValidType(type) { if (type === undefined || type === null) { return true; } if (type !== 'group' && type !== 'direct') { return false; } return true; } function isValidMembers(members) { if (members === undefined || members === null) { return true; } if (!Array.isArray(members)) { return false; } for (let i = 0; i < members.length; i++) { if (typeof members[i] !== 'string') { return false; } } return true; } // Search rooms by name router.get('/search', async function(req, res) { const q = req.query.q; if (typeof q !== 'string' || q.length < 1) { return res.status(400).json({ error: 'invalid_query' }); } const results = await roomCtrl.searchRooms({ q: q }); res.json(results); }); // List rooms with pagination router.get('/', async function(req, res) { let limit = parseInt(req.query.limit, 10); let offset = parseInt(req.query.offset, 10); if (isNaN(limit) || limit < 1) { limit = DEFAULT_LIMIT; } if (limit > MAX_LIMIT) { limit = MAX_LIMIT; } if (isNaN(offset) || offset < 0) { offset = 0; } const filters = {}; if (req.query.type) { filters.type = req.query.type; } if (req.query.memberId) { filters.memberId = req.query.memberId; } const rooms = await roomCtrl.listRooms({ limit: limit, offset: offset, filters: filters }); res.json(rooms); }); // Get room by id router.get('/:id', async function(req, res) { const room = await roomCtrl.getRoomById(req.params.id); if (!room) { return res.status(404).json({ error: 'not_found' }); } res.json(room); }); // Get room messages (chat history) router.get('/:id/messages', async function(req, res) { let limit = parseInt(req.query.limit, 10); let offset = parseInt(req.query.offset, 10); if (isNaN(limit) || limit < 1) { limit = DEFAULT_LIMIT; } if (limit > MAX_LIMIT) { limit = MAX_LIMIT; } if (isNaN(offset) || offset < 0) { offset = 0; } const room = await roomCtrl.getRoomById(req.params.id); if (!room) { return res.status(404).json({ error: 'room_not_found' }); } const messages = await roomCtrl.getRoomMessages(req.params.id, { limit: limit, offset: offset }); res.json(messages); }); // Create room router.post('/', async function(req, res) { const name = req.body.name; const type = req.body.type; const members = req.body.members; if (!isValidName(name)) { return res.status(400).json({ error: 'invalid_name' }); } if (!isValidType(type)) { return res.status(400).json({ error: 'invalid_type' }); } if (!isValidMembers(members)) { return res.status(400).json({ error: 'invalid_members' }); } const result = await roomCtrl.createRoom({ name: name, type: type, members: members }); if (result.error === 'member_not_found') { return res.status(400).json({ error: 'member_not_found', memberId: result.memberId }); } res.status(201).json(result); }); // Update room router.put('/:id', async function(req, res) { const name = req.body.name; const type = req.body.type; if (!isValidName(name)) { return res.status(400).json({ error: 'invalid_name' }); } if (!isValidType(type)) { return res.status(400).json({ error: 'invalid_type' }); } const updates = {}; if (name !== undefined) { updates.name = name; } if (type !== undefined) { updates.type = type; } const room = await roomCtrl.updateRoom(req.params.id, updates); if (!room) { return res.status(404).json({ error: 'not_found' }); } res.json(room); }); // Add member to room router.post('/:id/members', async function(req, res) { const userId = req.body.userId; if (typeof userId !== 'string' || userId.length < 1) { return res.status(400).json({ error: 'invalid_user_id' }); } const room = await roomCtrl.addMember(req.params.id, userId); if (!room) { return res.status(404).json({ error: 'not_found' }); } res.json(room); }); // Remove member from room router.delete('/:id/members/:userId', async function(req, res) { const room = await roomCtrl.removeMember(req.params.id, req.params.userId); if (!room) { return res.status(404).json({ error: 'not_found' }); } res.json(room); }); // Delete room router.delete('/:id', async function(req, res) { const ok = await roomCtrl.deleteRoom(req.params.id); if (!ok) { return res.status(404).json({ error: 'not_found' }); } res.status(204).send(); }); export default router;