Skip to content

Commit ff8fb46

Browse files
authored
Merge pull request #68 from ADARSHsri2004/feat/server_side_validation
feat: server side validation implemented
2 parents 5263dd2 + 306576f commit ff8fb46

File tree

11 files changed

+197
-46
lines changed

11 files changed

+197
-46
lines changed

backend/package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"nodemailer": "^7.0.10",
2626
"nodemon": "^3.1.10",
2727
"uuid": "^13.0.0",
28+
"zod": "^4.1.12"
2829
"winston": "^3.18.3"
2930
},
3031
"devDependencies": {

backend/src/middleware/auth.middleware.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// src/middleware/validateRequest.ts
2+
import { ZodObject } from "zod";
3+
import { Request, Response, NextFunction } from "express";
4+
5+
const validateRequest =
6+
(schema: ZodObject) =>
7+
(req: Request, res: Response, next: NextFunction) => {
8+
try {
9+
schema.parse({
10+
body: req.body,
11+
query: req.query,
12+
params: req.params,
13+
});
14+
next();
15+
} catch (err) {
16+
return res.status(400).json({
17+
message: "Validation failed",
18+
err
19+
// errors: err.errors.map((e: any) => e.message),
20+
});
21+
}
22+
};
23+
24+
export default validateRequest;

backend/src/routes/cartRoutes.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,23 @@ import {
66
getCart,
77
checkout,
88
} from "../controllers/cart.controller";
9-
import { authenticate } from "../middleware/authMiddleware";
9+
import { protect } from "../middleware/authMiddleware";
10+
import validateRequest from "../middleware/validateRequest";
11+
import {
12+
addItemSchema,
13+
removeItemSchema,
14+
updateQuantitySchema,
15+
getCartSchema,
16+
checkoutSchema,
17+
} from "../validations/cartValidation";
1018

1119
const router: Router = express.Router();
1220

1321
//Protected routes
14-
router.post("/", authenticate, addItem);
15-
router.patch("/:itemId", authenticate, updateQuantity);
16-
router.delete("/:itemId", authenticate, removeItem);
17-
router.get("/", authenticate, getCart);
18-
router.post("/checkout", authenticate, checkout);
22+
router.post("/add", protect, validateRequest(addItemSchema), addItem);
23+
router.patch("/:itemId", protect, validateRequest(updateQuantitySchema), updateQuantity);
24+
router.delete("/:itemId", protect, removeItem);
25+
router.get("/", protect, getCart);
26+
router.post("/checkout", protect, validateRequest(checkoutSchema), checkout);
1927

2028
export default router;

backend/src/routes/product.routes.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,22 @@ import {
77
deleteProduct,
88
} from "../controllers/product.controller";
99

10+
import {
11+
createProductSchema,
12+
updateProductSchema,
13+
getProductByIdSchema,
14+
deleteProductSchema,
15+
getProductsSchema,
16+
} from "../validations/product.validation";
17+
import validateRequest from "../middleware/validateRequest";
1018
const router = Router();
1119

12-
// router.post("/", verifyAuth, createProduct);
13-
router.post("/", createProduct);
14-
router.get("/", getProducts);
15-
router.get("/:id", getProductById);
16-
// router.put("/:id", verifyAuth, updateProduct);
17-
router.put("/:id", updateProduct);
18-
// router.delete("/:id", verifyAuth, deleteProduct);
19-
router.delete("/:id", deleteProduct);
20+
21+
router.post("/", validateRequest(createProductSchema), createProduct);
22+
router.get("/", validateRequest(getProductsSchema), getProducts);
23+
router.get("/:id", validateRequest(getProductByIdSchema), getProductById);
24+
router.put("/:id", validateRequest(updateProductSchema), updateProduct);
25+
router.delete("/:id", validateRequest(deleteProductSchema), deleteProduct);
2026

2127
export default router;
2228

backend/src/routes/user.routes.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
import express from "express";
33
import { register, verifyEmail, login, getMe } from "../controllers/auth.controller";
44
import { protect } from "../middleware/authMiddleware";
5-
5+
import validateRequest from "../middleware/validateRequest";
6+
import {
7+
registerSchema,
8+
loginSchema,
9+
verifyEmailSchema,
10+
} from "../validations/userValidation";
611
const router = express.Router();
712

8-
router.post("/register", register);
9-
router.get("/verify/:token", verifyEmail);
10-
router.post("/login", login);
13+
router.post("/register", validateRequest(registerSchema), register);
14+
router.get("/verify/:token", validateRequest(verifyEmailSchema), verifyEmail);
15+
router.post("/login", validateRequest(loginSchema), login);
1116
router.get("/me", protect, getMe);
1217

1318
export default router;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { z } from "zod";
2+
3+
export const addItemSchema = z.object({
4+
body: z.object({
5+
productId: z.string().min(1, "Product ID is required"),
6+
name: z.string().min(2, "Product name is required"),
7+
price: z.number().positive("Price must be positive"),
8+
quantity: z.number().int().positive("Quantity must be a positive integer"),
9+
}),
10+
});
11+
12+
export const removeItemSchema = z.object({
13+
params: z.object({
14+
itemId: z.string().min(1, "Item ID is required"),
15+
}),
16+
});
17+
18+
export const updateQuantitySchema = z.object({
19+
params: z.object({
20+
itemId: z.string().min(1, "Item ID is required"),
21+
}),
22+
body: z.object({
23+
quantity: z.number().int().positive("Quantity must be a positive integer"),
24+
}),
25+
});
26+
27+
export const getCartSchema = z.object({});
28+
29+
export const checkoutSchema = z.object({});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// src/validations/product.validation.ts
2+
import { z } from "zod";
3+
4+
export const createProductSchema = z.object({
5+
body: z.object({
6+
name: z.string().min(1, "Name is required"),
7+
description: z.string().min(1, "Description is required"),
8+
price: z.number().positive(),
9+
category: z.string().optional(),
10+
stock: z.number().optional(),
11+
}),
12+
});
13+
14+
export const updateProductSchema = z.object({
15+
params: z.object({
16+
id: z.string(),
17+
}),
18+
body: z.object({
19+
name: z.string().optional(),
20+
description: z.string().optional(),
21+
price: z.number().optional(),
22+
category: z.string().optional(),
23+
stock: z.number().optional(),
24+
}),
25+
});
26+
27+
export const getProductByIdSchema = z.object({
28+
params: z.object({
29+
id: z.string(),
30+
}),
31+
});
32+
33+
export const deleteProductSchema = z.object({
34+
params: z.object({
35+
id: z.string(),
36+
}),
37+
});
38+
39+
export const getProductsSchema = z.object({
40+
query: z.object({
41+
search: z.string().optional(),
42+
category: z.string().optional(),
43+
minPrice: z.string().optional(),
44+
maxPrice: z.string().optional(),
45+
sort: z.enum(["asc", "desc", "lowToHigh", "highToLow"]).optional(),
46+
}),
47+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// src/validation/userValidation.ts
2+
import { z } from "zod";
3+
4+
export const registerSchema = z.object({
5+
body: z.object({
6+
name: z
7+
.string()
8+
.min(2, "Name must be at least 2 characters long")
9+
.max(50, "Name too long"),
10+
email: z
11+
.string()
12+
.email("Invalid email address")
13+
.regex(/\.edu$/, "Email must be a college email (.edu)"),
14+
password: z
15+
.string()
16+
.min(6, "Password must be at least 6 characters long")
17+
.max(100, "Password too long"),
18+
}),
19+
});
20+
21+
export const loginSchema = z.object({
22+
body: z.object({
23+
email: z.string().email("Invalid email"),
24+
password: z.string().min(6, "Password must be at least 6 characters long"),
25+
}),
26+
});
27+
28+
export const verifyEmailSchema = z.object({
29+
params: z.object({
30+
token: z.string().min(10, "Invalid verification token"),
31+
}),
32+
});

0 commit comments

Comments
 (0)