From 5f6e0631c6ecd393f58fa71ac3fb481f8ae837a2 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Wed, 16 Oct 2024 11:46:37 +0800 Subject: [PATCH] Prettier formatting --- Server/controllers/authController.js | 577 +++++++++++++-------------- 1 file changed, 288 insertions(+), 289 deletions(-) diff --git a/Server/controllers/authController.js b/Server/controllers/authController.js index 1c5c37c9d..619cb2e94 100644 --- a/Server/controllers/authController.js +++ b/Server/controllers/authController.js @@ -1,11 +1,11 @@ import { - registrationBodyValidation, - loginValidation, - editUserParamValidation, - editUserBodyValidation, - recoveryValidation, - recoveryTokenValidation, - newPasswordValidation, + registrationBodyValidation, + loginValidation, + editUserParamValidation, + editUserBodyValidation, + recoveryValidation, + recoveryTokenValidation, + newPasswordValidation, } from "../validation/joi.js"; import logger from "../utils/logger.js"; import dotenv from "dotenv"; @@ -26,12 +26,12 @@ dotenv.config(); * @throws {Error} */ const issueToken = (payload, appSettings) => { - try { - const tokenTTL = appSettings.jwtTTL ? appSettings.jwtTTL : "2h"; - return jwt.sign(payload, appSettings.jwtSecret, { expiresIn: tokenTTL }); - } catch (error) { - throw handleError(error, SERVICE_NAME, "issueToken"); - } + try { + const tokenTTL = appSettings.jwtTTL ? appSettings.jwtTTL : "2h"; + return jwt.sign(payload, appSettings.jwtSecret, { expiresIn: tokenTTL }); + } catch (error) { + throw handleError(error, SERVICE_NAME, "issueToken"); + } }; /** @@ -47,65 +47,65 @@ const issueToken = (payload, appSettings) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422). */ const registerUser = async (req, res, next) => { - // joi validation - try { - await registrationBodyValidation.validateAsync(req.body); - } catch (error) { - const validationError = handleValidationError(error, SERVICE_NAME); - next(validationError); - return; - } - // Create a new user - try { - const { inviteToken } = req.body; - // If superAdmin exists, a token should be attached to all further register requests - const superAdminExists = await req.db.checkSuperadmin(req, res); - if (superAdminExists) { - await req.db.getInviteTokenAndDelete(inviteToken); - } else { - // This is the first account, create JWT secret to use if one is not supplied by env - const jwtSecret = crypto.randomBytes(64).toString("hex"); - await req.db.updateAppSettings({ jwtSecret }); - } + // joi validation + try { + await registrationBodyValidation.validateAsync(req.body); + } catch (error) { + const validationError = handleValidationError(error, SERVICE_NAME); + next(validationError); + return; + } + // Create a new user + try { + const { inviteToken } = req.body; + // If superAdmin exists, a token should be attached to all further register requests + const superAdminExists = await req.db.checkSuperadmin(req, res); + if (superAdminExists) { + await req.db.getInviteTokenAndDelete(inviteToken); + } else { + // This is the first account, create JWT secret to use if one is not supplied by env + const jwtSecret = crypto.randomBytes(64).toString("hex"); + await req.db.updateAppSettings({ jwtSecret }); + } - const newUser = await req.db.insertUser({ ...req.body }, req.file); + const newUser = await req.db.insertUser({ ...req.body }, req.file); - logger.info(successMessages.AUTH_CREATE_USER, { - service: SERVICE_NAME, - userId: newUser._id, - }); + logger.info(successMessages.AUTH_CREATE_USER, { + service: SERVICE_NAME, + userId: newUser._id, + }); - const userForToken = { ...newUser._doc }; - delete userForToken.profileImage; - delete userForToken.avatarImage; + const userForToken = { ...newUser._doc }; + delete userForToken.profileImage; + delete userForToken.avatarImage; - const appSettings = await req.settingsService.getSettings(); + const appSettings = await req.settingsService.getSettings(); - const token = issueToken(userForToken, appSettings); + const token = issueToken(userForToken, appSettings); - req.emailService - .buildAndSendEmail( - "welcomeEmailTemplate", - { name: newUser.firstName }, - newUser.email, - "Welcome to Uptime Monitor" - ) - .catch((error) => { - logger.error("Error sending welcome email", { - service: SERVICE_NAME, - error: error.message, - }); - }); + req.emailService + .buildAndSendEmail( + "welcomeEmailTemplate", + { name: newUser.firstName }, + newUser.email, + "Welcome to Uptime Monitor" + ) + .catch((error) => { + logger.error("Error sending welcome email", { + service: SERVICE_NAME, + error: error.message, + }); + }); - return res.status(200).json({ - success: true, - msg: successMessages.AUTH_CREATE_USER, - data: { user: newUser, token: token }, - }); - } catch (error) { - console.log("ERROR", error); - next(handleError(error, SERVICE_NAME, "registerController")); - } + return res.status(200).json({ + success: true, + msg: successMessages.AUTH_CREATE_USER, + data: { user: newUser, token: token }, + }); + } catch (error) { + console.log("ERROR", error); + next(handleError(error, SERVICE_NAME, "registerController")); + } }; /** @@ -121,44 +121,45 @@ const registerUser = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422) or the password is incorrect. */ const loginUser = async (req, res, next) => { - try { - await loginValidation.validateAsync(req.body); - } catch (error) { - const validationError = handleValidationError(error, SERVICE_NAME); - next(validationError); - return; - } - try { - const { email, password } = req.body; - // Check if user exists - const user = await req.db.getUserByEmail(email); + try { + await loginValidation.validateAsync(req.body); + } catch (error) { + const validationError = handleValidationError(error, SERVICE_NAME); + next(validationError); + return; + } + try { + const { email, password } = req.body; - // Compare password - const match = await user.comparePassword(password); - if (match !== true) { - next(new Error(errorMessages.AUTH_INCORRECT_PASSWORD)); - return; - } + // Check if user exists + const user = await req.db.getUserByEmail(email); - // Remove password from user object. Should this be abstracted to DB layer? - const userWithoutPassword = { ...user._doc }; - delete userWithoutPassword.password; - delete userWithoutPassword.avatarImage; + // Compare password + const match = await user.comparePassword(password); + if (match !== true) { + next(new Error(errorMessages.AUTH_INCORRECT_PASSWORD)); + return; + } - // Happy path, return token - const appSettings = await req.settingsService.getSettings(); - const token = issueToken(userWithoutPassword, appSettings); - // reset avatar image - userWithoutPassword.avatarImage = user.avatarImage; + // Remove password from user object. Should this be abstracted to DB layer? + const userWithoutPassword = { ...user._doc }; + delete userWithoutPassword.password; + delete userWithoutPassword.avatarImage; - return res.status(200).json({ - success: true, - msg: successMessages.AUTH_LOGIN_USER, - data: { user: userWithoutPassword, token: token }, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "loginController")); - } + // Happy path, return token + const appSettings = await req.settingsService.getSettings(); + const token = issueToken(userWithoutPassword, appSettings); + // reset avatar image + userWithoutPassword.avatarImage = user.avatarImage; + + return res.status(200).json({ + success: true, + msg: successMessages.AUTH_LOGIN_USER, + data: { user: userWithoutPassword, token: token }, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "loginUser")); + } }; /** @@ -176,58 +177,58 @@ const loginUser = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422), the user is unauthorized (401), or the password is incorrect (403). */ const editUser = async (req, res, next) => { - try { - await editUserParamValidation.validateAsync(req.params); - await editUserBodyValidation.validateAsync(req.body); - } catch (error) { - const validationError = handleValidationError(error, SERVICE_NAME); - next(validationError); - return; - } + try { + await editUserParamValidation.validateAsync(req.params); + await editUserBodyValidation.validateAsync(req.body); + } catch (error) { + const validationError = handleValidationError(error, SERVICE_NAME); + next(validationError); + return; + } - // TODO is this neccessary any longer? Verify ownership middleware should handle this - if (req.params.userId !== req.user._id.toString()) { - const error = new Error(errorMessages.AUTH_UNAUTHORIZED); - error.status = 401; - error.service = SERVICE_NAME; - next(error); - return; - } + // TODO is this neccessary any longer? Verify ownership middleware should handle this + if (req.params.userId !== req.user._id.toString()) { + const error = new Error(errorMessages.AUTH_UNAUTHORIZED); + error.status = 401; + error.service = SERVICE_NAME; + next(error); + return; + } - try { - // Change Password check - if (req.body.password && req.body.newPassword) { - // Get token from headers - const token = getTokenFromHeaders(req.headers); - // Get email from token - const { jwtSecret } = req.settingsService.getSettings(); - const { email } = jwt.verify(token, jwtSecret); - // Add user email to body for DB operation - req.body.email = email; - // Get user - const user = await req.db.getUserByEmail(email); - // Compare passwords - const match = await user.comparePassword(req.body.password); - // If not a match, throw a 403 - if (!match) { - const error = new Error(errorMessages.AUTH_INCORRECT_PASSWORD); - error.status = 403; - next(error); - return; - } - // If a match, update the password - req.body.password = req.body.newPassword; - } + try { + // Change Password check + if (req.body.password && req.body.newPassword) { + // Get token from headers + const token = getTokenFromHeaders(req.headers); + // Get email from token + const { jwtSecret } = req.settingsService.getSettings(); + const { email } = jwt.verify(token, jwtSecret); + // Add user email to body for DB operation + req.body.email = email; + // Get user + const user = await req.db.getUserByEmail(email); + // Compare passwords + const match = await user.comparePassword(req.body.password); + // If not a match, throw a 403 + if (!match) { + const error = new Error(errorMessages.AUTH_INCORRECT_PASSWORD); + error.status = 403; + next(error); + return; + } + // If a match, update the password + req.body.password = req.body.newPassword; + } - const updatedUser = await req.db.updateUser(req, res); - return res.status(200).json({ - success: true, - msg: successMessages.AUTH_UPDATE_USER, - data: updatedUser, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "userEditController")); - } + const updatedUser = await req.db.updateUser(req, res); + return res.status(200).json({ + success: true, + msg: successMessages.AUTH_UPDATE_USER, + data: updatedUser, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "userEditController")); + } }; /** @@ -240,16 +241,16 @@ const editUser = async (req, res, next) => { * @throws {Error} If there is an error during the process. */ const checkSuperadminExists = async (req, res, next) => { - try { - const superAdminExists = await req.db.checkSuperadmin(req, res); - return res.status(200).json({ - success: true, - msg: successMessages.AUTH_ADMIN_EXISTS, - data: superAdminExists, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "checkSuperadminController")); - } + try { + const superAdminExists = await req.db.checkSuperadmin(req, res); + return res.status(200).json({ + success: true, + msg: successMessages.AUTH_ADMIN_EXISTS, + data: superAdminExists, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "checkSuperadminController")); + } }; /** @@ -264,46 +265,46 @@ const checkSuperadminExists = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422). */ const requestRecovery = async (req, res, next) => { - try { - await recoveryValidation.validateAsync(req.body); - } catch (error) { - const validationError = handleValidationError(error, SERVICE_NAME); - next(validationError); - return; - } + try { + await recoveryValidation.validateAsync(req.body); + } catch (error) { + const validationError = handleValidationError(error, SERVICE_NAME); + next(validationError); + return; + } - try { - const { email } = req.body; - const user = await req.db.getUserByEmail(email); - if (user) { - const recoveryToken = await req.db.requestRecoveryToken(req, res); - const name = user.firstName; - const email = req.body.email; - const { clientHost } = req.settingsService.getSettings(); - const url = `${clientHost}/set-new-password/${recoveryToken.token}`; + try { + const { email } = req.body; + const user = await req.db.getUserByEmail(email); + if (user) { + const recoveryToken = await req.db.requestRecoveryToken(req, res); + const name = user.firstName; + const email = req.body.email; + const { clientHost } = req.settingsService.getSettings(); + const url = `${clientHost}/set-new-password/${recoveryToken.token}`; - const msgId = await req.emailService.buildAndSendEmail( - "passwordResetTemplate", - { - name, - email, - url, - }, - email, - "Bluewave Uptime Password Reset" - ); + const msgId = await req.emailService.buildAndSendEmail( + "passwordResetTemplate", + { + name, + email, + url, + }, + email, + "Bluewave Uptime Password Reset" + ); - return res.status(200).json({ - success: true, - msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN, - data: msgId, - }); - } else { - throw new Error(errorMessages.FRIENDLY_ERROR); - } - } catch (error) { - next(handleError(error, SERVICE_NAME, "recoveryRequestController")); - } + return res.status(200).json({ + success: true, + msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN, + data: msgId, + }); + } else { + throw new Error(errorMessages.FRIENDLY_ERROR); + } + } catch (error) { + next(handleError(error, SERVICE_NAME, "recoveryRequestController")); + } }; /** @@ -318,23 +319,23 @@ const requestRecovery = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422). */ const validateRecovery = async (req, res, next) => { - try { - await recoveryTokenValidation.validateAsync(req.body); - } catch (error) { - const validationError = handleValidationError(error, SERVICE_NAME); - next(validationError); - return; - } + try { + await recoveryTokenValidation.validateAsync(req.body); + } catch (error) { + const validationError = handleValidationError(error, SERVICE_NAME); + next(validationError); + return; + } - try { - await req.db.validateRecoveryToken(req, res); - return res.status(200).json({ - success: true, - msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "validateRecoveryTokenController")); - } + try { + await req.db.validateRecoveryToken(req, res); + return res.status(200).json({ + success: true, + msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "validateRecoveryTokenController")); + } }; /** @@ -350,26 +351,26 @@ const validateRecovery = async (req, res, next) => { * @throws {Error} If there is an error during the process, especially if there is a validation error (422). */ const resetPassword = async (req, res, next) => { - try { - await newPasswordValidation.validateAsync(req.body); - } catch (error) { - const validationError = handleValidationError(error, SERVICE_NAME); - next(validationError); - return; - } - try { - const user = await req.db.resetPassword(req, res); + try { + await newPasswordValidation.validateAsync(req.body); + } catch (error) { + const validationError = handleValidationError(error, SERVICE_NAME); + next(validationError); + return; + } + try { + const user = await req.db.resetPassword(req, res); - const appSettings = await req.settingsService.getSettings(); - const token = issueToken(user._doc, appSettings); - res.status(200).json({ - success: true, - msg: successMessages.AUTH_RESET_PASSWORD, - data: { user, token }, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "resetPasswordController")); - } + const appSettings = await req.settingsService.getSettings(); + const token = issueToken(user._doc, appSettings); + res.status(200).json({ + success: true, + msg: successMessages.AUTH_RESET_PASSWORD, + data: { user, token }, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "resetPasswordController")); + } }; /** @@ -382,74 +383,72 @@ const resetPassword = async (req, res, next) => { * @throws {Error} If user validation fails or user is not found in the database. */ const deleteUser = async (req, res, next) => { - try { - const token = getTokenFromHeaders(req.headers); - const decodedToken = jwt.decode(token); - const { email } = decodedToken; + try { + const token = getTokenFromHeaders(req.headers); + const decodedToken = jwt.decode(token); + const { email } = decodedToken; - // Check if the user exists - const user = await req.db.getUserByEmail(email); - if (!user) { - next(new Error(errorMessages.DB_USER_NOT_FOUND)); - return; - } + // Check if the user exists + const user = await req.db.getUserByEmail(email); + if (!user) { + next(new Error(errorMessages.DB_USER_NOT_FOUND)); + return; + } - // 1. Find all the monitors associated with the team ID if superadmin + // 1. Find all the monitors associated with the team ID if superadmin - const result = await req.db.getMonitorsByTeamId({ - params: { teamId: user.teamId }, - }); + const result = await req.db.getMonitorsByTeamId({ + params: { teamId: user.teamId }, + }); - if (user.role.includes("superadmin")) { - //2. Remove all jobs, delete checks and alerts - result?.monitors.length > 0 && - (await Promise.all( - result.monitors.map(async (monitor) => { - await req.jobQueue.deleteJob(monitor); - await req.db.deleteChecks(monitor._id); - await req.db.deletePageSpeedChecksByMonitorId(monitor._id); - await req.db.deleteNotificationsByMonitorId(monitor._id); - }) - )); + if (user.role.includes("superadmin")) { + //2. Remove all jobs, delete checks and alerts + result?.monitors.length > 0 && + (await Promise.all( + result.monitors.map(async (monitor) => { + await req.jobQueue.deleteJob(monitor); + await req.db.deleteChecks(monitor._id); + await req.db.deletePageSpeedChecksByMonitorId(monitor._id); + await req.db.deleteNotificationsByMonitorId(monitor._id); + }) + )); - // 3. Delete team - await req.db.deleteTeam(user.teamId); - // 4. Delete all other team members - await req.db.deleteAllOtherUsers(); - // 5. Delete each monitor - await req.db.deleteMonitorsByUserId(user._id); - } - // 6. Delete the user by id - await req.db.deleteUser(user._id); - return res.status(200).json({ - success: true, - msg: successMessages.AUTH_DELETE_USER, - }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "deleteUserController")); - } + // 3. Delete team + await req.db.deleteTeam(user.teamId); + // 4. Delete all other team members + await req.db.deleteAllOtherUsers(); + // 5. Delete each monitor + await req.db.deleteMonitorsByUserId(user._id); + } + // 6. Delete the user by id + await req.db.deleteUser(user._id); + return res.status(200).json({ + success: true, + msg: successMessages.AUTH_DELETE_USER, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "deleteUserController")); + } }; const getAllUsers = async (req, res, next) => { - try { - const allUsers = await req.db.getAllUsers(req, res); - res - .status(200) - .json({ success: true, msg: "Got all users", data: allUsers }); - } catch (error) { - next(handleError(error, SERVICE_NAME, "getAllUsersController")); - } + try { + const allUsers = await req.db.getAllUsers(req, res); + res.status(200).json({ success: true, msg: "Got all users", data: allUsers }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "getAllUsersController")); + } }; export { - issueToken, - registerUser, - loginUser, - editUser, - checkSuperadminExists, - requestRecovery, - validateRecovery, - resetPassword, - deleteUser, - getAllUsers, + issueToken, + registerUser, + loginUser, + editUser, + checkSuperadminExists, + requestRecovery, + validateRecovery, + resetPassword, + deleteUser, + getAllUsers, };