Merge pull request #900 from bluewave-labs/feat/be/refactor

Feat/be/refactor
This commit is contained in:
Alexander Holliday authored and GitHub committed 2024-09-30 20:03:09 -07:00
commit 3b6a610c96
34 files changed
+644 -681

No files matched your search

+2 -1
View File
@@ -1,4 +1,5 @@
.vite
.vscode
*.sh
!uptime.sh
!uptime.sh
*.idea
+396 -491
View File
@@ -1,459 +1,371 @@
const express = require("express");
const {
registrationBodyValidation,
loginValidation,
editUserParamValidation,
editUserBodyValidation,
recoveryValidation,
recoveryTokenValidation,
newPasswordValidation,
deleteUserParamValidation,
inviteRoleValidation,
inviteBodyValidation,
inviteVerifciationBodyValidation,
registrationBodyValidation,
loginValidation,
editUserParamValidation,
editUserBodyValidation,
recoveryValidation,
recoveryTokenValidation,
newPasswordValidation,
} = require("../validation/joi");
const logger = require("../utils/logger");
require("dotenv").config();
const { errorMessages, successMessages } = require("../utils/messages");
var jwt = require("jsonwebtoken");
const {errorMessages, successMessages} = require("../utils/messages");
const jwt = require("jsonwebtoken");
const SERVICE_NAME = "AuthController";
const { getTokenFromHeaders } = require("../utils/utils");
const {getTokenFromHeaders} = require("../utils/utils");
const crypto = require("crypto");
/**
* Creates and returns JWT token with an arbitrary payload
* @function
* @param {Object} payload
* @param {Object} appSettings
* @returns {String}
* @throws {Error}
*/
const issueToken = (payload, appSettings) => {
try {
const tokenTTL = appSettings.jwtTTL ? appSettings.jwtTTL : "2h";
return jwt.sign(payload, appSettings.jwtSecret, { expiresIn: tokenTTL });
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "issueToken") : null;
next(error);
}
};
/**
* @function
* @param {express.Request} req
* @param {express.Response} res
* @returns {{success: Boolean, msg: String}}
*/
const registerController = async (req, res, next) => {
// joi validation
try {
await registrationBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
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);
logger.info(successMessages.AUTH_CREATE_USER, {
service: SERVICE_NAME,
userId: newUser._id,
});
const userForToken = { ...newUser._doc };
delete userForToken.profileImage;
delete userForToken.avatarImage;
const appSettings = await req.settingsService.getSettings();
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,
});
});
return res.status(200).json({
success: true,
msg: successMessages.AUTH_CREATE_USER,
data: { user: newUser, token: token },
});
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "registerController") : null;
next(error);
}
};
/**
* Returns JWT with User info
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
*/
const loginController = async (req, res, next) => {
try {
await loginValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const { email, password } = req.body;
// Check if user exists
const user = await req.db.getUserByEmail(email);
// Compare password
const match = await user.comparePassword(password);
if (match !== true) {
throw new Error(errorMessages.AUTH_INCORRECT_PASSWORD);
}
// Remove password from user object. Should this be abstracted to DB layer?
const userWithoutPassword = { ...user._doc };
delete userWithoutPassword.password;
delete userWithoutPassword.avatarImage;
// Happy path, return token
const appSettings = 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) {
error.status = 500;
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "loginController") : null;
next(error);
}
};
const userEditController = async (req, res, next) => {
try {
await editUserParamValidation.validateAsync(req.params);
await editUserBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
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) {
const newPassword = req.body.newPassword;
const password = req.body.password;
// Compare password
// 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;
throw error;
}
// 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) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "userEditController") : null;
next(error);
return;
}
};
const inviteController = async (req, res, next) => {
try {
// Only admins can invite
const token = getTokenFromHeaders(req.headers);
const { role, firstname, teamId } = jwt.decode(token);
req.body.teamId = teamId;
try {
await inviteRoleValidation.validateAsync({ roles: role });
await inviteBodyValidation.validateAsync(req.body);
const tokenTTL = appSettings.jwtTTL ? appSettings.jwtTTL : "2h";
return jwt.sign(payload, appSettings.jwtSecret, {expiresIn: tokenTTL});
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "issueToken") : null;
throw error;
}
};
const inviteToken = await req.db.requestInviteToken(req, res);
const { clientHost } = req.settingsService.getSettings();
req.emailService
.buildAndSendEmail(
"employeeActivationTemplate",
{
name: firstname,
link: `${clientHost}/register/${inviteToken.token}`,
},
req.body.email,
"Welcome to Uptime Monitor"
)
.catch((error) => {
logger.error("Error sending invite email", {
service: SERVICE_NAME,
error: error.message,
/**
* Registers a new user. If the user is the first account, a JWT secret is created. If not, an invite token is required.
* @async
* @param {Object} req - The Express request object.
* @property {Object} req.body - The body of the request.
* @property {string} req.body.inviteToken - The invite token for registration.
* @property {Object} req.file - The file object for the user's profile image.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the creation of the user, the created user data, and a JWT token.
* @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) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details?.[0]?.message || error.message || "Validation Error";
next(error);
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);
logger.info(successMessages.AUTH_CREATE_USER, {
service: SERVICE_NAME, userId: newUser._id,
});
});
return res
.status(200)
.json({ success: true, msg: "Invite sent", data: inviteToken });
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "inviteController") : null;
next(error);
return;
}
};
const userForToken = {...newUser._doc};
delete userForToken.profileImage;
delete userForToken.avatarImage;
const inviteVerifyController = async (req, res, next) => {
try {
await inviteVerifciationBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
const appSettings = await req.settingsService.getSettings();
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,
});
});
try {
const invite = await req.db.getInviteToken(req, res);
res
.status(200)
.json({ status: "success", msg: "Invite verified", data: invite });
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined
? (error.method = "inviteVerifyController")
: null;
next(error);
return;
}
};
/**
* Checks to see if an admin account exists
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
*/
const checkSuperadminController = async (req, res) => {
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) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined
? (error.method = "checkSuperadminController")
: null;
next(error);
return;
}
};
/**
* Returns a recovery token
* @async
* @param {Express.Request} req
* @property {Object} req.body
* @property {string} req.body.email
* @property {EmailService} req.body.emailService
* @returns {Promise<Express.Response>}
*/
const recoveryRequestController = async (req, res, next) => {
try {
await recoveryValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
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}`;
const msgId = await req.emailService.buildAndSendEmail(
"passwordResetTemplate",
{ name, email, url },
email,
"Bluewaves Uptime Password Resest"
);
return res.status(200).json({
success: true,
msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN,
data: msgId,
});
return res.status(200).json({
success: true, msg: successMessages.AUTH_CREATE_USER, data: {user: newUser, token: token},
});
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "registerController") : null;
next(error);
}
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined
? (error.method = "recoveryRequestController")
: null;
next(error);
return;
}
};
/**
* Returns a recovery token
* Logs in a user by validating the user's credentials and issuing a JWT token.
* @async
* @param {Express.Request} req
* @property {Object} req.body
* @property {string} req.body.token
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
* @param {Object} req - The Express request object.
* @property {Object} req.body - The body of the request.
* @property {string} req.body.email - The email of the user.
* @property {string} req.body.password - The password of the user.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the login of the user, the user data (without password and avatar image), and a JWT token.
* @throws {Error} If there is an error during the process, especially if there is a validation error (422) or the password is incorrect.
*/
const validateRecoveryTokenController = async (req, res, next) => {
try {
await recoveryTokenValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
const loginUser = async (req, res, next) => {
try {
await loginValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const {email, password} = req.body;
// Check if user exists
const user = await req.db.getUserByEmail(email);
try {
await req.db.validateRecoveryToken(req, res);
// TODO Redirect user to reset password after validating token
return res.status(200).json({
success: true,
msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN,
});
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined
? (error.method = "validateRecoveryTokenController")
: null;
next(error);
return;
}
// Compare password
const match = await user.comparePassword(password);
if (match !== true) {
next(new Error(errorMessages.AUTH_INCORRECT_PASSWORD));
return;
}
// Remove password from user object. Should this be abstracted to DB layer?
const userWithoutPassword = {...user._doc};
delete userWithoutPassword.password;
delete userWithoutPassword.avatarImage;
// Happy path, return token
const appSettings = 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) {
error.status = 500;
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "loginController") : null;
next(error);
}
};
/**
* Returns an updated user
* Edits a user's information. If the user wants to change their password, the current password is checked before updating to the new password.
* @async
* @param {Express.Request} req
* @property {Object} req.body
* @property {string} req.body.token
* @property {string} req.body.password
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
* @param {Object} req - The Express request object.
* @property {Object} req.params - The parameters of the request.
* @property {string} req.params.userId - The ID of the user to be edited.
* @property {Object} req.body - The body of the request.
* @property {string} req.body.password - The current password of the user.
* @property {string} req.body.newPassword - The new password of the user.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the update of the user, and the updated user data.
* @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 resetPasswordController = async (req, res, next) => {
try {
await newPasswordValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const user = await req.db.resetPassword(req, res);
const editUser = async (req, res, next) => {
try {
await editUserParamValidation.validateAsync(req.params);
await editUserBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
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) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined
? (error.method = "resetPasswordController")
: null;
next(error);
}
// 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;
}
const updatedUser = await req.db.updateUser(req, res);
return res.status(200).json({
success: true, msg: successMessages.AUTH_UPDATE_USER, data: updatedUser,
});
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "userEditController") : null;
next(error);
}
};
/**
* Checks if a superadmin account exists in the database.
* @async
* @param {Object} req - The Express request object.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the existence of a superadmin, and a boolean indicating the existence of a superadmin.
* @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) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "checkSuperadminController") : null;
next(error);
}
};
/**
* Requests a recovery token for a user. The user's email is validated and a recovery token is created and sent via email.
* @async
* @param {Object} req - The Express request object.
* @property {Object} req.body - The body of the request.
* @property {string} req.body.email - The email of the user requesting recovery.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the creation of the recovery token, and the message ID of the sent email.
* @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) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details?.[0]?.message || error.message || "Validation Error";
next(error);
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}`;
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,
});
}
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "recoveryRequestController") : null;
next(error);
}
};
/**
* Validates a recovery token. The recovery token is validated and if valid, a success message is returned.
* @async
* @param {Object} req - The Express request object.
* @property {Object} req.body - The body of the request.
* @property {string} req.body.token - The recovery token to be validated.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status and a message indicating the validation of the recovery token.
* @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) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
await req.db.validateRecoveryToken(req, res);
return res.status(200).json({
success: true, msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN,
});
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "validateRecoveryTokenController") : null;
next(error);
}
};
/**
* Resets a user's password. The new password is validated and if valid, the user's password is updated in the database and a new JWT token is issued.
* @async
* @param {Object} req - The Express request object.
* @property {Object} req.body - The body of the request.
* @property {string} req.body.token - The recovery token.
* @property {string} req.body.password - The new password of the user.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the reset of the password, the updated user data (without password and avatar image), and a new JWT token.
* @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) {
error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details?.[0]?.message || error.message || "Validation Error";
next(error);
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) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "resetPasswordController") : null;
next(error);
}
};
/**
@@ -465,81 +377,74 @@ const resetPasswordController = async (req, res, next) => {
* @returns {Object} The response object with success status and message.
* @throws {Error} If user validation fails or user is not found in the database.
*/
const deleteUserController = async (req, res, next) => {
try {
const token = getTokenFromHeaders(req.headers);
const decodedToken = jwt.decode(token);
const { _id, email } = decodedToken;
const deleteUser = async (req, res, next) => {
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) {
throw new Error(errorMessages.DB_USER_NOT_FOUND);
// 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
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);
})));
// 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) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "deleteUserController") : null;
next(error);
}
// 1. Find all the monitors associated with the team ID if superadmin
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);
})
));
// 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) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "deleteUserController") : null;
next(error);
}
};
const getAllUsersController = async (req, res) => {
try {
const allUsers = await req.db.getAllUsers(req, res);
res
.status(200)
.json({ success: true, msg: "Got all users", data: allUsers });
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined
? (error.method = "getAllUsersController")
: null;
next(error);
}
const getAllUsers = async (req, res) => {
try {
const allUsers = await req.db.getAllUsers(req, res);
res
.status(200)
.json({success: true, msg: "Got all users", data: allUsers});
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "getAllUsersController") : null;
next(error);
}
};
module.exports = {
registerController,
loginController,
userEditController,
inviteController,
inviteVerifyController,
checkSuperadminController,
recoveryRequestController,
validateRecoveryTokenController,
resetPasswordController,
deleteUserController,
getAllUsersController,
registerUser,
loginUser,
editUser,
checkSuperadminExists: checkSuperAdminExists,
requestRecovery,
validateRecovery,
resetPassword,
deleteUser,
getAllUsers,
};
+89 -79
View File
@@ -1,101 +1,111 @@
const {
inviteRoleValidation,
inviteBodyValidation,
inviteVerifciationBodyValidation,
inviteRoleValidation,
inviteBodyValidation,
inviteVerificationBodyValidation,
} = require("../validation/joi");
const logger = require("../utils/logger");
require("dotenv").config();
const { errorMessages, successMessages } = require("../utils/messages");
var jwt = require("jsonwebtoken");
const jwt = require("jsonwebtoken");
const SERVICE_NAME = "inviteController";
const getTokenFromHeaders = (headers) => {
const authorizationHeader = headers.authorization;
if (!authorizationHeader) throw new Error("No auth headers");
const authorizationHeader = headers.authorization;
if (!authorizationHeader) throw new Error("No auth headers");
const parts = authorizationHeader.split(" ");
if (parts.length !== 2 || parts[0] !== "Bearer")
throw new Error("Invalid auth headers");
const parts = authorizationHeader.split(" ");
if (parts.length !== 2 || parts[0] !== "Bearer")
throw new Error("Invalid auth headers");
return parts[1];
return parts[1];
};
const inviteController = async (req, res, next) => {
try {
// Only admins can invite
const token = getTokenFromHeaders(req.headers);
const { role, firstname, teamId } = jwt.decode(token);
req.body.teamId = teamId;
/**
* Issues an invitation to a new user. Only admins can invite new users. An invitation token is created and sent via email.
* @async
* @param {Object} req - The Express request object.
* @property {Object} req.headers - The headers of the request.
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
* @property {Object} req.body - The body of the request.
* @property {string} req.body.email - The email of the user to be invited.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the sending of the invitation, and the invitation token.
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
*/
const issueInvitation = async (req, res, next) => {
try {
await inviteRoleValidation.validateAsync({ roles: role });
await inviteBodyValidation.validateAsync(req.body);
// Only admins can invite
const token = getTokenFromHeaders(req.headers);
const {role, firstname, teamId} = jwt.decode(token);
req.body.teamId = teamId;
try {
await inviteRoleValidation.validateAsync({roles: role});
await inviteBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
const inviteToken = await req.db.requestInviteToken({...req.body});
const {clientHost} = req.settingsService.getSettings();
req.emailService
.buildAndSendEmail(
"employeeActivationTemplate",
{
name: firstname,
link: `${clientHost}/register/${inviteToken.token}`,
},
req.body.email,
"Welcome to Uptime Monitor"
)
.catch((error) => {
logger.error("Error sending invite email", {
service: SERVICE_NAME,
error: error.message,
});
});
return res
.status(200)
.json({success: true, msg: "Invite sent", data: inviteToken});
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "inviteController") : null;
next(error);
}
const inviteToken = await req.db.requestInviteToken({ ...req.body });
const { clientHost } = req.settingsService.getSettings();
req.emailService
.buildAndSendEmail(
"employeeActivationTemplate",
{
name: firstname,
link: `${clientHost}/register/${inviteToken.token}`,
},
req.body.email,
"Welcome to Uptime Monitor"
)
.catch((error) => {
logger.error("Error sending invite email", {
service: SERVICE_NAME,
error: error.message,
});
});
return res
.status(200)
.json({ success: true, msg: "Invite sent", data: inviteToken });
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined ? (error.method = "inviteController") : null;
next(error);
return;
}
};
const inviteVerifyController = async (req, res, next) => {
try {
await inviteVerifciationBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
await inviteVerificationBodyValidation.validateAsync(req.body);
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
return;
}
try {
const invite = await req.db.getInviteToken(req.body.token);
res
.status(200)
.json({ status: "success", msg: "Invite verified", data: invite });
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined
? (error.method = "inviteVerifyController")
: null;
next(error);
return;
}
try {
const invite = await req.db.getInviteToken(req.body.token);
res
.status(200)
.json({status: "success", msg: "Invite verified", data: invite});
} catch (error) {
error.service === undefined ? (error.service = SERVICE_NAME) : null;
error.method === undefined
? (error.method = "inviteVerifyController")
: null;
next(error);
}
};
module.exports = {
inviteController,
inviteVerifyController,
inviteController: issueInvitation,
inviteVerifyController,
};
@@ -5,8 +5,9 @@ const {
getMaintenanceWindowsByMonitorIdParamValidation,
} = require("../validation/joi");
const {successMessages} = require("../utils/messages")
const SERVICE_NAME = "maintenanceWindowController";
const { errorMessages, successMessages } = require("../utils/messages");
const createMaintenanceWindow = async (req, res, next) => {
try {
@@ -67,7 +68,7 @@ const getMaintenanceWindowsByUserId = async (req, res, next) => {
return res.status(201).json({
success: true,
msg: successMessages.MAINTEANCE_WINDOW_GET_BY_USER,
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_USER,
data: maintenanceWindows,
});
} catch (error) {
@@ -100,7 +101,7 @@ const getMaintenanceWindowsByMonitorId = async (req, res, next) => {
return res.status(201).json({
success: true,
msg: successMessages.MAINTEANCE_WINDOW_GET_BY_USER,
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_USER,
data: maintenanceWindows,
});
} catch (error) {
+97 -48
View File
@@ -11,8 +11,6 @@ const {
getMonitorStatsByIdParamValidation,
getMonitorStatsByIdQueryValidation,
getCertificateParamValidation,
getMonitorAggregateStatsParamValidation,
getMonitorAggregateStatsQueryValidation,
} = require("../validation/joi");
const sslChecker = require("ssl-checker");
@@ -27,6 +25,7 @@ const logger = require("../utils/logger");
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @param {function} next
* @returns {Promise<Express.Response>}
* @throws {Error}
*/
@@ -50,6 +49,7 @@ const getAllMonitors = async (req, res, next) => {
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @param {function} next
* @returns {Promise<Express.Response>}
* @throws {Error}
*/
@@ -69,7 +69,7 @@ const getMonitorStatsById = async (req, res, next) => {
const monitorStats = await req.db.getMonitorStatsById(req);
return res.json({
success: true,
msg: successMessages.MONTIOR_STATS_BY_ID,
msg: successMessages.MONITOR_STATS_BY_ID,
data: monitorStats,
});
} catch (error) {
@@ -119,12 +119,15 @@ const getMonitorCertificate = async (req, res, next) => {
};
/**
* Returns monitor with matching ID
* Retrieves a monitor by its ID.
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
* @throws {Error}
* @param {Object} req - The Express request object.
* @property {Object} req.params - The parameters of the request.
* @property {string} req.params.monitorId - The ID of the monitor to be retrieved.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message, and the retrieved monitor data.
* @throws {Error} If there is an error during the process, especially if the monitor is not found (404) or if there is a validation error (422).
*/
const getMonitorById = async (req, res, next) => {
try {
@@ -143,12 +146,11 @@ const getMonitorById = async (req, res, next) => {
if (!monitor) {
const error = new Error(errorMessages.MONITOR_GET_BY_ID);
error.status = 404;
throw error;
}
return res.json({
success: true,
msg: successMessages.MONTIOR_GET_BY_ID,
msg: successMessages.MONITOR_GET_BY_ID,
data: monitor,
});
} catch (error) {
@@ -159,14 +161,18 @@ const getMonitorById = async (req, res, next) => {
};
/**
* Returns all monitors and a sumamry for a team with TeamID
* Retrieves all monitors and a summary for a team based on the team ID.
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
* @throws {Error}
* @param {Object} req - The Express request object.
* @property {Object} req.params - The parameters of the request.
* @property {string} req.params.teamId - The ID of the team.
* @property {Object} req.query - The query parameters of the request.
* @property {string} req.query.type - The type of the request.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message, and the data containing the monitors and summary for the team.
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
*/
const getMonitorsAndSummaryByTeamId = async (req, res, next) => {
try {
await getMonitorsAndSummaryByTeamIdParamValidation.validateAsync(
@@ -177,8 +183,7 @@ const getMonitorsAndSummaryByTeamId = async (req, res, next) => {
} catch (error) {
error.status = 422;
error.service = SERVICE_NAME;
error.method === undefined &&
error.method === "getMonitorsAndSummaryByTeamId";
error.method === undefined? error.method = "getMonitorsAndSummaryByTeamId": null;
error.message =
error.details?.[0]?.message || error.message || "Validation Error";
next(error);
@@ -207,12 +212,16 @@ const getMonitorsAndSummaryByTeamId = async (req, res, next) => {
};
/**
* Returns all monitors belong to team with TeamID
* Retrieves all monitors associated with a team by the team's ID.
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
* @throws {Error}
* @param {Object} req - The Express request object.
* @property {Object} req.params - The parameters of the request.
* @property {string} req.params.teamId - The ID of the team.
* @property {Object} req.query - The query parameters of the request.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message, and the data containing the monitors for the team.
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
*/
const getMonitorsByTeamId = async (req, res, next) => {
try {
@@ -243,14 +252,16 @@ const getMonitorsByTeamId = async (req, res, next) => {
};
/**
* Creates a new monitor
* Creates a new monitor and adds it to the job queue.
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
* @throws {Error}
* @param {Object} req - The Express request object.
* @property {Object} req.body - The body of the request.
* @property {Array} req.body.notifications - The notifications associated with the monitor.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the creation of the monitor, and the created monitor data.
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
*/
const createMonitor = async (req, res, next) => {
try {
await createMonitorBodyValidation.validateAsync(req.body);
@@ -269,13 +280,12 @@ const createMonitor = async (req, res, next) => {
const monitor = await req.db.createMonitor(req, res);
if (notifications && notifications.length !== 0) {
const setNotifications = await Promise.all(
notifications.map(async (notification) => {
notification.monitorId = monitor._id;
await req.db.createNotification(notification);
})
monitor.notifications = await Promise.all(
notifications.map(async (notification) => {
notification.monitorId = monitor._id;
await req.db.createNotification(notification);
})
);
monitor.notifications = setNotifications;
await monitor.save();
}
// Add monitor to job queue
@@ -293,14 +303,16 @@ const createMonitor = async (req, res, next) => {
};
/**
* Delete a monitor by ID
* Deletes a monitor by its ID and also deletes associated checks, alerts, and notifications.
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
* @throws {Error}
* @param {Object} req - The Express request object.
* @property {Object} req.params - The parameters of the request.
* @property {string} req.params.monitorId - The ID of the monitor to be deleted.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status and a message indicating the deletion of the monitor.
* @throws {Error} If there is an error during the process, especially if there is a validation error (422) or an error in deleting associated records.
*/
const deleteMonitor = async (req, res, next) => {
try {
await getMonitorByIdParamValidation.validateAsync(req.params);
@@ -331,7 +343,6 @@ const deleteMonitor = async (req, res, next) => {
}
);
}
return res
.status(200)
.json({ success: true, msg: successMessages.MONITOR_DELETE });
@@ -342,7 +353,18 @@ const deleteMonitor = async (req, res, next) => {
}
};
const deleteAllMonitors = async (req, res) => {
/**
* Deletes all monitors associated with a team.
* @async
* @param {Object} req - The Express request object.
* @property {Object} req.headers - The headers of the request.
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
* @param {Object} res - The Express response object.
* @param {function} next
* @returns {Object} The response object with a success status and a message indicating the number of deleted monitors.
* @throws {Error} If there is an error during the deletion process.
*/
const deleteAllMonitors = async (req, res, next) => {
try {
const token = getTokenFromHeaders(req.headers);
const { jwtSecret } = req.settingsService.getSettings();
@@ -367,12 +389,17 @@ const deleteAllMonitors = async (req, res) => {
};
/**
* Edit a monitor by ID
* Edits a monitor by its ID, updates its notifications, and updates its job in the job queue.
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Express.Response>}
* @throws {Error}
* @param {Object} req - The Express request object.
* @property {Object} req.params - The parameters of the request.
* @property {string} req.params.monitorId - The ID of the monitor to be edited.
* @property {Object} req.body - The body of the request.
* @property {Array} req.body.notifications - The notifications to be associated with the monitor.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the editing of the monitor, and the edited monitor data.
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
*/
const editMonitor = async (req, res, next) => {
try {
@@ -423,6 +450,17 @@ const editMonitor = async (req, res, next) => {
}
};
/**
* Pauses or resumes a monitor based on its current state.
* @async
* @param {Object} req - The Express request object.
* @property {Object} req.params - The parameters of the request.
* @property {string} req.params.monitorId - The ID of the monitor to be paused or resumed.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the new state of the monitor, and the updated monitor data.
* @throws {Error} If there is an error during the process.
*/
const pauseMonitor = async (req, res, next) => {
try {
await pauseMonitorParamValidation.validateAsync(req.params);
@@ -458,6 +496,17 @@ const pauseMonitor = async (req, res, next) => {
}
};
/**
* Adds demo monitors for a team.
* @async
* @param {Object} req - The Express request object.
* @property {Object} req.headers - The headers of the request.
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
* @param {Object} res - The Express response object.
* @param {function} next - The next middleware function.
* @returns {Object} The response object with a success status, a message indicating the addition of demo monitors, and the number of demo monitors added.
* @throws {Error} If there is an error during the process.
*/
const addDemoMonitors = async (req, res, next) => {
try {
const token = getTokenFromHeaders(req.headers);
+2 -2
View File
@@ -20,8 +20,8 @@
// The rest of the code is the same, as all the `db` methods are standardized.
// **************************
const Monitor = require("../models/Monitor");
const UserModel = require("../models/User");
const Monitor = require("./models/Monitor");
const UserModel = require("./models/User");
const bcrypt = require("bcrypt");
let FAKE_MONITOR_DATA = [];
File renamed without changes.
@@ -1,6 +1,6 @@
const mongoose = require("mongoose");
const EmailService = require("../service/emailService");
const Notification = require("../models/Notification");
const EmailService = require("../../service/emailService");
const Notification = require("./Notification");
/**
* Check Schema for MongoDB collection.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2 -2
View File
@@ -1,6 +1,6 @@
const mongoose = require("mongoose");
const UserModel = require("../../models/User");
const AppSettings = require("../../models/AppSettings");
const UserModel = require("../models/User");
const AppSettings = require("../models/AppSettings");
//****************************************
// DB Connection
+3 -3
View File
@@ -1,6 +1,6 @@
const Check = require("../../../models/Check");
const Monitor = require("../../../models/Monitor");
const User = require("../../../models/User");
const Check = require("../../models/Check");
const Monitor = require("../../models/Monitor");
const User = require("../../models/User");
const logger = require("../../../utils/logger");
const SERVICE_NAME = "checkModule";
const dateRangeLookup = {
+1 -1
View File
@@ -1,4 +1,4 @@
const InviteToken = require("../../../models/InviteToken");
const InviteToken = require("../../models/InviteToken");
const crypto = require("crypto");
const { errorMessages } = require("../../../utils/messages");
const SERVICE_NAME = "inviteModule";
@@ -1,4 +1,4 @@
const MaintenanceWindow = require("../../../models/MaintenanceWindow");
const MaintenanceWindow = require("../../models/MaintenanceWindow");
const SERVICE_NAME = "maintenanceWindowModule";
/**
+7 -7
View File
@@ -1,8 +1,8 @@
const Monitor = require("../../../models/Monitor");
const Check = require("../../../models/Check");
const PageSpeedCheck = require("../../../models/PageSpeedCheck");
const Monitor = require("../../models/Monitor");
const Check = require("../../models/Check");
const PageSpeedCheck = require("../../models/PageSpeedCheck");
const { errorMessages } = require("../../../utils/messages");
const Notification = require("../../../models/Notification");
const Notification = require("../../models/Notification");
const { NormalizeData } = require("../../../utils/dataUtils");
const demoMonitors = require("../../../utils/demoMonitors.json");
const SERVICE_NAME = "monitorModule";
@@ -147,7 +147,7 @@ const getMonitorStatsById = async (req) => {
let { limit, sortOrder, dateRange, numToDisplay, normalize } = req.query;
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
throw new Error(errorMessages.DB_FIND_MONTIOR_BY_ID(monitorId));
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
}
// This effectively removes limit, returning all checks
if (limit === undefined) limit = 0;
@@ -283,7 +283,7 @@ const getMonitorById = async (monitorId) => {
try {
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
throw new Error(errorMessages.DB_FIND_MONTIOR_BY_ID(monitorId));
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
}
// Get notifications
const notifications = await Notification.find({
@@ -481,7 +481,7 @@ const deleteMonitor = async (req, res) => {
try {
const monitor = await Monitor.findByIdAndDelete(monitorId);
if (!monitor) {
throw new Error(errorMessages.DB_FIND_MONTIOR_BY_ID(monitorId));
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
}
return monitor;
} catch (error) {
@@ -1,4 +1,4 @@
const Notification = require("../../../models/Notification");
const Notification = require("../../models/Notification");
const SERVICE_NAME = "notificationModule";
/**
* Creates a new notification.
@@ -1,4 +1,4 @@
const PageSpeedCheck = require("../../../models/PageSpeedCheck");
const PageSpeedCheck = require("../../models/PageSpeedCheck");
const SERVICE_NAME = "pageSpeedCheckModule";
/**
* Create a PageSpeed check for a monitor
+2 -2
View File
@@ -1,5 +1,5 @@
const UserModel = require("../../../models/User");
const RecoveryToken = require("../../../models/RecoveryToken");
const UserModel = require("../../models/User");
const RecoveryToken = require("../../models/RecoveryToken");
const crypto = require("crypto");
const { errorMessages } = require("../../../utils/messages");
const SERVICE_NAME = "recoveryModule";
+1 -1
View File
@@ -1,4 +1,4 @@
const AppSettings = require("../../../models/AppSettings");
const AppSettings = require("../../models/AppSettings");
const SERVICE_NAME = "SettingsModule";
const getAppSettings = async () => {
+2 -2
View File
@@ -1,5 +1,5 @@
const UserModel = require("../../../models/User");
const TeamModel = require("../../../models/Team");
const UserModel = require("../../models/User");
const TeamModel = require("../../models/Team");
const { errorMessages } = require("../../../utils/messages");
const { GenerateAvatarImage } = require("../../../utils/imageProcessing");
+1 -1
View File
@@ -4,7 +4,7 @@ const SERVICE_NAME = "verifyJWT";
const TOKEN_PREFIX = "Bearer ";
const { errorMessages } = require("../utils/messages");
const { parse } = require("path");
const User = require("../models/User");
const User = require("../db/models/User");
/**
* Verifies the JWT token
* @function
+19 -20
View File
@@ -4,47 +4,46 @@ const { verifyOwnership } = require("../middleware/verifyOwnership");
const { isAllowed } = require("../middleware/isAllowed");
const multer = require("multer");
const upload = multer();
const User = require("../models/User");
const User = require("../db/models/User");
const {
registerController,
loginController,
logoutController,
userEditController,
recoveryRequestController,
validateRecoveryTokenController,
resetPasswordController,
checkSuperadminController,
getAllUsersController,
deleteUserController,
registerUser,
loginUser,
editUser,
requestRecovery,
validateRecovery,
resetPassword,
checkSuperadminExists,
getAllUsers,
deleteUser,
} = require("../controllers/authController");
//Auth routes
router.post("/register", upload.single("profileImage"), registerController);
router.post("/login", loginController);
router.post("/register", upload.single("profileImage"), registerUser);
router.post("/login", loginUser);
router.put(
"/user/:userId",
upload.single("profileImage"),
verifyJWT,
userEditController
editUser
);
router.get("/users/superadmin", checkSuperadminController);
router.get("/users/superadmin", checkSuperadminExists);
router.get(
"/users",
verifyJWT,
isAllowed(["admin", "superadmin"]),
getAllUsersController
getAllUsers
);
router.delete(
"/user/:userId",
verifyJWT,
verifyOwnership(User, "userId"),
deleteUserController
deleteUser
);
//Recovery routes
router.post("/recovery/request", recoveryRequestController);
router.post("/recovery/validate", validateRecoveryTokenController);
router.post("/recovery/reset/", resetPasswordController);
router.post("/recovery/request", requestRecovery);
router.post("/recovery/validate", validateRecovery);
router.post("/recovery/reset/", resetPassword);
module.exports = router;
+1 -1
View File
@@ -2,7 +2,7 @@ const router = require("express").Router();
const checkController = require("../controllers/checkController");
const { verifyOwnership } = require("../middleware/verifyOwnership");
const { isAllowed } = require("../middleware/isAllowed");
const Monitor = require("../models/Monitor");
const Monitor = require("../db/models/Monitor");
router.get("/:monitorId", checkController.getChecks);
router.post(
+1 -1
View File
@@ -1,7 +1,7 @@
const router = require("express").Router();
const maintenanceWindowController = require("../controllers/maintenanceWindowController");
const { verifyOwnership } = require("../middleware/verifyOwnership");
const Monitor = require("../models/Monitor");
const Monitor = require("../db/models/Monitor");
router.get(
"/monitor/:monitorId",
+1 -1
View File
@@ -1,7 +1,7 @@
const router = require("express").Router();
const settingsController = require("../controllers/settingsController");
const { isAllowed } = require("../middleware/isAllowed");
const Monitor = require("../models/Monitor");
const Monitor = require("../db/models/Monitor");
router.get("/", settingsController.getAppSettings);
router.put(
+1 -2
View File
@@ -1,7 +1,6 @@
const { env } = require("process");
const AppSettings = require("../models/AppSettings");
const SERVICE_NAME = "SettingsService";
// Load settings from environment variables
const envConfig = {
logLevel: undefined,
apiBaseUrl: undefined,
+6 -7
View File
@@ -13,7 +13,7 @@ const errorMessages = {
NO_AUTH_TOKEN: "No auth token provided",
INVALID_AUTH_TOKEN: "Invalid auth token",
//Onwership Middleware
//Ownership Middleware
VERIFY_OWNER_NOT_FOUND: "Document not found",
VERIFY_OWNER_UNAUTHORIZED: "Unauthorized access",
@@ -26,17 +26,16 @@ const errorMessages = {
DB_TOKEN_NOT_FOUND: "Token not found",
DB_RESET_PASSWORD_BAD_MATCH:
"New password must be different from old password",
DB_FIND_MONTIOR_BY_ID: (monitorId) =>
DB_FIND_MONITOR_BY_ID: (monitorId) =>
`Monitor with id ${monitorId} not found`,
DB_DELETE_CHECKS: (monitorId) =>
`No checks found for monitor with id ${monitorId}`,
DB_DELETE_ALERT: (alertId) => `Alert with id ${alertId} not found`,
//Auth errors
AUTH_INCORRECT_PASSWORD: "Incorrect password",
AUTH_UNAUTHORIZED: "Unauthorized access",
// Monitor Errros
// Monitor Errors
MONITOR_GET_BY_ID: "Monitor not found",
MONITOR_GET_BY_USER_ID: "No monitors found for user",
@@ -77,8 +76,8 @@ const successMessages = {
//Monitor Controller
MONITOR_GET_ALL: "Got all monitors successfully",
MONTIOR_STATS_BY_ID: "Got monitor stats by Id successfully",
MONTIOR_GET_BY_ID: "Got monitor by Id successfully",
MONITOR_STATS_BY_ID: "Got monitor stats by Id successfully",
MONITOR_GET_BY_ID: "Got monitor by Id successfully",
MONITOR_GET_BY_USER_ID: (userId) => `Got monitor for ${userId} successfully"`,
MONITOR_CREATE: "Monitor created successfully",
MONITOR_DELETE: "Monitor deleted successfully",
@@ -94,7 +93,7 @@ const successMessages = {
//Maintenance Window Controller
MAINTENANCE_WINDOW_CREATE: "Maintenance Window created successfully",
MAINTEANCE_WINDOW_GET_BY_USER: "Got Maintenance Windows by User successfully",
MAINTENANCE_WINDOW_GET_BY_USER: "Got Maintenance Windows by User successfully",
//Ping Operations
PING_SUCCESS: "Success",
+1 -1
View File
@@ -410,7 +410,7 @@ module.exports = {
newPasswordValidation,
inviteRoleValidation,
inviteBodyValidation,
inviteVerifciationBodyValidation,
inviteVerificationBodyValidation: inviteVerifciationBodyValidation,
createMonitorBodyValidation,
getMonitorByIdParamValidation,
getMonitorByIdQueryValidation,