/**
* @file Controller for user-related operations like registration and login.
* @module controllers/userController
* @requires ../models/userModel
* @requires jsonwebtoken
*/
const User = require("../models/userModel");
const jwt = require("jsonwebtoken");
/**
* Generates a JSON Web Token (JWT) for a given user ID.
*
* @private
* @param {string} id - The user's unique identifier from MongoDB.
* @returns {string} The generated JWT, valid for 30 days.
*/
const generateToken = (id) => {
return jwt.sign({ id }, process.env.JWT_SECRET, {
expiresIn: "30d",
});
};
/**
* Registers a new user.
*
* - Validates that the email is unique.
* - Creates a new user in the database.
* - Returns user details and a JWT on success.
*
* @async
* @route POST /api/users/register
* @access Public
* @param {Object} req - Express request object (contains `name`, `email`, `password`, and optional `role` in `body`).
* @param {Object} res - Express response object.
* @returns {Promise<void>}
*/
exports.registerUser = async (req, res) => {
const { name, email, password, role } = req.body;
try {
const userExists = await User.findOne({ email });
if (userExists) {
return res
.status(400)
.json({ message: "User with this email already exists" });
}
const user = await User.create({ name, email, password, role });
if (user) {
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user._id),
});
} else {
res.status(400).json({ message: "Invalid user data" });
}
} catch (error) {
res.status(500).json({ message: "Server Error", error: error.message });
}
};
/**
* Authenticates an existing user and returns a JWT.
*
* - Verifies email and password.
* - Returns user details and a JWT if credentials are valid.
*
* @async
* @route POST /api/users/login
* @access Public
* @param {Object} req - Express request object (contains `email` and `password` in `body`).
* @param {Object} res - Express response object.
* @returns {Promise<void>}
*/
exports.loginUser = async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (user && (await user.matchPassword(password))) {
res.json({
_id: user._id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user._id),
});
} else {
res.status(401).json({ message: "Invalid email or password" });
}
} catch (error) {
res.status(500).json({ message: "Server Error", error: error.message });
}
};