import express from 'express'; import * as msgCtrl from '../controllers/messageController.js'; import { authenticate } from '../middleware/auth.js'; const router = express.Router(); // Apply auth to all message routes router.use(authenticate); const TEXT_MIN = 1; const TEXT_MAX = 1000; const ROOM_ID_MAX = 100; const DEFAULT_LIMIT = 50; const MAX_LIMIT = 200; function isValidText(text) { if (typeof text !== 'string') { return false; } if (text.length < TEXT_MIN || text.length > TEXT_MAX) { return false; } return true; } function isValidRoomId(roomId) { if (roomId === undefined || roomId === null) { return true; } if (typeof roomId !== 'string') { return false; } return roomId.length <= ROOM_ID_MAX; } function isValidAuthorId(authorId) { if (typeof authorId !== 'string') { return false; } if (authorId.length < 1) { return false; } return true; } // Search messages (must be before /:id) 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 msgCtrl.searchMessages({ q: q, fields: ['text'], filters: {} }); res.json(results); }); // List messages 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.authorId) { filters.authorId = req.query.authorId; } const messages = await msgCtrl.listMessages({ limit: limit, offset: offset, filters: filters }); res.json(messages); }); // Get message by id router.get('/:id', async function(req, res) { const message = await msgCtrl.getMessageById(req.params.id); if (!message) { return res.status(404).json({ error: 'not_found' }); } res.json(message); }); // Create message router.post('/', async function(req, res) { const authorId = req.body.authorId; const text = req.body.text; const roomId = req.body.roomId; if (!isValidAuthorId(authorId)) { return res.status(400).json({ error: 'invalid_author_id' }); } if (!isValidText(text)) { return res.status(400).json({ error: 'invalid_text' }); } if (!isValidRoomId(roomId)) { return res.status(400).json({ error: 'invalid_room_id' }); } const result = await msgCtrl.createMessage({ authorId: authorId, text: text, roomId: roomId }); if (result.error === 'author_not_found') { return res.status(400).json({ error: 'author_not_found' }); } res.status(201).json(result); }); // Update message router.put('/:id', async function(req, res) { const text = req.body.text; const roomId = req.body.roomId; if (text !== undefined && !isValidText(text)) { return res.status(400).json({ error: 'invalid_text' }); } if (!isValidRoomId(roomId)) { return res.status(400).json({ error: 'invalid_room_id' }); } const updates = {}; if (text !== undefined) { updates.text = text; } if (roomId !== undefined) { updates.roomId = roomId; } const message = await msgCtrl.updateMessage(req.params.id, updates); if (!message) { return res.status(404).json({ error: 'not_found' }); } res.json(message); }); // Delete message router.delete('/:id', async function(req, res) { const ok = await msgCtrl.deleteMessage(req.params.id); if (!ok) { return res.status(404).json({ error: 'not_found' }); } res.status(204).send(); }); export default router;