From 18a37e29962cb4f8dd11426645b72dfa33cfca53 Mon Sep 17 00:00:00 2001 From: jackiettran <41605212+jackiettran@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:11:57 -0500 Subject: [PATCH] lat lon validation --- backend/middleware/validation.js | 33 +++++++++++++++++++++++++++++++- backend/routes/forum.js | 3 ++- backend/routes/items.js | 7 ++++--- backend/routes/users.js | 5 +++-- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/backend/middleware/validation.js b/backend/middleware/validation.js index 8235b6f..b2ca0b2 100644 --- a/backend/middleware/validation.js +++ b/backend/middleware/validation.js @@ -1,4 +1,4 @@ -const { body, validationResult } = require("express-validator"); +const { body, query, validationResult } = require("express-validator"); const DOMPurify = require("dompurify"); const { JSDOM } = require("jsdom"); @@ -316,6 +316,35 @@ const validateFeedback = [ handleValidationErrors, ]; +// Coordinate validation for query parameters (e.g., location search) +const validateCoordinatesQuery = [ + query("lat") + .optional() + .isFloat({ min: -90, max: 90 }) + .withMessage("Latitude must be between -90 and 90"), + query("lng") + .optional() + .isFloat({ min: -180, max: 180 }) + .withMessage("Longitude must be between -180 and 180"), + query("radius") + .optional() + .isFloat({ min: 0.1, max: 100 }) + .withMessage("Radius must be between 0.1 and 100 miles"), + handleValidationErrors, +]; + +// Coordinate validation for body parameters (e.g., user addresses, forum posts) +const validateCoordinatesBody = [ + body("latitude") + .optional() + .isFloat({ min: -90, max: 90 }) + .withMessage("Latitude must be between -90 and 90"), + body("longitude") + .optional() + .isFloat({ min: -180, max: 180 }) + .withMessage("Longitude must be between -180 and 180"), +]; + module.exports = { sanitizeInput, handleValidationErrors, @@ -328,4 +357,6 @@ module.exports = { validateResetPassword, validateVerifyResetToken, validateFeedback, + validateCoordinatesQuery, + validateCoordinatesBody, }; diff --git a/backend/routes/forum.js b/backend/routes/forum.js index e885b70..be54830 100644 --- a/backend/routes/forum.js +++ b/backend/routes/forum.js @@ -2,6 +2,7 @@ const express = require('express'); const { Op } = require('sequelize'); const { ForumPost, ForumComment, PostTag, User } = require('../models'); const { authenticateToken, requireAdmin, optionalAuth } = require('../middleware/auth'); +const { validateCoordinatesBody, handleValidationErrors } = require('../middleware/validation'); const logger = require('../utils/logger'); const emailServices = require('../services/email'); const googleMapsService = require('../services/googleMapsService'); @@ -239,7 +240,7 @@ router.get('/posts/:id', optionalAuth, async (req, res, next) => { }); // POST /api/forum/posts - Create new post -router.post('/posts', authenticateToken, async (req, res, next) => { +router.post('/posts', authenticateToken, ...validateCoordinatesBody, handleValidationErrors, async (req, res, next) => { try { // Require email verification if (!req.user.isVerified) { diff --git a/backend/routes/items.js b/backend/routes/items.js index 3439b10..1c740ee 100644 --- a/backend/routes/items.js +++ b/backend/routes/items.js @@ -2,6 +2,7 @@ const express = require("express"); const { Op, Sequelize } = require("sequelize"); const { Item, User, Rental, sequelize } = require("../models"); // Import from models/index.js to get models with associations const { authenticateToken, requireVerifiedEmail, requireAdmin, optionalAuth } = require("../middleware/auth"); +const { validateCoordinatesQuery, validateCoordinatesBody, handleValidationErrors } = require("../middleware/validation"); const logger = require("../utils/logger"); const { validateS3Keys } = require("../utils/s3KeyValidator"); const { IMAGE_LIMITS } = require("../config/imageLimits"); @@ -53,7 +54,7 @@ function extractAllowedFields(body) { return result; } -router.get("/", async (req, res, next) => { +router.get("/", validateCoordinatesQuery, async (req, res, next) => { try { const { minPrice, @@ -327,7 +328,7 @@ router.get("/:id", optionalAuth, async (req, res, next) => { } }); -router.post("/", authenticateToken, requireVerifiedEmail, async (req, res, next) => { +router.post("/", authenticateToken, requireVerifiedEmail, ...validateCoordinatesBody, handleValidationErrors, async (req, res, next) => { try { // Extract only allowed fields (prevents mass assignment) const allowedData = extractAllowedFields(req.body); @@ -435,7 +436,7 @@ router.post("/", authenticateToken, requireVerifiedEmail, async (req, res, next) } }); -router.put("/:id", authenticateToken, async (req, res, next) => { +router.put("/:id", authenticateToken, ...validateCoordinatesBody, handleValidationErrors, async (req, res, next) => { try { const item = await Item.findByPk(req.params.id); diff --git a/backend/routes/users.js b/backend/routes/users.js index 2d1ec25..aece226 100644 --- a/backend/routes/users.js +++ b/backend/routes/users.js @@ -1,6 +1,7 @@ const express = require('express'); const { User, UserAddress } = require('../models'); // Import from models/index.js to get models with associations const { authenticateToken, optionalAuth, requireAdmin } = require('../middleware/auth'); +const { validateCoordinatesBody, handleValidationErrors } = require('../middleware/validation'); const logger = require('../utils/logger'); const userService = require('../services/UserService'); const { validateS3Keys } = require('../utils/s3KeyValidator'); @@ -109,7 +110,7 @@ router.get('/addresses', authenticateToken, async (req, res, next) => { } }); -router.post('/addresses', authenticateToken, async (req, res, next) => { +router.post('/addresses', authenticateToken, ...validateCoordinatesBody, handleValidationErrors, async (req, res, next) => { try { // Extract only allowed fields (prevents mass assignment) const allowedData = extractAllowedAddressFields(req.body); @@ -128,7 +129,7 @@ router.post('/addresses', authenticateToken, async (req, res, next) => { } }); -router.put('/addresses/:id', authenticateToken, async (req, res, next) => { +router.put('/addresses/:id', authenticateToken, ...validateCoordinatesBody, handleValidationErrors, async (req, res, next) => { try { // Extract only allowed fields (prevents mass assignment) const allowedData = extractAllowedAddressFields(req.body);