/**
* @module userController
* @description Handles user-related operations such as registration.
*/
const pool = require('../utility/connection.utility');
const { validateUserRegistration, validateRequestBody } = require('../utility/user.utility');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
require('dotenv').config();
/**
* The function `registerUser` handles user registration by validating input, hashing the password,
* inserting user data into a database, generating a JWT token, and sending a response.
* @param {Object} req - The HTTP request object, containing information about the incoming request.
* @param {Object} req.body - The body of the request, containing user registration data.
* @param {string} req.body.name - The name of the user.
* @param {string} req.body.email - The email of the user.
* @param {string} req.body.password - The password of the user.
* @param {Object} res - The HTTP response object, used to send the response back to the client.
* @returns {Promise<void>} - A promise that resolves to sending a response to the client.
* @throws {Error} - Throws an error if validation fails or if there is an issue with database interaction.
* @memberof module:userController
*/
const registerUser = async (req, res) => {
try {
// Validate request body
const requiredFields = ['name', 'email', 'password'];
validateRequestBody(req.body, requiredFields);
// Extract the required fields from the request body
const { name, email, password } = req.body;
// Validate the user registration input
validateUserRegistration(name, email, password);
// Hash the password
const hashedPassword = await bcrypt.hash(password, 10);
// Register a new user
const SQL = `
INSERT INTO user (name, email, password, create_time)
VALUES (?, ?, ?, date_format(now(), '%Y-%m-%d %H:%i:%s'))
`;
// Execute the query
const [results] = await pool.query(SQL, [name, email, hashedPassword]);
// Get the user ID
const userId = results.insertId;
// Generate a JWT token
const token = jwt.sign({ userId, name, email }, process.env.JWT_SECRET, { expiresIn: '1h' });
// Send the response
return res.status(200).json({ message: 'User registered successfully', token });
} catch (error) {
console.error(error);
return res.status(500).json({ error: error.message });
}
};
/**
* The function `loginUser` handles user login by validating input, retrieving user data from the database,
* comparing the password, generating a JWT token, and sending a response.
* @param {Object} req - The HTTP request object, containing information about the incoming request.
* @param {Object} req.body - The body of the request, containing user login data.
* @param {string} req.body.email - The email of the user.
* @param {string} req.body.password - The password of the user.
* @param {Object} res - The HTTP response object, used to send the response back to the client.
* @returns {Promise<void>} - A promise that resolves to sending a response to the client.
* @throws {Error} - Throws an error if validation fails or if there is an issue with database interaction.
* @memberof module:userController
*/
const loginUser = async (req, res) => {
try {
// Validate request body
const requiredFields = ['email', 'password'];
validateRequestBody(req.body, requiredFields);
// Extract the required fields from the request body
const { email, password } = req.body;
// Get the user from the database
const SQL = `
SELECT * FROM user
WHERE email = ?
`;
// Execute the query
const [results] = await pool.query(SQL, [email]);
// Check if the user exists
if (results.length === 0) {
return res.status(401).json({ error: 'Invalid email or password' });
}
// Compare the password
const user = results[0];
const isValidPassword = await bcrypt.compare(password, user.password);
if (!isValidPassword) {
return res.status(401).json({ error: 'Invalid email or password' });
}
// Generate a JWT token
const token = jwt.sign({ id: user.id, name: user.name, email: user.email }, process.env.JWT_SECRET, {
expiresIn: '1h',
});
// Send the response
return res.status(200).json({ message: 'User logged in successfully', token });
} catch (error) {
console.error(error);
return res.status(500).json({ error: error.message });
}
};
/**
* The function `refreshToken` handles refreshing a JWT token by verifying the refresh token,
* generating a new JWT token, and sending a response.
* @param {Object} req - The HTTP request object, containing information about the incoming request.
* @param {Object} req.body - The body of the request, containing the refresh token.
* @param {string} req.body.token - The refresh token to be verified.
* @param {Object} res - The HTTP response object, used to send the response back to the client.
* @returns {Promise<void>} - A promise that resolves to sending a response to the client.
* @throws {Error} - Throws an error if the refresh token is missing or invalid.
* @memberof module:userController
*/
const refreshToken = async (req, res) => {
try {
const { token } = req.body;
if (!token) {
return res.status(401).json({ error: 'Refresh token is required' });
}
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const newToken = jwt.sign(
{ id: decoded.id, name: decoded.name, email: decoded.email },
process.env.JWT_SECRET,
{
expiresIn: '1h',
},
);
return res.status(200).json({ token: newToken });
} catch (error) {
console.error(error);
return res.status(500).json({ error: error.message });
}
};
module.exports = {
registerUser,
loginUser,
refreshToken,
};