Skip to content

Commit bba280a

Browse files
authored
Merge pull request #36 from Shreyanshi210205/shreyanshi_joi
feat: add Joi validation schemas for authentication and RBAC routes
2 parents 5220c55 + 316566d commit bba280a

File tree

7 files changed

+156
-8
lines changed

7 files changed

+156
-8
lines changed

package-lock.json

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

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"cors": "^2.8.5",
2424
"dotenv": "^17.2.3",
2525
"express": "^5.1.0",
26+
"joi": "^18.0.1",
2627
"jsonwebtoken": "^9.0.2",
2728
"mongoose": "^8.19.1",
2829
"nodemon": "^3.1.10",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export const validateMiddleware = (schema, property = 'body') => {
2+
return (req, res, next) => {
3+
const { error } = schema.validate(req[property]);
4+
if (error) {
5+
return res.status(400).json({
6+
error: error.details[0].message,
7+
});
8+
}
9+
next();
10+
};
11+
};

src/routes/authRoutes.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import express from 'express';
2-
import { registerUser,loginUser, forgotPassword, resetPassword } from '../controllers/authController.js';
3-
import { authMiddleware } from '../middlewares/auth.middleware.js';
2+
import { registerUser,loginUser } from '../controllers/authController.js';
3+
import { registerSchema, loginSchema } from '../validations/authValidation.js';
4+
import {validateMiddleware} from '../middlewares/validate.middleware.js';
5+
46

57
const router = express.Router();
68

7-
router.post('/register', registerUser);
8-
router.post('/login', loginUser);
9+
router.post('/register', validateMiddleware(registerSchema), registerUser);
10+
router.post('/login', validateMiddleware(loginSchema), loginUser);
911
router.post('/forgotPassword',forgotPassword);
1012
router.post('/resetPassword/:token',resetPassword);
1113

src/routes/rbacRoutes.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import express from 'express';
22
import { authMiddleware } from '../middlewares/auth.middleware.js';
33
import { checkRole } from '../middlewares/rbac.middleware.js';
4+
import { adminAccessSchema, userAccessSchema } from '../validations/rbacValidation.js';
5+
import {validateMiddleware} from '../middlewares/validate.middleware.js';
46

57
const router = express.Router();
68

79

8-
router.get('/admin-only', authMiddleware, checkRole(['Admin']), (req, res) => {
10+
router.get('/admin-only', validateMiddleware(adminAccessSchema, 'headers'), authMiddleware, checkRole(['Admin']), (req, res) => {
911
return res.status(200).json({ message: 'Welcome, Admin' });
1012
});
1113

12-
13-
router.get('/user-only', authMiddleware, checkRole(['User']), (req, res) => {
14+
15+
router.get('/user-only', validateMiddleware(userAccessSchema, 'headers'), authMiddleware, checkRole(['User']), (req, res) => {
1416
return res.status(200).json({ message: 'Welcome, User' });
1517
});
1618

src/validations/authValidation.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import Joi from 'joi';
2+
3+
const registerSchema = Joi.object({
4+
username: Joi.string().min(3).max(30).required().messages({
5+
'string.empty': 'Username is required',
6+
'string.min': 'Username must be at least 3 characters',
7+
'string.max': 'Username must be at most 30 characters',
8+
}),
9+
fullname: Joi.string().min(3).max(50).required().messages({
10+
'string.empty': 'Full name is required',
11+
'string.min': 'Full name must be at least 3 characters',
12+
'string.max': 'Full name must be at most 50 characters',
13+
}),
14+
email: Joi.string().email().required().messages({
15+
'string.empty': 'Email is required',
16+
'string.email': 'Email must be a valid email address',
17+
}),
18+
password: Joi.string().min(6).required().messages({
19+
'string.empty': 'Password is required',
20+
'string.min': 'Password must be at least 6 characters',
21+
}),
22+
});
23+
24+
const loginSchema = Joi.object({
25+
email: Joi.string().email().required().messages({
26+
'string.empty': 'Email is required',
27+
'string.email': 'Email must be a valid email address',
28+
}),
29+
password: Joi.string().min(6).required().messages({
30+
'string.empty': 'Password is required',
31+
'string.min': 'Password must be at least 6 characters',
32+
}),
33+
});
34+
35+
export { registerSchema, loginSchema };

src/validations/rbacValidation.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// src/validations/rbacValidation.js
2+
import Joi from "joi";
3+
4+
const adminAccessSchema = Joi.object({
5+
authorization: Joi.string()
6+
.pattern(/^Bearer\s.+$/)
7+
.required()
8+
.messages({
9+
"string.pattern.base": "Authorization header must be in Bearer token format",
10+
"string.empty": "Authorization token is required",
11+
}),
12+
}).unknown(true); // allows other headers
13+
14+
const userAccessSchema = Joi.object({
15+
authorization: Joi.string()
16+
.pattern(/^Bearer\s.+$/)
17+
.required()
18+
.messages({
19+
"string.pattern.base": "Authorization header must be in Bearer token format",
20+
"string.empty": "Authorization token is required",
21+
}),
22+
}).unknown(true);
23+
24+
export { adminAccessSchema, userAccessSchema };

0 commit comments

Comments
 (0)