diff --git a/README.md b/README.md index 14cede0..a5c735f 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,9 @@ base url: `http://localhost:3000` ### User +- **Get all Users**: GET `/api/users` +- **Get a specific Users**: GET `/api/Users/:userId` + ### Organization - **Create an Organization**: POST `/api/organization` diff --git a/src/controllers/user.controller.js b/src/controllers/user.controller.js index 8b2fce6..36284ca 100644 --- a/src/controllers/user.controller.js +++ b/src/controllers/user.controller.js @@ -1,6 +1,8 @@ import prisma from '../config/prismaClient.js'; +import { getUserByIdValidation } from '../validations/user.validation.js'; +//import { validateUserId, validateCreateUser } from '../validations/user.validation.j // import { authenticate } from '../middlewares/auth.middleware.js'; - +/* eslint no-undef:off */ /** * @swagger * /api/users: @@ -52,6 +54,73 @@ export const getAllUsers = async (req, res, next) => { users, }); } catch (error) { - next(error); + next(error); // Ensure next is called with the error + } +}; + +/** + * @swagger + * /api/users/{id}: + * get: + * summary: Get user by ID + * tags: [Users] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * format: uuid + * description: User ID + * responses: + * 200: + * description: User details retrieved successfully + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + * email: + * type: string + * firstName: + * type: string + * lastName: + * type: string + * role: + * type: string + * 404: + * description: User not found + * 500: + * description: Server error + */ +export const getUserById = async (req, res, next) => { + const { id } = req.params; + try { + // Validate the ID format (UUID) + // const { error } = getUserByIdValidation(req.body); + // if (error) { + // return res.status(400).json({ message: error.details[0].message }); + // } + // Fetch the user by ID from the database + const user = await prisma.user.findFirst({ + where: { id }, + select: { + id: true, + email: true, + firstName: true, + lastName: true, + role: true, + }, + }); + + if (!user) { + return res.status(404).json({ message: 'User not found' }); + } + + return res.status(200).json(user); + } catch (error) { + next(error); // Ensure next is called with the error } }; diff --git a/src/middlewares/auth.middleware.js b/src/middlewares/auth.middleware.js index ffba2dd..5baf617 100644 --- a/src/middlewares/auth.middleware.js +++ b/src/middlewares/auth.middleware.js @@ -28,3 +28,19 @@ export const verifyAccessToken = (req, res, next) => { return res.status(403).json({ message: 'Invalid token' }); } }; + +// export const authorizeUser = (req, res, next) => { +// const { user } = req; // Assuming `req.user` is populated by authentication middleware +// const { id } = req.params; + +// if (!user) { +// return res.status(401).json({ message: 'Unauthorized' }); +// } + +// // Allow access if the user is an admin or accessing their own data +// if (user.role === 'ADMIN' || user.id === id) { +// return next(); +// } + +// return res.status(403).json({ message: 'Forbidden: You do not have access to this resource' }); +// }; diff --git a/src/routes/user.routes.js b/src/routes/user.routes.js index d20ee6e..1602d7e 100644 --- a/src/routes/user.routes.js +++ b/src/routes/user.routes.js @@ -1,5 +1,6 @@ import { Router } from 'express'; -import { getAllUsers } from '../controllers/user.controller.js'; +import { getAllUsers, getUserById } from '../controllers/user.controller.js'; +// import{authorizeUser} from '../middlewares/auth.middleware.js'; const router = Router(); @@ -82,4 +83,30 @@ const router = Router(); */ router.get('/api/users', getAllUsers); +/** + * @swagger + * /api/users/{id}: + * get: + * summary: Get user by ID + * tags: [Users] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: string + * format: uuid + * description: User ID + * responses: + * 200: + * description: User details retrieved successfully + * 400: + * description: Invalid ID format + * 404: + * description: User not found + * 500: + * description: Server error + */ +router.get('/api/users/:id', getUserById); + export default router; diff --git a/src/validations/user.validation.js b/src/validations/user.validation.js new file mode 100644 index 0000000..023a0bc --- /dev/null +++ b/src/validations/user.validation.js @@ -0,0 +1,49 @@ +import Joi from 'joi'; + +export const updateUserAccountValidation = (obj) => { + const schema = Joi.object({ + firstName: Joi.string().trim().min(3).max(30).messages({ + 'string.min': 'First name must be at least 3 characters long.', + 'string.max': 'First name must be at most 30 characters long.', + }), + lastName: Joi.string().trim().messages({ + 'string.min': 'Last name must be at least 3 characters long.', + 'string.max': 'Last name must be at most 30 characters long.', + }), + gender: Joi.string().valid('Male', 'Female').messages({ + 'any.only': "Gender must be either 'male' or 'female'.", + }), + DOB: Joi.date() + .max(new Date(new Date().setFullYear(new Date().getFullYear() - 18))) // Ensures the user is at least 18 years old + .messages({ + 'date.base': 'Invalid date format for DOB.', + 'date.max': 'You must be at least 18 years old.', + }), + mobileNumber: Joi.string().trim().messages({ + 'string.empty': 'Mobile number cannot be empty if provided', + }), + }).min(1); // At least one field must be provided + + return schema.validate(obj); +}; + +export const updateUserPasswordValidation = (obj) => { + const schema = Joi.object({ + password: Joi.string().required().trim().min(8).max(32).messages({ + 'string.empty': 'Password is required.', + 'string.min': 'Password must be at least 8 characters long.', + 'string.max': 'Password must be at most 32 characters long.', + }), + }); + return schema.validate(obj); +}; + +export const getUserByIdValidation = (obj) => { + const schema = Joi.object({ + id: Joi.string().required().trim().messages({ + 'string.empty': 'ID is required.', + }), + }); + + return schema.validate(obj); +};