const { RegisterService, LoginService, getAllUsersService, getUserFromIdService, editUserService, deleteUserService } = require("../services/UserService"); const {JwtVerify} = require("../services/JwtService"); const { Logger } = require('tslog'); const logger = new Logger({ name: "Auth Controller" }); /** * Registers a user. * * @async * @param {Object} req - The request object. * @param {Object} res - The response object. * @return {Object} The response object containing the result of the registration. * If successful, it will contain the registered user's data. * If there is an error, it will contain an error name and message. */ async function registerUser(req, res) { const body = req.body; if (!body) { logger.warn(`Invalid input data (${req.ip})`); return res .type('application/json') .status(400) .json({ error: 'Invalid input data' }); } if (!body.password || !body.username || !body.firstName || !body.lastName || !body.displayName) { logger.warn(`Field(s) missing (${req.ip})`); return res .type('application/json') .status(400) .json({ error: 'Field(s) missing' }); } // sanitize data let gdpr = false if (body.gdpr === true) {gdpr = true} const sanitizeData= { username: `${body.username}`, displayName: `${body.displayName}`, gdpr: gdpr, password: `${body.password}`, firstName: `${body.firstName}`, lastName: `${body.lastName}`, }; /** * Represents the result of the registration service. * * @typedef {Object} RegisterServiceResult * @property {Promise} promise - The promise that resolves when the service registration is complete. */ const RegisterServiceResult = await RegisterService(sanitizeData) if (RegisterServiceResult.error === "gdprNotApproved") { logger.warn(`GDPR not approved (${req.ip})`); return res .status(400) .json({ error: RegisterServiceResult.error, message: "GDPR not accepted." }); } if (RegisterServiceResult.error === "exist") { logger.warn(`The user already exists (${req.ip})`); return res .type('application/json') .status(400) .json({ error: RegisterServiceResult.error, message: "The user already exists." }); } // SUCCESS logger.info(`User registered successfully (${req.ip})`); return res .type('application/json') .status(201) .json(RegisterServiceResult); } /** * Logs in a user with the provided username and password. * * @param {Object} req - The request object containing the body data. * @param {Object} res - The response object to send the result. * @returns {Promise} - A promise that resolves once the login process is complete. */ async function loginUser(req, res) { const body = req.body; if (!body) { return res .type('application/json') .status(400) .json({ error: 'Invalid input data' }); } if (!body.password || !body.username) { logger.warn(`Field(s) missing (${req.ip})`); return res .type('application/json') .status(400) .json({ error: 'Field(s) missing' }); } const loginData = { username: `${body.username}`, password: `${body.password}` }; console.log(body) const LoginServiceResult = await LoginService(loginData); console.log(LoginServiceResult) if (LoginServiceResult.error === "userNotFound") { console.log('POOL') return res .type('application/json') .status(404) .json({ error: LoginServiceResult.error, message: "User not found." }); } if (LoginServiceResult.error === "invalidPassword") { return res .type('application/json') .status(401) .json({ error: LoginServiceResult.error, message: "Invalid password." }); } return res .type('application/json') .status(200) .json(LoginServiceResult); } //TODO - To test async function getAllUsers(req, res) { const authHeader = req.headers.authorization; const bearerToken = authHeader.split(' ')[1]; const payload = await JwtVerify(bearerToken); const sourceUser = await getUserFromIdService(payload.sub) if (!sourceUser) { return res .type('application/json') .status(404) .json({ error: 'You dont exist anymore' }); } if (!sourceUser.isAdmin) { return res .type('application/json') .status(403) .json({ error: 'Unauthorized' }); } const AllUserResponse = await getAllUsersService() if (!AllUserResponse.users) { return res .type('application/json') .status(500) .json({ error: 'Internal server error' }); } return res .type('application/json') .status(200) .json(AllUserResponse); } //TODO - To test /** * Get user from the database based on the provided user ID and return it as a response. * * @async * @param {object} req - The request object containing the user ID as a parameter. * @param {object} res - The response object to be used for sending the user data or error. * @return {Promise} - A Promise that resolves when the user data is sent to the client or an error occurred. */ async function getUser(req, res) { const userId = req.params.userId; const dbUser = await getUserFromIdService(userId); if (!dbUser) { logger.warn(`User not found (${req.ip})`); return res .type('application/json') .status(404) .json({ error: 'User not found' }); } return res .type('application/json') .status(200) .json(dbUser); } //TODO - To test async function editUser(req, res) { const body = req.body; if (!body) { return res .type('application/json') .status(400) .json({ error: 'Field(s) missing' }); } const authHeader = req.headers.authorization; const bearerToken = authHeader.split(' ')[1]; const payload = await JwtVerify(bearerToken); const sourceUser = await getUserFromIdService(payload.sub) /** * Represents the user ID that is the target for a specific operation. * * @type {string|number} */ const targetUserId = body.targetId | payload.sub if (!sourceUser) { logger.warn(`Unauthorized access attempt (${req.ip})`); return res .type('application/json') .status(404) .json({ error: 'You dont exist anymore' }); } if (sourceUser.isAdmin || sourceUser.id === payload.sub) { if (sourceUser.isAdmin) { logger.info(`EDIT :> Source user is an admin (${sourceUser.displayName})`) } else { logger.info(`EDIT :> Source user modify itself (${sourceUser.displayName})`) } // biome-ignore lint/style/useConst: let modifiedData= {} if (body.firstName) modifiedData.firstName = `${body.firstName}`; if (body.lastName) modifiedData.lastName = `${body.lastName}`; if (body.displayName) modifiedData.displayName = `${body.displayName}`; if (body.password) modifiedData.password = `${body.password}`; //Call service const EditUserServiceResult = await editUserService(`${targetUserId}`, modifiedData); if (EditUserServiceResult.error === 'userNotFound') { logger.warn(`User not found (${req.ip})`); return res .type('application/json') .status(404) .json({ error: 'User not found' }); } if (EditUserServiceResult.error !== 'none') { logger.error(`Error occurred during user edit (${req.ip})`); return res .type('application/json') .status(500) .json({ error: 'Internal server error' }); } return res .type('application/json') .status(200) .json(EditUserServiceResult); } //Not itself or logger.warn(`Unauthorized access attempt, not self or admin (${req.ip})`); return res .type('application/json') .status(403) .json({ error: 'Unauthorized' }); } //TODO - To test async function deleteUser(req, res) { const body = req.body; const authHeader = req.headers.authorization; const bearerToken = authHeader.split(' ')[1]; const payload = await JwtVerify(bearerToken); const sourceUser = await getUserFromIdService(payload.sub) const targetUserId = body.targetId | payload.sub if (!sourceUser) { logger.warn(`Unauthorized access attempt (${req.ip})`); return res .type('application/json') .status(404) .json({ error: 'You dont exist anymore' }); } if (sourceUser.isAdmin || sourceUser.id === payload.sub) { const deleteUserServiceResult = await deleteUserService(`${targetUserId}`); if (!deleteUserServiceResult) { logger.error(`Error occurred during user delete (${req.ip})`); return res .type('application/json') .status(500) .json({ error: 'Internal server error' }); } return res .type('application/json') .status(200) .json({ message: 'User deleted successfully' }); } } /** * Retrieves the user's information. * * @param {object} req - The incoming request object. * @param {object} res - The outgoing response object. */ async function getSelf(req, res) { const authHeader = req.headers.authorization; const bearerToken = authHeader.split(' ')[1]; const payload = await JwtVerify(bearerToken); console.log(payload) const dbUser = await getUserFromIdService(payload.sub) if (!dbUser) { return res .type('application/json') .status(404) .json({ error: 'User not found' }); } return res .type('application/json') .status(200) .json({ username: dbUser.username, displayName: dbUser.displayName, firstName: dbUser.firstName, lastName: dbUser.lastName }); } module.exports = { registerUser, loginUser, getAllUsers, getUser, editUser, deleteUser, getSelf }