Skip to content

Commit 524a2df

Browse files
authored
Merge pull request #45 from Shreyanshi210205/shreyanshi_zod
feat: add Zod input validation
2 parents 7d6829c + 1d53627 commit 524a2df

File tree

6 files changed

+91
-51
lines changed

6 files changed

+91
-51
lines changed

backend/package-lock.json

Lines changed: 22 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
"jsonwebtoken": "^9.0.2",
2020
"mongodb": "^6.20.0",
2121
"mongoose": "^8.19.2",
22-
"socket.io": "^4.8.1"
22+
"socket.io": "^4.8.1",
23+
"zod": "^4.1.12"
2324
},
2425
"devDependencies": {
2526
"@types/bcryptjs": "^2.4.6",
2627
"@types/express": "^5.0.3",
2728
"@types/jsonwebtoken": "^9.0.10",
2829
"@types/node": "^24.9.1",
30+
"@types/socket.io": "^3.0.1",
2931
"nodemon": "^3.1.10",
3032
"ts-node": "^10.9.2",
3133
"ts-node-dev": "^2.0.0",

backend/src/controllers/authController.ts

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,59 @@ import type { Request, Response, NextFunction } from "express";
22
import bcrypt from "bcryptjs";
33
import User from "../models/userModel.js";
44
import { generateToken } from "../utils/generateToken.js";
5-
import { validateEmail, validatePassword } from "../utils/validateInputs.js";
5+
import { userSchema, loginSchema } from "../utils/validateInputs.js";
66

77
export const registerUser = async (req: Request, res: Response, next: NextFunction) => {
8-
try {
9-
const { name, email, password } = req.body;
8+
try {
9+
const parseResult = userSchema.safeParse(req.body);
1010

11-
if (!name || !email || !password)
12-
return res.status(400).json({ success: false, message: "All fields are required" });
13-
14-
if (!validateEmail(email))
15-
return res.status(400).json({ success: false, message: "Invalid email format" });
11+
if (!parseResult.success) {
12+
return res.status(400).json({ success: false, message: parseResult.error.issues[0]?.message });
13+
}
1614

17-
if (!validatePassword(password))
18-
return res.status(400).json({ success: false, message: "Password must be at least 6 characters" });
15+
const { name, email, password } = parseResult.data;
1916

20-
const existingUser = await User.findOne({ email });
21-
if (existingUser)
22-
return res.status(400).json({ success: false, message: "Email already registered" });
17+
const existingUser = await User.findOne({ email });
18+
if (existingUser)
19+
return res.status(400).json({ success: false, message: "Email already registered" });
2320

24-
const hashedPassword = await bcrypt.hash(password, 10);
25-
const user = await User.create({ name, email, password: hashedPassword });
21+
const hashedPassword = await bcrypt.hash(password, 10);
22+
const user = await User.create({ name, email, password: hashedPassword });
2623

27-
res.status(201).json({
28-
success: true,
29-
message: "User registered successfully",
30-
token: generateToken(user._id.toString()),
31-
});
32-
} catch (err) {
33-
next(err);
34-
}
24+
res.status(201).json({
25+
success: true,
26+
message: "User registered successfully",
27+
token: generateToken(user._id.toString()),
28+
});
29+
} catch (err) {
30+
next(err);
31+
}
3532
};
3633

3734
export const loginUser = async (req: Request, res: Response, next: NextFunction) => {
38-
try {
39-
const { email, password } = req.body;
40-
41-
if (!email || !password)
42-
return res.status(400).json({ success: false, message: "Email and password required" });
43-
44-
const user = await User.findOne({ email });
45-
if (!user)
46-
return res.status(400).json({ success: false, message: "Invalid credentials" });
47-
48-
const isMatch = await bcrypt.compare(password, user.password);
49-
if (!isMatch)
50-
return res.status(400).json({ success: false, message: "Invalid credentials" });
51-
52-
res.json({
53-
success: true,
54-
message: "Login successful",
55-
token: generateToken(user._id.toString()),
56-
});
57-
} catch (err) {
58-
next(err);
35+
try {
36+
const parseResult = loginSchema.safeParse(req.body);
37+
38+
if (!parseResult.success) {
39+
return res.status(400).json({ success: false, message: parseResult.error.issues[0]?.message || "Validation error" });
5940
}
41+
42+
const { email, password } = parseResult.data;
43+
44+
const user = await User.findOne({ email });
45+
if (!user)
46+
return res.status(400).json({ success: false, message: "Invalid credentials" });
47+
48+
const isMatch = await bcrypt.compare(password, user.password);
49+
if (!isMatch)
50+
return res.status(400).json({ success: false, message: "Invalid credentials" });
51+
52+
res.json({
53+
success: true,
54+
message: "Login successful",
55+
token: generateToken(user._id.toString()),
56+
});
57+
} catch (err) {
58+
next(err);
59+
}
6060
};
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1-
export const validateEmail = (email: string) => /\S+@\S+\.\S+/.test(email);
1+
import { z } from "zod";
22

3-
export const validatePassword = (password: string) => password.length >= 6;
3+
export const userSchema = z.object({
4+
name: z.string().min(1, "Name is required"),
5+
email: z.string().refine((val) => /^\S+@\S+\.\S+$/.test(val), {
6+
message: "Invalid email format",
7+
}),
8+
password: z.string().min(6, "Password must be at least 6 characters"),
9+
});
10+
11+
export const loginSchema = z.object({
12+
email: z.string().refine((val) => /^\S+@\S+\.\S+$/.test(val), {
13+
message: "Invalid email format",
14+
}),
15+
password: z.string().min(6, "Password must be at least 6 characters"),
16+
});
17+
18+
export type RegisterInput = z.infer<typeof userSchema>;
19+
export type LoginInput = z.infer<typeof loginSchema>;

frontend/package-lock.json

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

frontend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"autoprefixer": "^10.4.21",
4040
"postcss": "^8.5.6",
4141
"rollup": "^4.52.5",
42-
"tailwindcss": "^4.1.14"
42+
"tailwindcss": "^4.1.14",
43+
"vite": "^7.1.11"
4344
}
4445
}

0 commit comments

Comments
 (0)