From 39c44a17ece7b2ca7f3b88b7376202fedf118a99 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Date: Tue, 18 Mar 2025 23:05:04 +0530 Subject: [PATCH] fixes --- server/controllers/resultController.js | 3 ++ server/middlewares/validation.js | 45 +++++++++++++++++++-- server/postman_collection.json | 55 +++++++++++++++++++------- server/scripts/test-api.js | 9 +++-- 4 files changed, 90 insertions(+), 22 deletions(-) diff --git a/server/controllers/resultController.js b/server/controllers/resultController.js index 1ec540e..21a5c0c 100644 --- a/server/controllers/resultController.js +++ b/server/controllers/resultController.js @@ -6,6 +6,9 @@ exports.getMonthlyResults = async (req, res) => { if (!team || !month) { return res.status(400).json({ error: 'Team and month are required.' }); } + if (!/^\d{4}-\d{2}$/.test(month)) { + return res.status(400).json({ error: 'Invalid month format. Use YYYY-MM.' }); + } const results = await db.query(` SELECT r.result, r.result_date, r.announcement_time FROM results r diff --git a/server/middlewares/validation.js b/server/middlewares/validation.js index 417a66f..e19088d 100644 --- a/server/middlewares/validation.js +++ b/server/middlewares/validation.js @@ -2,7 +2,15 @@ const Joi = require('joi'); exports.validateTeam = (req, res, next) => { const schema = Joi.object({ - name: Joi.string().max(100).required() + name: Joi.string() + .pattern(/^[a-zA-Z0-9\s]+$/) + .max(100) + .required() + .messages({ + 'string.empty': 'Team name is required.', + 'string.pattern.base': 'Team name must only contain alphanumeric characters and spaces.', + 'string.max': 'Team name must not exceed 100 characters.' + }) }); const { error } = schema.validate(req.body); @@ -14,9 +22,38 @@ exports.validateTeam = (req, res, next) => { exports.validateResult = (req, res, next) => { const schema = Joi.object({ - team: Joi.string().max(100).required(), - date: Joi.string().pattern(/^\d{4}-\d{2}-\d{2}$/).required(), - result: Joi.string().max(10).required() + team: Joi.string() + .pattern(/^[a-zA-Z0-9\s]+$/) + .max(100) + .required() + .messages({ + 'string.empty': 'Team name is required.', + 'string.pattern.base': 'Team name must only contain alphanumeric characters and spaces.', + 'string.max': 'Team name must not exceed 100 characters.' + }), + date: Joi.string() + .pattern(/^\d{4}-\d{2}-\d{2}$/) + .required() + .messages({ + 'string.empty': 'Date is required.', + 'string.pattern.base': 'Date must be in YYYY-MM-DD format.' + }), + result: Joi.string() + .pattern(/^[0-9]+$/) + .max(10) + .required() + .messages({ + 'string.empty': 'Result is required.', + 'string.pattern.base': 'Result must only contain numeric characters.', + 'string.max': 'Result must not exceed 10 characters.' + }), + announcement_time: Joi.string() + .pattern(/^\d{2}:\d{2}:\d{2}$/) + .required() + .messages({ + 'string.empty': 'Announcement time is required.', + 'string.pattern.base': 'Announcement time must be in HH:MM:SS format.' + }) }); const { error } = schema.validate(req.body); diff --git a/server/postman_collection.json b/server/postman_collection.json index c68a498..a75b8ea 100644 --- a/server/postman_collection.json +++ b/server/postman_collection.json @@ -55,6 +55,20 @@ } } }, + { + "name": "Get All Teams", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:3000/api/teams", + "protocol": "http", + "host": ["localhost"], + "port": "3000", + "path": ["api", "teams"] + } + } + }, { "name": "Update Result (Admin)", "request": { @@ -126,20 +140,6 @@ } } }, - { - "name": "Get All Teams", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "http://localhost:3000/api/teams", - "protocol": "http", - "host": ["localhost"], - "port": "3000", - "path": ["api", "teams"] - } - } - }, { "name": "Create Team (Admin)", "request": { @@ -269,6 +269,33 @@ ] } } + }, + { + "name": "Publish Result Validation Example", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "Bearer " + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"team\": \"INVALID@TEAM\",\n \"date\": \"2025-03-12\",\n \"result\": \"INVALID_RESULT\",\n \"announcement_time\": \"INVALID_TIME\"\n}" + }, + "url": { + "raw": "http://localhost:3000/admin/results", + "protocol": "http", + "host": ["localhost"], + "port": "3000", + "path": ["admin", "results"] + } + } } ] } diff --git a/server/scripts/test-api.js b/server/scripts/test-api.js index c12ed7f..2d162d8 100644 --- a/server/scripts/test-api.js +++ b/server/scripts/test-api.js @@ -15,7 +15,7 @@ const BASE_URL = 'http://localhost:3000'; console.log('Creating a new team...'); const createTeamResponse = await axios.post( - `${BASE_URL}/api/teams`, + `${BASE_URL}/admin/teams`, { name: 'NEW TEAM' }, @@ -32,7 +32,7 @@ const BASE_URL = 'http://localhost:3000'; console.log('Updating a team...'); const updateTeamResponse = await axios.put( - `${BASE_URL}/api/teams/1`, + `${BASE_URL}/admin/teams/1`, { name: 'UPDATED TEAM' }, @@ -43,7 +43,7 @@ const BASE_URL = 'http://localhost:3000'; console.log('Team updated:', updateTeamResponse.data); console.log('Deleting a team...'); - const deleteTeamResponse = await axios.delete(`${BASE_URL}/api/teams/1`, { + const deleteTeamResponse = await axios.delete(`${BASE_URL}/admin/teams/1`, { headers: { Authorization: `Bearer ${sessionToken}` } }); console.log('Team deleted:', deleteTeamResponse.data); @@ -54,7 +54,8 @@ const BASE_URL = 'http://localhost:3000'; { team: 'NEW TEAM', date: '2025-03-12', - result: '45' + result: '45', + announcement_time: '02:30:00' }, { headers: { Authorization: `Bearer ${sessionToken}` }