From 6641da9a3d66656273d351a701095e68c5f627b1 Mon Sep 17 00:00:00 2001 From: Julien Gautier Date: Mon, 27 Apr 2026 00:04:50 +0200 Subject: [PATCH] feat(validation): replace fieldValidation with express-validator on products and tags Add products.validators.js and tags.validators.js following the same pattern as articles/users. Wire createProductRules, updateProductRules, and createTagRules into their respective routes via the validate middleware. Remove the local fieldValidation helper from both controllers and fix missing return statements on next() calls in products.controller.js. --- src/controllers/products.controller.js | 15 +++-------- src/controllers/tags.controller.js | 7 ----- .../validators/products.validators.js | 27 +++++++++++++++++++ src/middlewares/validators/tags.validators.js | 10 +++++++ src/routes/api/cms/tags.routes.js | 4 ++- src/routes/api/ecommerce/product.routes.js | 6 +++-- 6 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 src/middlewares/validators/products.validators.js create mode 100644 src/middlewares/validators/tags.validators.js diff --git a/src/controllers/products.controller.js b/src/controllers/products.controller.js index 6aea2ff..593ec5a 100644 --- a/src/controllers/products.controller.js +++ b/src/controllers/products.controller.js @@ -134,14 +134,10 @@ module.exports.getProduct = asyncHandler(async (req, res, next) => { module.exports.createProduct = asyncHandler(async (req, res, next) => { const { loggedUser } = req; - fieldValidation(req.body.product.title, next); - fieldValidation(req.body.product.description, next); - fieldValidation(req.body.product.body, next); - const { title, description, body, tagList } = req.body.product; const slugInDB = await Product.findOne({ where: { slug: slug(`${title}`) } }); if (slugInDB) { - next(new ErrorResponse("Title already exists", 400)); + return next(new ErrorResponse("Title already exists", 400)); } const product = await Product.create({ @@ -181,7 +177,7 @@ module.exports.deleteProduct = asyncHandler(async (req, res, next) => { }); if (!product) { - next(new ErrorResponse("Product not found", 404)); + return next(new ErrorResponse("Product not found", 404)); } if (product.authorId !== loggedUser.id) { @@ -203,7 +199,7 @@ module.exports.updateProduct = asyncHandler(async (req, res, next) => { }); if (!product) { - next(new ErrorResponse("Product not found", 404)); + return next(new ErrorResponse("Product not found", 404)); } if (product.authorId !== loggedUser.id) { return next(new ErrorResponse("Unauthorized", 401, "Authentication required.")); @@ -277,8 +273,3 @@ module.exports.deleteFavoriteProduct = asyncHandler(async (req, res, next) => { res.status(200).json({ product }); }); -const fieldValidation = (field, next) => { - if (!field) { - return next(new ErrorResponse(`Missing fields`, 400)); - } -}; diff --git a/src/controllers/tags.controller.js b/src/controllers/tags.controller.js index 21ed105..59b9642 100644 --- a/src/controllers/tags.controller.js +++ b/src/controllers/tags.controller.js @@ -4,8 +4,6 @@ const ErrorResponse = require("../utils/errorResponse"); module.exports.createTag = asyncHandler(async (req, res, next) => { try { - - fieldValidation(req.body.tag.name, next); const { name } = req.body.tag; const tagInDB = await TagService.tagIsInDB(name); if (tagInDB) { @@ -60,8 +58,3 @@ module.exports.getAllTags = asyncHandler(async (req, res, next) => { } }); -const fieldValidation = (field, next) => { - if (!field) { - return next(new ErrorResponse(`Missing fields`, 400)); - } -}; diff --git a/src/middlewares/validators/products.validators.js b/src/middlewares/validators/products.validators.js new file mode 100644 index 0000000..6b7da93 --- /dev/null +++ b/src/middlewares/validators/products.validators.js @@ -0,0 +1,27 @@ +const { body } = require('express-validator'); + +const createProductRules = [ + body('product.title') + .notEmpty().withMessage("can't be blank") + .isLength({ max: 255 }).withMessage('must be at most 255 characters') + .trim(), + body('product.description') + .notEmpty().withMessage("can't be blank") + .isLength({ max: 1000 }).withMessage('must be at most 1000 characters') + .trim(), + body('product.body') + .notEmpty().withMessage("can't be blank"), +]; + +const updateProductRules = [ + body('product.title') + .optional() + .isLength({ max: 255 }).withMessage('must be at most 255 characters') + .trim(), + body('product.description') + .optional() + .isLength({ max: 1000 }).withMessage('must be at most 1000 characters') + .trim(), +]; + +module.exports = { createProductRules, updateProductRules }; diff --git a/src/middlewares/validators/tags.validators.js b/src/middlewares/validators/tags.validators.js new file mode 100644 index 0000000..c89b21d --- /dev/null +++ b/src/middlewares/validators/tags.validators.js @@ -0,0 +1,10 @@ +const { body } = require('express-validator'); + +const createTagRules = [ + body('tag.name') + .notEmpty().withMessage("can't be blank") + .isLength({ max: 50 }).withMessage('must be at most 50 characters') + .trim(), +]; + +module.exports = { createTagRules }; diff --git a/src/routes/api/cms/tags.routes.js b/src/routes/api/cms/tags.routes.js index 4b26e24..409751e 100644 --- a/src/routes/api/cms/tags.routes.js +++ b/src/routes/api/cms/tags.routes.js @@ -1,10 +1,12 @@ const express = require('express'); const { createTag, deleteTag, getAllTags } = require('../../../controllers/tags.controller'); const auth = require('../../../middlewares/auth'); +const validate = require('../../../middlewares/validate'); +const { createTagRules } = require('../../../middlewares/validators/tags.validators'); const tagRouter = express.Router(); -tagRouter.post('/', auth.required, createTag); +tagRouter.post('/', auth.required, createTagRules, validate, createTag); tagRouter.get('/', auth.optional, getAllTags); tagRouter.delete('/:name', auth.required, deleteTag); diff --git a/src/routes/api/ecommerce/product.routes.js b/src/routes/api/ecommerce/product.routes.js index 9e51bb1..ade9081 100644 --- a/src/routes/api/ecommerce/product.routes.js +++ b/src/routes/api/ecommerce/product.routes.js @@ -9,13 +9,15 @@ const { updateProduct, } = require('../../../controllers/products.controller'); const auth = require('../../../middlewares/auth'); +const validate = require('../../../middlewares/validate'); +const { createProductRules, updateProductRules } = require('../../../middlewares/validators/products.validators'); const productRouter = express.Router(); productRouter.get('/', auth.optional, getProducts); -productRouter.post('/', auth.required, createProduct); +productRouter.post('/', auth.required, createProductRules, validate, createProduct); productRouter.get('/:slug', auth.optional, getProduct); -productRouter.put('/:slug', auth.required, updateProduct); +productRouter.put('/:slug', auth.required, updateProductRules, validate, updateProduct); productRouter.delete('/:slug', auth.required, deleteProduct); productRouter.post('/:slug/favorite', auth.required, addFavoriteProduct); productRouter.delete('/:slug/favorite', auth.required, deleteFavoriteProduct);