Merge branch 'develop' into 915-be-add-middeware-for-verification-of-refresh-token
This commit is contained in:
commit
090f0df3e8
78 files changed
+10826
-11692
No files matched your search
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
require: ["esm", "chai/register-expect.js"], // Include Chai's "expect" interface globally
|
||||
spec: "tests/**/*.test.js", // Specify test files
|
||||
timeout: 5000, // Set test-case timeout in milliseconds
|
||||
recursive: true, // Include subdirectories
|
||||
reporter: "spec", // Use the "spec" reporter
|
||||
exit: true, // Force Mocha to quit after tests complete
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
module.exports = {
|
||||
require: ["chai/register-expect.js"], // Include Chai's "expect" interface globally
|
||||
spec: "tests/**/*.test.js", // Specify test files
|
||||
timeout: 5000, // Set test-case timeout in milliseconds
|
||||
recursive: true, // Include subdirectories
|
||||
reporter: "spec", // Use the "spec" reporter
|
||||
exit: true, // Force Mocha to quit after tests complete
|
||||
};
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"all": true,
|
||||
"include": ["controllers/*.js"],
|
||||
"exclude": ["**/*.test.js"],
|
||||
"reporter": ["html", "text", "lcov"],
|
||||
"sourceMap": false,
|
||||
"instrument": true
|
||||
"all": true,
|
||||
"include": ["controllers/*.js", "utils/*.js"],
|
||||
"exclude": ["**/*.test.js"],
|
||||
"reporter": ["html", "text", "lcov"],
|
||||
"sourceMap": false,
|
||||
"instrument": true
|
||||
}
|
||||
@@ -12,4 +12,4 @@ const connectDbAndRunServer = async (app, db) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { connectDbAndRunServer };
|
||||
export { connectDbAndRunServer };
|
||||
@@ -1,20 +1,21 @@
|
||||
const {
|
||||
registrationBodyValidation,
|
||||
loginValidation,
|
||||
editUserParamValidation,
|
||||
editUserBodyValidation,
|
||||
recoveryValidation,
|
||||
recoveryTokenValidation,
|
||||
newPasswordValidation,
|
||||
} = require("../validation/joi");
|
||||
const logger = require("../utils/logger");
|
||||
require("dotenv").config();
|
||||
const { errorMessages, successMessages } = require("../utils/messages");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const SERVICE_NAME = "AuthController";
|
||||
const { getTokenFromHeaders, tokenType } = require("../utils/utils");
|
||||
const crypto = require("crypto");
|
||||
const { handleValidationError, handleError } = require("./controllerUtils");
|
||||
import {
|
||||
registrationBodyValidation,
|
||||
loginValidation,
|
||||
editUserParamValidation,
|
||||
editUserBodyValidation,
|
||||
recoveryValidation,
|
||||
recoveryTokenValidation,
|
||||
newPasswordValidation,
|
||||
} from "../validation/joi.js";
|
||||
import logger from "../utils/logger.js";
|
||||
import dotenv from "dotenv";
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { getTokenFromHeaders, tokenType } from "../utils/utils.js";
|
||||
import crypto from "crypto";
|
||||
import { handleValidationError, handleError } from "./controllerUtils.js";
|
||||
const SERVICE_NAME = "authController";
|
||||
dotenv.config();
|
||||
|
||||
/**
|
||||
* Creates and returns JWT token with an arbitrary payload
|
||||
@@ -26,15 +27,21 @@ const { handleValidationError, handleError } = require("./controllerUtils");
|
||||
* @throws {Error}
|
||||
*/
|
||||
const issueToken = (payload, typeOfToken, appSettings) => {
|
||||
try {
|
||||
const tokenTTL = (typeOfToken === tokenType.REFRESH_TOKEN) ? (appSettings?.refreshTokenTTL?? "7d") : (appSettings?.jwtTTL?? "2h");
|
||||
const tokenSecret = (typeOfToken === tokenType.REFRESH_TOKEN) ? appSettings?.refreshTokenSecret : appSettings?.jwtSecret;
|
||||
const payloadData = (typeOfToken === tokenType.REFRESH_TOKEN) ? {} : payload;
|
||||
try {
|
||||
const tokenTTL =
|
||||
typeOfToken === tokenType.REFRESH_TOKEN
|
||||
? (appSettings?.refreshTokenTTL ?? "7d")
|
||||
: (appSettings?.jwtTTL ?? "2h");
|
||||
const tokenSecret =
|
||||
typeOfToken === tokenType.REFRESH_TOKEN
|
||||
? appSettings?.refreshTokenSecret
|
||||
: appSettings?.jwtSecret;
|
||||
const payloadData = typeOfToken === tokenType.REFRESH_TOKEN ? {} : payload;
|
||||
|
||||
return jwt.sign(payloadData, tokenSecret, { expiresIn: tokenTTL });
|
||||
} catch (error) {
|
||||
throw handleError(error, SERVICE_NAME, "issueToken");
|
||||
}
|
||||
return jwt.sign(payloadData, tokenSecret, { expiresIn: tokenTTL });
|
||||
} catch (error) {
|
||||
throw handleError(error, SERVICE_NAME, "issueToken");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -50,66 +57,65 @@ const issueToken = (payload, typeOfToken, 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, tokenType.ACCESS_TOKEN, appSettings);
|
||||
const refreshToken = issueToken({}, tokenType.REFRESH_TOKEN, appSettings);
|
||||
const token = issueToken(userForToken, tokenType.ACCESS_TOKEN, appSettings);
|
||||
const refreshToken = issueToken({}, tokenType.REFRESH_TOKEN, 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, refreshToken: refreshToken },
|
||||
});
|
||||
} 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, refreshToken: refreshToken },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "registerController"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -125,45 +131,46 @@ 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, tokenType.ACCESS_TOKEN, appSettings);
|
||||
const refreshToken = issueToken({}, tokenType.REFRESH_TOKEN, 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, refreshToken: refreshToken },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "loginController"));
|
||||
}
|
||||
// Happy path, return token
|
||||
const appSettings = await req.settingsService.getSettings();
|
||||
const token = issueToken(userWithoutPassword, tokenType.ACCESS_TOKEN, appSettings);
|
||||
const refreshToken = issueToken({}, tokenType.REFRESH_TOKEN, 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, refreshToken: refreshToken },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "loginUser"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -181,58 +188,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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -244,17 +251,17 @@ const editUser = async (req, res, next) => {
|
||||
* @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) {
|
||||
next(handleError(error, SERVICE_NAME, "checkSuperadminController"));
|
||||
}
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -269,46 +276,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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -323,23 +330,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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -355,26 +362,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, tokenType.ACCESS_TOKEN, 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, tokenType.ACCESS_TOKEN, appSettings);
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_RESET_PASSWORD,
|
||||
data: { user, token },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "resetPasswordController"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -387,74 +394,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) => {
|
||||
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"));
|
||||
}
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
issueToken,
|
||||
registerUser,
|
||||
loginUser,
|
||||
editUser,
|
||||
checkSuperadminExists: checkSuperAdminExists,
|
||||
requestRecovery,
|
||||
validateRecovery,
|
||||
resetPassword,
|
||||
deleteUser,
|
||||
getAllUsers,
|
||||
export {
|
||||
issueToken,
|
||||
registerUser,
|
||||
loginUser,
|
||||
editUser,
|
||||
checkSuperadminExists,
|
||||
requestRecovery,
|
||||
validateRecovery,
|
||||
resetPassword,
|
||||
deleteUser,
|
||||
getAllUsers,
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
const {
|
||||
import {
|
||||
createCheckParamValidation,
|
||||
createCheckBodyValidation,
|
||||
getChecksParamValidation,
|
||||
@@ -8,12 +8,13 @@ const {
|
||||
deleteChecksParamValidation,
|
||||
deleteChecksByTeamIdParamValidation,
|
||||
updateChecksTTLBodyValidation,
|
||||
} = require("../validation/joi");
|
||||
const { successMessages } = require("../utils/messages");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const { getTokenFromHeaders } = require("../utils/utils");
|
||||
} from "../validation/joi.js";
|
||||
import { successMessages } from "../utils/messages.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { getTokenFromHeaders } from "../utils/utils.js";
|
||||
import { handleValidationError, handleError } from "./controllerUtils.js";
|
||||
|
||||
const SERVICE_NAME = "checkController";
|
||||
const { handleValidationError, handleError } = require("./controllerUtils");
|
||||
|
||||
const createCheck = async (req, res, next) => {
|
||||
try {
|
||||
@@ -143,7 +144,7 @@ const updateChecksTTL = async (req, res, next) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
createCheck,
|
||||
getChecks,
|
||||
getTeamChecks,
|
||||
|
||||
@@ -1,19 +1,43 @@
|
||||
const handleValidationError = (error, serviceName) => {
|
||||
error.status = 422;
|
||||
error.service = serviceName;
|
||||
error.message =
|
||||
error.details?.[0]?.message || error.message || "Validation Error";
|
||||
return error;
|
||||
error.status = 422;
|
||||
error.service = serviceName;
|
||||
error.message = error.details?.[0]?.message || error.message || "Validation Error";
|
||||
return error;
|
||||
};
|
||||
|
||||
const handleError = (error, serviceName, method, status = 500) => {
|
||||
error.status === undefined ? (error.status = status) : null;
|
||||
error.service === undefined ? (error.service = serviceName) : null;
|
||||
error.method === undefined ? (error.method = method) : null;
|
||||
return error;
|
||||
error.status === undefined ? (error.status = status) : null;
|
||||
error.service === undefined ? (error.service = serviceName) : null;
|
||||
error.method === undefined ? (error.method = method) : null;
|
||||
return error;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
handleValidationError,
|
||||
handleError,
|
||||
const fetchMonitorCertificate = async (tls, monitor) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const monitorUrl = new URL(monitor.url);
|
||||
const hostname = monitorUrl.hostname;
|
||||
try {
|
||||
let socket = tls.connect(
|
||||
{
|
||||
port: 443,
|
||||
host: hostname,
|
||||
servername: hostname, // this is required in case the server enabled SNI
|
||||
},
|
||||
() => {
|
||||
try {
|
||||
let x509Certificate = socket.getPeerX509Certificate();
|
||||
resolve(x509Certificate);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
} finally {
|
||||
socket.end();
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export { handleValidationError, handleError, fetchMonitorCertificate };
|
||||
@@ -1,14 +1,17 @@
|
||||
const {
|
||||
import {
|
||||
inviteRoleValidation,
|
||||
inviteBodyValidation,
|
||||
inviteVerificationBodyValidation,
|
||||
} = require("../validation/joi");
|
||||
const logger = require("../utils/logger");
|
||||
require("dotenv").config();
|
||||
const jwt = require("jsonwebtoken");
|
||||
const { handleError, handleValidationError } = require("./controllerUtils");
|
||||
} from "../validation/joi.js";
|
||||
import logger from "../utils/logger.js";
|
||||
import dotenv from "dotenv";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { handleError, handleValidationError } from "./controllerUtils.js";
|
||||
import { getTokenFromHeaders } from "../utils/utils.js";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const SERVICE_NAME = "inviteController";
|
||||
const { getTokenFromHeaders } = require("../utils/utils");
|
||||
|
||||
/**
|
||||
* Issues an invitation to a new user. Only admins can invite new users. An invitation token is created and sent via email.
|
||||
@@ -82,7 +85,4 @@ const inviteVerifyController = async (req, res, next) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
issueInvitation,
|
||||
inviteVerifyController,
|
||||
};
|
||||
export { issueInvitation, inviteVerifyController };
|
||||
@@ -1,4 +1,4 @@
|
||||
const {
|
||||
import {
|
||||
createMaintenanceWindowBodyValidation,
|
||||
editMaintenanceWindowByIdParamValidation,
|
||||
editMaintenanceByIdWindowBodyValidation,
|
||||
@@ -6,11 +6,12 @@ const {
|
||||
getMaintenanceWindowsByMonitorIdParamValidation,
|
||||
getMaintenanceWindowsByTeamIdQueryValidation,
|
||||
deleteMaintenanceWindowByIdParamValidation,
|
||||
} = require("../validation/joi");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const { getTokenFromHeaders } = require("../utils/utils");
|
||||
const { successMessages } = require("../utils/messages");
|
||||
const { handleValidationError, handleError } = require("./controllerUtils");
|
||||
} from "../validation/joi.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { getTokenFromHeaders } from "../utils/utils.js";
|
||||
import { successMessages } from "../utils/messages.js";
|
||||
import { handleValidationError, handleError } from "./controllerUtils.js";
|
||||
|
||||
const SERVICE_NAME = "maintenanceWindowController";
|
||||
|
||||
const createMaintenanceWindows = async (req, res, next) => {
|
||||
@@ -160,7 +161,7 @@ const editMaintenanceWindow = async (req, res, next) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
createMaintenanceWindows,
|
||||
getMaintenanceWindowById,
|
||||
getMaintenanceWindowsByTeamId,
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
const {
|
||||
getMonitorByIdParamValidation,
|
||||
getMonitorByIdQueryValidation,
|
||||
getMonitorsByTeamIdValidation,
|
||||
createMonitorBodyValidation,
|
||||
editMonitorBodyValidation,
|
||||
getMonitorsAndSummaryByTeamIdParamValidation,
|
||||
getMonitorsAndSummaryByTeamIdQueryValidation,
|
||||
getMonitorsByTeamIdQueryValidation,
|
||||
pauseMonitorParamValidation,
|
||||
getMonitorStatsByIdParamValidation,
|
||||
getMonitorStatsByIdQueryValidation,
|
||||
getCertificateParamValidation,
|
||||
} = require("../validation/joi");
|
||||
import {
|
||||
getMonitorByIdParamValidation,
|
||||
getMonitorByIdQueryValidation,
|
||||
getMonitorsByTeamIdValidation,
|
||||
createMonitorBodyValidation,
|
||||
editMonitorBodyValidation,
|
||||
getMonitorsAndSummaryByTeamIdParamValidation,
|
||||
getMonitorsAndSummaryByTeamIdQueryValidation,
|
||||
getMonitorsByTeamIdQueryValidation,
|
||||
pauseMonitorParamValidation,
|
||||
getMonitorStatsByIdParamValidation,
|
||||
getMonitorStatsByIdQueryValidation,
|
||||
getCertificateParamValidation,
|
||||
} from "../validation/joi.js";
|
||||
import * as tls from "tls";
|
||||
|
||||
const sslChecker = require("ssl-checker");
|
||||
const SERVICE_NAME = "monitorController";
|
||||
const { errorMessages, successMessages } = require("../utils/messages");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const { getTokenFromHeaders } = require("../utils/utils");
|
||||
const logger = require("../utils/logger");
|
||||
const { handleError, handleValidationError } = require("./controllerUtils");
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { getTokenFromHeaders } from "../utils/utils.js";
|
||||
import logger from "../utils/logger.js";
|
||||
import {
|
||||
handleError,
|
||||
handleValidationError,
|
||||
fetchMonitorCertificate,
|
||||
} from "./controllerUtils.js";
|
||||
|
||||
/**
|
||||
* Returns all monitors
|
||||
@@ -31,16 +35,16 @@ const { handleError, handleValidationError } = require("./controllerUtils");
|
||||
* @throws {Error}
|
||||
*/
|
||||
const getAllMonitors = async (req, res, next) => {
|
||||
try {
|
||||
const monitors = await req.db.getAllMonitors();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_ALL,
|
||||
data: monitors,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAllMonitors"));
|
||||
}
|
||||
try {
|
||||
const monitors = await req.db.getAllMonitors();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_ALL,
|
||||
data: monitors,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAllMonitors"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -53,56 +57,55 @@ const getAllMonitors = async (req, res, next) => {
|
||||
* @throws {Error}
|
||||
*/
|
||||
const getMonitorStatsById = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorStatsByIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorStatsByIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await getMonitorStatsByIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorStatsByIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const monitorStats = await req.db.getMonitorStatsById(req);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_STATS_BY_ID,
|
||||
data: monitorStats,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorStatsById"));
|
||||
}
|
||||
try {
|
||||
const monitorStats = await req.db.getMonitorStatsById(req);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_STATS_BY_ID,
|
||||
data: monitorStats,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorStatsById"));
|
||||
}
|
||||
};
|
||||
|
||||
const getMonitorCertificate = async (req, res, next) => {
|
||||
try {
|
||||
await getCertificateParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
}
|
||||
const getMonitorCertificate = async (req, res, next, fetchMonitorCertificate) => {
|
||||
try {
|
||||
await getCertificateParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
}
|
||||
|
||||
try {
|
||||
const { monitorId } = req.params;
|
||||
const monitor = await req.db.getMonitorById(monitorId);
|
||||
const monitorUrl = new URL(monitor.url);
|
||||
const certificate = await sslChecker(monitorUrl.hostname);
|
||||
if (certificate && certificate.validTo) {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_CERTIFICATE,
|
||||
data: {
|
||||
certificateDate: new Date(certificate.validTo).toLocaleDateString(),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_CERTIFICATE,
|
||||
data: { certificateDate: "N/A" },
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorCertificate"));
|
||||
}
|
||||
try {
|
||||
const { monitorId } = req.params;
|
||||
const monitor = await req.db.getMonitorById(monitorId);
|
||||
const certificate = await fetchMonitorCertificate(tls, monitor);
|
||||
if (certificate && certificate.validTo) {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_CERTIFICATE,
|
||||
data: {
|
||||
certificateDate: new Date(certificate.validTo),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_CERTIFICATE,
|
||||
data: { certificateDate: "N/A" },
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorCertificate"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -117,30 +120,30 @@ const getMonitorCertificate = async (req, res, next) => {
|
||||
* @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 {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorByIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorByIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const monitor = await req.db.getMonitorById(req.params.monitorId);
|
||||
if (!monitor) {
|
||||
const error = new Error(errorMessages.MONITOR_GET_BY_ID);
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
try {
|
||||
const monitor = await req.db.getMonitorById(req.params.monitorId);
|
||||
if (!monitor) {
|
||||
const error = new Error(errorMessages.MONITOR_GET_BY_ID);
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_ID,
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorById"));
|
||||
}
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_ID,
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorById"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -157,31 +160,26 @@ const getMonitorById = async (req, res, next) => {
|
||||
* @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(
|
||||
req.params
|
||||
);
|
||||
await getMonitorsAndSummaryByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await getMonitorsAndSummaryByTeamIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorsAndSummaryByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { teamId } = req.params;
|
||||
const { type } = req.query;
|
||||
const monitorsSummary = await req.db.getMonitorsAndSummaryByTeamId(
|
||||
teamId,
|
||||
type
|
||||
);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_USER_ID(teamId),
|
||||
data: monitorsSummary,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorsAndSummaryByTeamId"));
|
||||
}
|
||||
try {
|
||||
const { teamId } = req.params;
|
||||
const { type } = req.query;
|
||||
const monitorsSummary = await req.db.getMonitorsAndSummaryByTeamId(teamId, type);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_USER_ID(teamId),
|
||||
data: monitorsSummary,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorsAndSummaryByTeamId"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -197,26 +195,26 @@ const getMonitorsAndSummaryByTeamId = async (req, res, next) => {
|
||||
* @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 {
|
||||
await getMonitorsByTeamIdValidation.validateAsync(req.params);
|
||||
await getMonitorsByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await getMonitorsByTeamIdValidation.validateAsync(req.params);
|
||||
await getMonitorsByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const teamId = req.params.teamId;
|
||||
const monitors = await req.db.getMonitorsByTeamId(req, res);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_USER_ID(teamId),
|
||||
data: monitors,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorsByTeamId"));
|
||||
next(error);
|
||||
}
|
||||
try {
|
||||
const teamId = req.params.teamId;
|
||||
const monitors = await req.db.getMonitorsByTeamId(req, res);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_USER_ID(teamId),
|
||||
data: monitors,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorsByTeamId"));
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -231,36 +229,36 @@ const getMonitorsByTeamId = async (req, res, next) => {
|
||||
* @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);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await createMonitorBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const notifications = req.body.notifications;
|
||||
const monitor = await req.db.createMonitor(req, res);
|
||||
try {
|
||||
const notifications = req.body.notifications;
|
||||
const monitor = await req.db.createMonitor(req, res);
|
||||
|
||||
if (notifications && notifications.length !== 0) {
|
||||
monitor.notifications = await Promise.all(
|
||||
notifications.map(async (notification) => {
|
||||
notification.monitorId = monitor._id;
|
||||
await req.db.createNotification(notification);
|
||||
})
|
||||
);
|
||||
await monitor.save();
|
||||
}
|
||||
// Add monitor to job queue
|
||||
req.jobQueue.addJob(monitor._id, monitor);
|
||||
return res.status(201).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_CREATE,
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "createMonitor"));
|
||||
}
|
||||
if (notifications && notifications.length !== 0) {
|
||||
monitor.notifications = await Promise.all(
|
||||
notifications.map(async (notification) => {
|
||||
notification.monitorId = monitor._id;
|
||||
await req.db.createNotification(notification);
|
||||
})
|
||||
);
|
||||
await monitor.save();
|
||||
}
|
||||
// Add monitor to job queue
|
||||
req.jobQueue.addJob(monitor._id, monitor);
|
||||
return res.status(201).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_CREATE,
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "createMonitor"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -275,37 +273,35 @@ const createMonitor = async (req, res, next) => {
|
||||
* @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);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const monitor = await req.db.deleteMonitor(req, res, next);
|
||||
// Delete associated checks,alerts,and notifications
|
||||
try {
|
||||
await req.jobQueue.deleteJob(monitor);
|
||||
await req.db.deleteChecks(monitor._id);
|
||||
await req.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
||||
await req.db.deleteNotificationsByMonitorId(monitor._id);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
||||
{
|
||||
method: "deleteMonitor",
|
||||
service: SERVICE_NAME,
|
||||
error: error.message,
|
||||
}
|
||||
);
|
||||
}
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: successMessages.MONITOR_DELETE });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteMonitor"));
|
||||
}
|
||||
try {
|
||||
const monitor = await req.db.deleteMonitor(req, res, next);
|
||||
// Delete associated checks,alerts,and notifications
|
||||
try {
|
||||
await req.jobQueue.deleteJob(monitor);
|
||||
await req.db.deleteChecks(monitor._id);
|
||||
await req.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
||||
await req.db.deleteNotificationsByMonitorId(monitor._id);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
||||
{
|
||||
method: "deleteMonitor",
|
||||
service: SERVICE_NAME,
|
||||
error: error.message,
|
||||
}
|
||||
);
|
||||
}
|
||||
return res.status(200).json({ success: true, msg: successMessages.MONITOR_DELETE });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteMonitor"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -320,34 +316,34 @@ const deleteMonitor = async (req, res, next) => {
|
||||
* @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();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const { monitors, deletedCount } = await req.db.deleteAllMonitors(teamId);
|
||||
await Promise.all(
|
||||
monitors.map(async (monitor) => {
|
||||
try {
|
||||
await req.jobQueue.deleteJob(monitor);
|
||||
await req.db.deleteChecks(monitor._id);
|
||||
await req.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
||||
await req.db.deleteNotificationsByMonitorId(monitor._id);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
||||
{
|
||||
method: "deleteAllMonitors",
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: `Deleted ${deletedCount} monitors` });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteAllMonitors"));
|
||||
}
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = req.settingsService.getSettings();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const { monitors, deletedCount } = await req.db.deleteAllMonitors(teamId);
|
||||
await Promise.all(
|
||||
monitors.map(async (monitor) => {
|
||||
try {
|
||||
await req.jobQueue.deleteJob(monitor);
|
||||
await req.db.deleteChecks(monitor._id);
|
||||
await req.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
||||
await req.db.deleteNotificationsByMonitorId(monitor._id);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
||||
{
|
||||
method: "deleteAllMonitors",
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: `Deleted ${deletedCount} monitors` });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteAllMonitors"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -364,46 +360,46 @@ const deleteAllMonitors = async (req, res, next) => {
|
||||
* @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 {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
await editMonitorBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
await editMonitorBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { monitorId } = req.params;
|
||||
const monitorBeforeEdit = await req.db.getMonitorById(monitorId);
|
||||
try {
|
||||
const { monitorId } = req.params;
|
||||
const monitorBeforeEdit = await req.db.getMonitorById(monitorId);
|
||||
|
||||
// Get notifications from the request body
|
||||
const notifications = req.body.notifications;
|
||||
// Get notifications from the request body
|
||||
const notifications = req.body.notifications;
|
||||
|
||||
const editedMonitor = await req.db.editMonitor(monitorId, req.body);
|
||||
const editedMonitor = await req.db.editMonitor(monitorId, req.body);
|
||||
|
||||
await req.db.deleteNotificationsByMonitorId(editedMonitor._id);
|
||||
await req.db.deleteNotificationsByMonitorId(editedMonitor._id);
|
||||
|
||||
if (notifications && notifications.length !== 0) {
|
||||
await Promise.all(
|
||||
notifications.map(async (notification) => {
|
||||
notification.monitorId = editedMonitor._id;
|
||||
await req.db.createNotification(notification);
|
||||
})
|
||||
);
|
||||
}
|
||||
if (notifications && notifications.length !== 0) {
|
||||
await Promise.all(
|
||||
notifications.map(async (notification) => {
|
||||
notification.monitorId = editedMonitor._id;
|
||||
await req.db.createNotification(notification);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Delete the old job(editedMonitor has the same ID as the old monitor)
|
||||
await req.jobQueue.deleteJob(monitorBeforeEdit);
|
||||
// Add the new job back to the queue
|
||||
await req.jobQueue.addJob(editedMonitor._id, editedMonitor);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_EDIT,
|
||||
data: editedMonitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "editMonitor"));
|
||||
}
|
||||
// Delete the old job(editedMonitor has the same ID as the old monitor)
|
||||
await req.jobQueue.deleteJob(monitorBeforeEdit);
|
||||
// Add the new job back to the queue
|
||||
await req.jobQueue.addJob(editedMonitor._id, editedMonitor);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_EDIT,
|
||||
data: editedMonitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "editMonitor"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -418,32 +414,32 @@ const editMonitor = async (req, res, next) => {
|
||||
* @throws {Error} If there is an error during the process.
|
||||
*/
|
||||
const pauseMonitor = async (req, res, next) => {
|
||||
try {
|
||||
await pauseMonitorParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
}
|
||||
try {
|
||||
await pauseMonitorParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
}
|
||||
|
||||
try {
|
||||
const monitor = await req.db.getMonitorById(req.params.monitorId);
|
||||
if (monitor.isActive) {
|
||||
await req.jobQueue.deleteJob(monitor);
|
||||
} else {
|
||||
await req.jobQueue.addJob(monitor._id, monitor);
|
||||
}
|
||||
monitor.isActive = !monitor.isActive;
|
||||
monitor.status = undefined;
|
||||
monitor.save();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: monitor.isActive
|
||||
? successMessages.MONITOR_RESUME
|
||||
: successMessages.MONITOR_PAUSE,
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "pauseMonitor"));
|
||||
}
|
||||
try {
|
||||
const monitor = await req.db.getMonitorById(req.params.monitorId);
|
||||
if (monitor.isActive) {
|
||||
await req.jobQueue.deleteJob(monitor);
|
||||
} else {
|
||||
await req.jobQueue.addJob(monitor._id, monitor);
|
||||
}
|
||||
monitor.isActive = !monitor.isActive;
|
||||
monitor.status = undefined;
|
||||
monitor.save();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: monitor.isActive
|
||||
? successMessages.MONITOR_RESUME
|
||||
: successMessages.MONITOR_PAUSE,
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "pauseMonitor"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -458,36 +454,36 @@ const pauseMonitor = async (req, res, next) => {
|
||||
* @throws {Error} If there is an error during the process.
|
||||
*/
|
||||
const addDemoMonitors = async (req, res, next) => {
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = req.settingsService.getSettings();
|
||||
const { _id, teamId } = jwt.verify(token, jwtSecret);
|
||||
const demoMonitors = await req.db.addDemoMonitors(_id, teamId);
|
||||
await Promise.all(
|
||||
demoMonitors.map((monitor) => req.jobQueue.addJob(monitor._id, monitor))
|
||||
);
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = req.settingsService.getSettings();
|
||||
const { _id, teamId } = jwt.verify(token, jwtSecret);
|
||||
const demoMonitors = await req.db.addDemoMonitors(_id, teamId);
|
||||
await Promise.all(
|
||||
demoMonitors.map((monitor) => req.jobQueue.addJob(monitor._id, monitor))
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_DEMO_ADDED,
|
||||
data: demoMonitors.length,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "addDemoMonitors"));
|
||||
}
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_DEMO_ADDED,
|
||||
data: demoMonitors.length,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "addDemoMonitors"));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getAllMonitors,
|
||||
getMonitorStatsById,
|
||||
getMonitorCertificate,
|
||||
getMonitorById,
|
||||
getMonitorsAndSummaryByTeamId,
|
||||
getMonitorsByTeamId,
|
||||
createMonitor,
|
||||
deleteMonitor,
|
||||
deleteAllMonitors,
|
||||
editMonitor,
|
||||
pauseMonitor,
|
||||
addDemoMonitors,
|
||||
export {
|
||||
getAllMonitors,
|
||||
getMonitorStatsById,
|
||||
getMonitorCertificate,
|
||||
getMonitorById,
|
||||
getMonitorsAndSummaryByTeamId,
|
||||
getMonitorsByTeamId,
|
||||
createMonitor,
|
||||
deleteMonitor,
|
||||
deleteAllMonitors,
|
||||
editMonitor,
|
||||
pauseMonitor,
|
||||
addDemoMonitors,
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
const { handleError } = require("./controllerUtils");
|
||||
const { errorMessages, successMessages } = require("../utils/messages");
|
||||
import { handleError } from "./controllerUtils.js";
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
|
||||
const SERVICE_NAME = "JobQueueController";
|
||||
|
||||
const getMetrics = async (req, res, next) => {
|
||||
@@ -55,9 +56,4 @@ const obliterateQueue = async (req, res, next) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getMetrics,
|
||||
getJobs,
|
||||
addJob,
|
||||
obliterateQueue,
|
||||
};
|
||||
export { getMetrics, getJobs, addJob, obliterateQueue };
|
||||
@@ -1,7 +1,7 @@
|
||||
const { successMessages } = require("../utils/messages");
|
||||
import { successMessages } from "../utils/messages.js";
|
||||
import { updateAppSettingsBodyValidation } from "../validation/joi.js";
|
||||
import { handleValidationError, handleError } from "./controllerUtils.js";
|
||||
const SERVICE_NAME = "SettingsController";
|
||||
const { updateAppSettingsBodyValidation } = require("../validation/joi");
|
||||
const { handleValidationError, handleError } = require("./controllerUtils");
|
||||
|
||||
const getAppSettings = async (req, res, next) => {
|
||||
try {
|
||||
@@ -39,7 +39,4 @@ const updateAppSettings = async (req, res, next) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getAppSettings,
|
||||
updateAppSettings,
|
||||
};
|
||||
export { getAppSettings, updateAppSettings };
|
||||
@@ -1,4 +1,4 @@
|
||||
const mongoose = require("mongoose");
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const AppSettingsSchema = mongoose.Schema(
|
||||
{
|
||||
@@ -88,4 +88,4 @@ const AppSettingsSchema = mongoose.Schema(
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = mongoose.model("AppSettings", AppSettingsSchema);
|
||||
export default mongoose.model("AppSettings", AppSettingsSchema);
|
||||
@@ -1,6 +1,6 @@
|
||||
const mongoose = require("mongoose");
|
||||
const EmailService = require("../../service/emailService");
|
||||
const Notification = require("./Notification");
|
||||
import mongoose from "mongoose";
|
||||
import EmailService from "../../service/emailService.js";
|
||||
import Notification from "./Notification.js";
|
||||
|
||||
/**
|
||||
* Check Schema for MongoDB collection.
|
||||
@@ -73,5 +73,4 @@ const CheckSchema = mongoose.Schema(
|
||||
);
|
||||
|
||||
CheckSchema.index({ createdAt: 1 });
|
||||
|
||||
module.exports = mongoose.model("Check", CheckSchema);
|
||||
export default mongoose.model("Check", CheckSchema);
|
||||
@@ -1,5 +1,4 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
import mongoose from "mongoose";
|
||||
const InviteTokenSchema = mongoose.Schema(
|
||||
{
|
||||
email: {
|
||||
@@ -32,4 +31,4 @@ const InviteTokenSchema = mongoose.Schema(
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = mongoose.model("InviteToken", InviteTokenSchema);
|
||||
export default mongoose.model("InviteToken", InviteTokenSchema);
|
||||
@@ -1,5 +1,4 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
import mongoose from "mongoose";
|
||||
/**
|
||||
* MaintenanceWindow Schema
|
||||
* @module MaintenanceWindow
|
||||
@@ -66,4 +65,4 @@ const MaintenanceWindow = mongoose.Schema(
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = mongoose.model("MaintenanceWindow", MaintenanceWindow);
|
||||
export default mongoose.model("MaintenanceWindow", MaintenanceWindow);
|
||||
@@ -1,5 +1,5 @@
|
||||
const mongoose = require("mongoose");
|
||||
const Notification = require("./Notification");
|
||||
import mongoose from "mongoose";
|
||||
import Notification from "./Notification.js";
|
||||
|
||||
const MonitorSchema = mongoose.Schema(
|
||||
{
|
||||
@@ -60,4 +60,4 @@ const MonitorSchema = mongoose.Schema(
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = mongoose.model("Monitor", MonitorSchema);
|
||||
export default mongoose.model("Monitor", MonitorSchema);
|
||||
@@ -1,5 +1,4 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
import mongoose from "mongoose";
|
||||
const NotificationSchema = mongoose.Schema(
|
||||
{
|
||||
monitorId: {
|
||||
@@ -22,5 +21,4 @@ const NotificationSchema = mongoose.Schema(
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = mongoose.model("Notification", NotificationSchema);
|
||||
export default mongoose.model("Notification", NotificationSchema);
|
||||
@@ -1,5 +1,4 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
import mongoose from "mongoose";
|
||||
const AuditSchema = mongoose.Schema({
|
||||
id: { type: String, required: true },
|
||||
title: { type: String, required: true },
|
||||
@@ -109,4 +108,4 @@ PageSpeedCheck.pre("save", async function (next) {
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = mongoose.model("PageSpeedCheck", PageSpeedCheck);
|
||||
export default mongoose.model("PageSpeedCheck", PageSpeedCheck);
|
||||
@@ -1,4 +1,4 @@
|
||||
const mongoose = require("mongoose");
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const RecoveryTokenSchema = mongoose.Schema(
|
||||
{
|
||||
@@ -22,4 +22,4 @@ const RecoveryTokenSchema = mongoose.Schema(
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = mongoose.model("RecoveryToken", RecoveryTokenSchema);
|
||||
export default mongoose.model("RecoveryToken", RecoveryTokenSchema);
|
||||
@@ -1,5 +1,4 @@
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
import mongoose from "mongoose";
|
||||
const TeamSchema = mongoose.Schema(
|
||||
{
|
||||
email: {
|
||||
@@ -12,5 +11,4 @@ const TeamSchema = mongoose.Schema(
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = mongoose.model("Team", TeamSchema);
|
||||
export default mongoose.model("Team", TeamSchema);
|
||||
+68
-68
@@ -1,87 +1,87 @@
|
||||
const mongoose = require("mongoose");
|
||||
const bcrypt = require("bcrypt");
|
||||
import mongoose from "mongoose";
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
const UserSchema = mongoose.Schema(
|
||||
{
|
||||
firstName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
lastName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
avatarImage: {
|
||||
type: String,
|
||||
},
|
||||
profileImage: {
|
||||
data: Buffer,
|
||||
contentType: String,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isVerified: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
role: {
|
||||
type: [String],
|
||||
default: "user",
|
||||
enum: ["user", "admin", "superadmin", "demo"],
|
||||
},
|
||||
teamId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Team",
|
||||
immutable: true,
|
||||
},
|
||||
checkTTL: {
|
||||
type: Number,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
{
|
||||
firstName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
lastName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
avatarImage: {
|
||||
type: String,
|
||||
},
|
||||
profileImage: {
|
||||
data: Buffer,
|
||||
contentType: String,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isVerified: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
role: {
|
||||
type: [String],
|
||||
default: "user",
|
||||
enum: ["user", "admin", "superadmin", "demo"],
|
||||
},
|
||||
teamId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Team",
|
||||
immutable: true,
|
||||
},
|
||||
checkTTL: {
|
||||
type: Number,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
UserSchema.pre("save", async function (next) {
|
||||
if (!this.isModified("password")) {
|
||||
next();
|
||||
}
|
||||
const salt = await bcrypt.genSalt(10); //genSalt is asynchronous, need to wait
|
||||
this.password = await bcrypt.hash(this.password, salt); // hash is also async, need to eitehr await or use hashSync
|
||||
next();
|
||||
if (!this.isModified("password")) {
|
||||
next();
|
||||
}
|
||||
const salt = await bcrypt.genSalt(10); //genSalt is asynchronous, need to wait
|
||||
this.password = await bcrypt.hash(this.password, salt); // hash is also async, need to eitehr await or use hashSync
|
||||
next();
|
||||
});
|
||||
|
||||
UserSchema.pre("findOneAndUpdate", async function (next) {
|
||||
const update = this.getUpdate();
|
||||
if ("password" in update) {
|
||||
const salt = await bcrypt.genSalt(10); //genSalt is asynchronous, need to wait
|
||||
update.password = await bcrypt.hash(update.password, salt); // hash is also async, need to eitehr await or use hashSync
|
||||
}
|
||||
const update = this.getUpdate();
|
||||
if ("password" in update) {
|
||||
const salt = await bcrypt.genSalt(10); //genSalt is asynchronous, need to wait
|
||||
update.password = await bcrypt.hash(update.password, salt); // hash is also async, need to eitehr await or use hashSync
|
||||
}
|
||||
|
||||
next();
|
||||
next();
|
||||
});
|
||||
|
||||
UserSchema.methods.comparePassword = async function (submittedPassword) {
|
||||
res = await bcrypt.compare(submittedPassword, this.password);
|
||||
return res;
|
||||
const res = await bcrypt.compare(submittedPassword, this.password);
|
||||
return res;
|
||||
};
|
||||
|
||||
const User = mongoose.model("User", UserSchema);
|
||||
|
||||
User.init().then(() => {
|
||||
console.log("User model initialized");
|
||||
console.log("User model initialized");
|
||||
});
|
||||
|
||||
module.exports = mongoose.model("User", UserSchema);
|
||||
export default mongoose.model("User", UserSchema);
|
||||
+21
-24
@@ -1,6 +1,6 @@
|
||||
const mongoose = require("mongoose");
|
||||
const UserModel = require("../models/User");
|
||||
const AppSettings = require("../models/AppSettings");
|
||||
import mongoose from "mongoose";
|
||||
import UserModel from "../models/User.js";
|
||||
import AppSettings from "../models/AppSettings.js";
|
||||
|
||||
//****************************************
|
||||
// DB Connection
|
||||
@@ -41,7 +41,7 @@ const checkSuperadmin = async (req, res) => {
|
||||
// User Operations
|
||||
//****************************************
|
||||
|
||||
const {
|
||||
import {
|
||||
insertUser,
|
||||
getUserByEmail,
|
||||
updateUser,
|
||||
@@ -50,32 +50,32 @@ const {
|
||||
deleteAllOtherUsers,
|
||||
getAllUsers,
|
||||
logoutUser,
|
||||
} = require("./modules/userModule");
|
||||
} from "./modules/userModule.js";
|
||||
|
||||
//****************************************
|
||||
// Invite Token Operations
|
||||
//****************************************
|
||||
|
||||
const {
|
||||
import {
|
||||
requestInviteToken,
|
||||
getInviteToken,
|
||||
getInviteTokenAndDelete,
|
||||
} = require("./modules/inviteModule");
|
||||
} from "./modules/inviteModule.js";
|
||||
|
||||
//****************************************
|
||||
// Recovery Operations
|
||||
//****************************************
|
||||
const {
|
||||
import {
|
||||
requestRecoveryToken,
|
||||
validateRecoveryToken,
|
||||
resetPassword,
|
||||
} = require("./modules/recoveryModule");
|
||||
} from "./modules/recoveryModule.js";
|
||||
|
||||
//****************************************
|
||||
// Monitors
|
||||
//****************************************
|
||||
|
||||
const {
|
||||
import {
|
||||
getAllMonitors,
|
||||
getMonitorStatsById,
|
||||
getMonitorById,
|
||||
@@ -87,23 +87,23 @@ const {
|
||||
deleteMonitorsByUserId,
|
||||
editMonitor,
|
||||
addDemoMonitors,
|
||||
} = require("./modules/monitorModule");
|
||||
} from "./modules/monitorModule.js";
|
||||
|
||||
//****************************************
|
||||
// Page Speed Checks
|
||||
//****************************************
|
||||
|
||||
const {
|
||||
import {
|
||||
createPageSpeedCheck,
|
||||
getPageSpeedChecks,
|
||||
deletePageSpeedChecksByMonitorId,
|
||||
} = require("./modules/pageSpeedCheckModule");
|
||||
} from "./modules/pageSpeedCheckModule.js";
|
||||
|
||||
//****************************************
|
||||
// Checks
|
||||
//****************************************
|
||||
|
||||
const {
|
||||
import {
|
||||
createCheck,
|
||||
getChecksCount,
|
||||
getChecks,
|
||||
@@ -111,12 +111,12 @@ const {
|
||||
deleteChecks,
|
||||
deleteChecksByTeamId,
|
||||
updateChecksTTL,
|
||||
} = require("./modules/checkModule");
|
||||
} from "./modules/checkModule.js";
|
||||
|
||||
//****************************************
|
||||
// Maintenance Window
|
||||
//****************************************
|
||||
const {
|
||||
import {
|
||||
createMaintenanceWindow,
|
||||
getMaintenanceWindowById,
|
||||
getMaintenanceWindowsByTeamId,
|
||||
@@ -125,26 +125,23 @@ const {
|
||||
deleteMaintenanceWindowByMonitorId,
|
||||
deleteMaintenanceWindowByUserId,
|
||||
editMaintenanceWindowById,
|
||||
} = require("./modules/maintenanceWindowModule");
|
||||
} from "./modules/maintenanceWindowModule.js";
|
||||
|
||||
//****************************************
|
||||
// Notifications
|
||||
//****************************************
|
||||
const {
|
||||
import {
|
||||
createNotification,
|
||||
getNotificationsByMonitorId,
|
||||
deleteNotificationsByMonitorId,
|
||||
} = require("./modules/notificationModule");
|
||||
} from "./modules/notificationModule.js";
|
||||
|
||||
//****************************************
|
||||
// AppSettings
|
||||
//****************************************
|
||||
const {
|
||||
getAppSettings,
|
||||
updateAppSettings,
|
||||
} = require("./modules/settingsModule");
|
||||
import { getAppSettings, updateAppSettings } from "./modules/settingsModule.js";
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
connect,
|
||||
insertUser,
|
||||
getUserByEmail,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const Check = require("../../models/Check");
|
||||
const Monitor = require("../../models/Monitor");
|
||||
const User = require("../../models/User");
|
||||
const logger = require("../../../utils/logger");
|
||||
import Check from "../../models/Check.js";
|
||||
import Monitor from "../../models/Monitor.js";
|
||||
import User from "../../models/User.js";
|
||||
import logger from "../../../utils/logger.js";
|
||||
const SERVICE_NAME = "checkModule";
|
||||
const dateRangeLookup = {
|
||||
day: new Date(new Date().setDate(new Date().getDate() - 1)),
|
||||
@@ -274,7 +274,7 @@ const updateChecksTTL = async (teamId, ttl) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
createCheck,
|
||||
getChecksCount,
|
||||
getChecks,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const InviteToken = require("../../models/InviteToken");
|
||||
const crypto = require("crypto");
|
||||
const { errorMessages } = require("../../../utils/messages");
|
||||
const SERVICE_NAME = "inviteModule";
|
||||
import InviteToken from "../../models/InviteToken.js";
|
||||
import crypto from "crypto";
|
||||
import { errorMessages } from "../../../utils/messages.js";
|
||||
|
||||
const SERVICE_NAME = "inviteModule";
|
||||
/**
|
||||
* Request an invite token for a user.
|
||||
*
|
||||
@@ -83,8 +83,4 @@ const getInviteTokenAndDelete = async (token) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
requestInviteToken,
|
||||
getInviteToken,
|
||||
getInviteTokenAndDelete,
|
||||
};
|
||||
export { requestInviteToken, getInviteToken, getInviteTokenAndDelete };
|
||||
@@ -1,4 +1,4 @@
|
||||
const MaintenanceWindow = require("../../models/MaintenanceWindow");
|
||||
import MaintenanceWindow from "../../models/MaintenanceWindow.js";
|
||||
const SERVICE_NAME = "maintenanceWindowModule";
|
||||
|
||||
/**
|
||||
@@ -220,7 +220,7 @@ const editMaintenanceWindowById = async (
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
createMaintenanceWindow,
|
||||
getMaintenanceWindowById,
|
||||
getMaintenanceWindowsByTeamId,
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
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 { NormalizeData } = require("../../../utils/dataUtils");
|
||||
const demoMonitors = require("../../../utils/demoMonitors.json");
|
||||
import Monitor from "../../models/Monitor.js";
|
||||
import Check from "../../models/Check.js";
|
||||
import PageSpeedCheck from "../../models/PageSpeedCheck.js";
|
||||
import { errorMessages } from "../../../utils/messages.js";
|
||||
import Notification from "../../models/Notification.js";
|
||||
import { NormalizeData } from "../../../utils/dataUtils.js";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const demoMonitorsPath = path.resolve(
|
||||
__dirname,
|
||||
"../../../utils/demoMonitors.json"
|
||||
);
|
||||
const demoMonitors = JSON.parse(fs.readFileSync(demoMonitorsPath, "utf8"));
|
||||
|
||||
const SERVICE_NAME = "monitorModule";
|
||||
|
||||
/**
|
||||
@@ -572,7 +584,7 @@ const addDemoMonitors = async (userId, teamId) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
getAllMonitors,
|
||||
getMonitorStatsById,
|
||||
getMonitorById,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const Notification = require("../../models/Notification");
|
||||
import Notification from "../../models/Notification.js";
|
||||
const SERVICE_NAME = "notificationModule";
|
||||
/**
|
||||
* Creates a new notification.
|
||||
@@ -49,7 +49,7 @@ const deleteNotificationsByMonitorId = async (monitorId) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
createNotification,
|
||||
getNotificationsByMonitorId,
|
||||
deleteNotificationsByMonitorId,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const PageSpeedCheck = require("../../models/PageSpeedCheck");
|
||||
import PageSpeedCheck from "../../models/PageSpeedCheck.js";
|
||||
const SERVICE_NAME = "pageSpeedCheckModule";
|
||||
/**
|
||||
* Create a PageSpeed check for a monitor
|
||||
@@ -63,7 +63,7 @@ const deletePageSpeedChecksByMonitorId = async (monitorId) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
createPageSpeedCheck,
|
||||
getPageSpeedChecks,
|
||||
deletePageSpeedChecksByMonitorId,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
const UserModel = require("../../models/User");
|
||||
const RecoveryToken = require("../../models/RecoveryToken");
|
||||
const crypto = require("crypto");
|
||||
const { errorMessages } = require("../../../utils/messages");
|
||||
import UserModel from "../../models/User.js";
|
||||
import RecoveryToken from "../../models/RecoveryToken.js";
|
||||
import crypto from "crypto";
|
||||
import { errorMessages } from "../../../utils/messages.js";
|
||||
|
||||
const SERVICE_NAME = "recoveryModule";
|
||||
|
||||
/**
|
||||
@@ -81,8 +82,4 @@ const resetPassword = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
requestRecoveryToken,
|
||||
validateRecoveryToken,
|
||||
resetPassword,
|
||||
};
|
||||
export { requestRecoveryToken, validateRecoveryToken, resetPassword };
|
||||
@@ -1,4 +1,4 @@
|
||||
const AppSettings = require("../../models/AppSettings");
|
||||
import AppSettings from "../../models/AppSettings.js";
|
||||
const SERVICE_NAME = "SettingsModule";
|
||||
|
||||
const getAppSettings = async () => {
|
||||
@@ -27,7 +27,4 @@ const updateAppSettings = async (newSettings) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getAppSettings,
|
||||
updateAppSettings,
|
||||
};
|
||||
export { getAppSettings, updateAppSettings };
|
||||
@@ -1,11 +1,11 @@
|
||||
const UserModel = require("../../models/User");
|
||||
const TeamModel = require("../../models/Team");
|
||||
const { errorMessages } = require("../../../utils/messages");
|
||||
const { GenerateAvatarImage } = require("../../../utils/imageProcessing");
|
||||
import UserModel from "../../models/User.js";
|
||||
import TeamModel from "../../models/Team.js";
|
||||
import { errorMessages } from "../../../utils/messages.js";
|
||||
import { GenerateAvatarImage } from "../../../utils/imageProcessing.js";
|
||||
|
||||
const DUPLICATE_KEY_CODE = 11000; // MongoDB error code for duplicate key
|
||||
const { ParseBoolean } = require("../../../utils/utils");
|
||||
SERVICE_NAME = "userModule";
|
||||
import { ParseBoolean } from "../../../utils/utils.js";
|
||||
const SERVICE_NAME = "userModule";
|
||||
|
||||
/**
|
||||
* Insert a User
|
||||
@@ -208,7 +208,7 @@ const logoutUser = async (userId) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
insertUser,
|
||||
getUserByEmail,
|
||||
updateUser,
|
||||
|
||||
+140
-138
@@ -1,163 +1,165 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const swaggerUi = require("swagger-ui-express");
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import swaggerUi from "swagger-ui-express";
|
||||
|
||||
const express = require("express");
|
||||
const helmet = require("helmet");
|
||||
const cors = require("cors");
|
||||
const logger = require("./utils/logger");
|
||||
const { verifyJWT } = require("./middleware/verifyJWT");
|
||||
const { handleErrors } = require("./middleware/handleErrors");
|
||||
const { errorMessages } = require("./utils/messages");
|
||||
const authRouter = require("./routes/authRoute");
|
||||
const inviteRouter = require("./routes/inviteRoute");
|
||||
const monitorRouter = require("./routes/monitorRoute");
|
||||
const checkRouter = require("./routes/checkRoute");
|
||||
const maintenanceWindowRouter = require("./routes/maintenanceWindowRoute");
|
||||
const settingsRouter = require("./routes/settingsRoute");
|
||||
import express from "express";
|
||||
import helmet from "helmet";
|
||||
import cors from "cors";
|
||||
import logger from "./utils/logger.js";
|
||||
import { verifyJWT } from "./middleware/verifyJWT.js";
|
||||
import { handleErrors } from "./middleware/handleErrors.js";
|
||||
import { errorMessages } from "./utils/messages.js";
|
||||
import authRouter from "./routes/authRoute.js";
|
||||
import inviteRouter from "./routes/inviteRoute.js";
|
||||
import monitorRouter from "./routes/monitorRoute.js";
|
||||
import checkRouter from "./routes/checkRoute.js";
|
||||
import maintenanceWindowRouter from "./routes/maintenanceWindowRoute.js";
|
||||
import settingsRouter from "./routes/settingsRoute.js";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const { connectDbAndRunServer } = require("./configs/db");
|
||||
const queueRouter = require("./routes/queueRoute");
|
||||
const JobQueue = require("./service/jobQueue");
|
||||
const NetworkService = require("./service/networkService");
|
||||
const EmailService = require("./service/emailService");
|
||||
const SettingsService = require("./service/settingsService");
|
||||
import { connectDbAndRunServer } from "./configs/db.js";
|
||||
import queueRouter from "./routes/queueRoute.js";
|
||||
import JobQueue from "./service/jobQueue.js";
|
||||
import NetworkService from "./service/networkService.js";
|
||||
import EmailService from "./service/emailService.js";
|
||||
import SettingsService from "./service/settingsService.js";
|
||||
import db from "./db/mongo/MongoDB.js";
|
||||
import { fetchMonitorCertificate } from "./controllers/controllerUtils.js";
|
||||
const SERVICE_NAME = "Server";
|
||||
|
||||
let cleaningUp = false;
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const openApiSpec = JSON.parse(
|
||||
fs.readFileSync(path.join(__dirname, "openapi.json"), "utf8")
|
||||
fs.readFileSync(path.join(__dirname, "openapi.json"), "utf8")
|
||||
);
|
||||
// Need to wrap server setup in a function to handle async nature of JobQueue
|
||||
const startApp = async () => {
|
||||
// **************************
|
||||
// Here is where we can swap out DBs easily. Spin up a mongoDB instance and try it out.
|
||||
// Simply comment out the FakeDB and uncomment the MongoDB or vice versa.
|
||||
// We can easily swap between any type of data source as long as the methods are implemented
|
||||
//
|
||||
// FakeDB
|
||||
// const db = require("./db/FakeDb");
|
||||
//
|
||||
// MongoDB
|
||||
// const db = require("./db/MongoDB");
|
||||
//
|
||||
// **************************
|
||||
const DB_TYPE = {
|
||||
MongoDB: () => require("./db/mongo/MongoDB"),
|
||||
FakedDB: () => require("./db/FakeDb"),
|
||||
};
|
||||
// **************************
|
||||
// Here is where we can swap out DBs easily. Spin up a mongoDB instance and try it out.
|
||||
// Simply comment out the FakeDB and uncomment the MongoDB or vice versa.
|
||||
// We can easily swap between any type of data source as long as the methods are implemented
|
||||
//
|
||||
// FakeDB
|
||||
// const db = require("./db/FakeDb");
|
||||
//
|
||||
// MongoDB
|
||||
// const db = require("./db/MongoDB");
|
||||
//
|
||||
// **************************
|
||||
// const DB_TYPE = {
|
||||
// MongoDB: async () => (await import("./db/mongo/MongoDB.js")).default,
|
||||
// FakedDB: async () => (await import("./db/FakeDb.js")).default,
|
||||
// };
|
||||
|
||||
// const db = DB_TYPE[process.env.DB_TYPE]
|
||||
// ? DB_TYPE[process.env.DB_TYPE]()
|
||||
// : require("./db/FakeDb");
|
||||
// const db = DB_TYPE[process.env.DB_TYPE]
|
||||
// ? DB_TYPE[process.env.DB_TYPE]()
|
||||
// : require("./db/FakeDb");
|
||||
|
||||
const db = DB_TYPE.MongoDB();
|
||||
// const db = DB_TYPE.MongoDB();
|
||||
|
||||
const app = express();
|
||||
const app = express();
|
||||
|
||||
// middlewares
|
||||
app.use(
|
||||
cors()
|
||||
//We will add configuration later
|
||||
);
|
||||
app.use(express.json());
|
||||
app.use(helmet());
|
||||
// **************************
|
||||
// Make DB accessible anywhere we have a Request object
|
||||
// By adding the DB to the request object, we can access it in any route
|
||||
// Thus we do not need to import it in every route file, and we can easily swap out DBs as there is only one place to change it
|
||||
// Same applies for JobQueue and emailService
|
||||
// **************************
|
||||
app.use((req, res, next) => {
|
||||
req.db = db;
|
||||
req.jobQueue = jobQueue;
|
||||
req.emailService = emailService;
|
||||
req.settingsService = settingsService;
|
||||
next();
|
||||
});
|
||||
// middlewares
|
||||
app.use(
|
||||
cors()
|
||||
//We will add configuration later
|
||||
);
|
||||
app.use(express.json());
|
||||
app.use(helmet());
|
||||
// **************************
|
||||
// Make DB accessible anywhere we have a Request object
|
||||
// By adding the DB to the request object, we can access it in any route
|
||||
// Thus we do not need to import it in every route file, and we can easily swap out DBs as there is only one place to change it
|
||||
// Same applies for JobQueue and emailService
|
||||
// **************************
|
||||
app.use((req, res, next) => {
|
||||
req.db = db;
|
||||
req.jobQueue = jobQueue;
|
||||
req.emailService = emailService;
|
||||
req.settingsService = settingsService;
|
||||
next();
|
||||
});
|
||||
|
||||
// Swagger UI
|
||||
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(openApiSpec));
|
||||
// Swagger UI
|
||||
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(openApiSpec));
|
||||
|
||||
//routes
|
||||
app.use("/api/v1/auth", authRouter);
|
||||
app.use("/api/v1/settings", verifyJWT, settingsRouter);
|
||||
app.use("/api/v1/invite", inviteRouter);
|
||||
app.use("/api/v1/monitors", verifyJWT, monitorRouter);
|
||||
app.use("/api/v1/checks", verifyJWT, checkRouter);
|
||||
app.use("/api/v1/maintenance-window", verifyJWT, maintenanceWindowRouter);
|
||||
app.use("/api/v1/queue", verifyJWT, queueRouter);
|
||||
//routes
|
||||
app.use("/api/v1/auth", authRouter);
|
||||
app.use("/api/v1/settings", verifyJWT, settingsRouter);
|
||||
app.use("/api/v1/invite", inviteRouter);
|
||||
app.use("/api/v1/monitors", verifyJWT, monitorRouter);
|
||||
app.use("/api/v1/checks", verifyJWT, checkRouter);
|
||||
app.use("/api/v1/maintenance-window", verifyJWT, maintenanceWindowRouter);
|
||||
app.use("/api/v1/queue", verifyJWT, queueRouter);
|
||||
|
||||
//health check
|
||||
app.use("/api/v1/healthy", (req, res) => {
|
||||
try {
|
||||
logger.info("Checking Health of the server.");
|
||||
return res.status(200).json({ message: "Healthy" });
|
||||
} catch (error) {
|
||||
logger.error(error.message);
|
||||
return res.status(500).json({ message: error.message });
|
||||
}
|
||||
});
|
||||
//health check
|
||||
app.use("/api/v1/healthy", (req, res) => {
|
||||
try {
|
||||
logger.info("Checking Health of the server.");
|
||||
return res.status(200).json({ message: "Healthy" });
|
||||
} catch (error) {
|
||||
logger.error(error.message);
|
||||
return res.status(500).json({ message: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.use("/api/v1/mail", async (req, res) => {
|
||||
try {
|
||||
const id = await req.emailService.buildAndSendEmail(
|
||||
"welcomeEmailTemplate",
|
||||
{
|
||||
name: "Alex",
|
||||
},
|
||||
"ajhollid@gmail.com",
|
||||
"Welcome"
|
||||
);
|
||||
res.status(200).json({ success: true, msg: "Email sent", data: id });
|
||||
} catch (error) {
|
||||
logger.error(error.message);
|
||||
return res.status(500).json({ message: error.message });
|
||||
}
|
||||
});
|
||||
app.use("/api/v1/mail", async (req, res) => {
|
||||
try {
|
||||
const id = await req.emailService.buildAndSendEmail(
|
||||
"welcomeEmailTemplate",
|
||||
{
|
||||
name: "Alex",
|
||||
},
|
||||
"ajhollid@gmail.com",
|
||||
"Welcome"
|
||||
);
|
||||
res.status(200).json({ success: true, msg: "Email sent", data: id });
|
||||
} catch (error) {
|
||||
logger.error(error.message);
|
||||
return res.status(500).json({ message: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Error handler middleware
|
||||
* Should be called last
|
||||
*/
|
||||
app.use(handleErrors);
|
||||
/**
|
||||
* Error handler middleware
|
||||
* Should be called last
|
||||
*/
|
||||
app.use(handleErrors);
|
||||
|
||||
// Create services
|
||||
await connectDbAndRunServer(app, db);
|
||||
const settingsService = new SettingsService();
|
||||
// Create services
|
||||
await connectDbAndRunServer(app, db);
|
||||
const settingsService = new SettingsService();
|
||||
|
||||
await settingsService.loadSettings();
|
||||
const emailService = new EmailService(settingsService);
|
||||
const networkService = new NetworkService(db, emailService);
|
||||
const jobQueue = await JobQueue.createJobQueue(
|
||||
db,
|
||||
networkService,
|
||||
settingsService
|
||||
);
|
||||
await settingsService.loadSettings();
|
||||
const emailService = new EmailService(settingsService);
|
||||
const networkService = new NetworkService(db, emailService);
|
||||
const jobQueue = await JobQueue.createJobQueue(db, networkService, settingsService);
|
||||
|
||||
const cleanup = async () => {
|
||||
if (cleaningUp) {
|
||||
console.log("Already cleaning up");
|
||||
return;
|
||||
}
|
||||
cleaningUp = true;
|
||||
try {
|
||||
console.log("Shutting down gracefully");
|
||||
await jobQueue.obliterate();
|
||||
console.log("Finished cleanup");
|
||||
} catch (error) {
|
||||
logger.error(errorMessages.JOB_QUEUE_DELETE_JOB, {
|
||||
service: SERVICE_NAME,
|
||||
errorMsg: error.message,
|
||||
});
|
||||
}
|
||||
process.exit(0);
|
||||
};
|
||||
process.on("SIGUSR2", cleanup);
|
||||
process.on("SIGINT", cleanup);
|
||||
process.on("SIGTERM", cleanup);
|
||||
const cleanup = async () => {
|
||||
if (cleaningUp) {
|
||||
console.log("Already cleaning up");
|
||||
return;
|
||||
}
|
||||
cleaningUp = true;
|
||||
try {
|
||||
console.log("Shutting down gracefully");
|
||||
await jobQueue.obliterate();
|
||||
console.log("Finished cleanup");
|
||||
} catch (error) {
|
||||
logger.error(errorMessages.JOB_QUEUE_DELETE_JOB, {
|
||||
service: SERVICE_NAME,
|
||||
errorMsg: error.message,
|
||||
});
|
||||
}
|
||||
process.exit(0);
|
||||
};
|
||||
process.on("SIGUSR2", cleanup);
|
||||
process.on("SIGINT", cleanup);
|
||||
process.on("SIGTERM", cleanup);
|
||||
};
|
||||
|
||||
startApp().catch((error) => {
|
||||
console.log(error);
|
||||
console.log(error);
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
const logger = require("../utils/logger");
|
||||
const { errorMessages } = require("../utils/messages");
|
||||
import logger from "../utils/logger.js";
|
||||
import { errorMessages } from "../utils/messages.js";
|
||||
|
||||
const handleErrors = (error, req, res, next) => {
|
||||
const status = error.status || 500;
|
||||
@@ -12,4 +12,4 @@ const handleErrors = (error, req, res, next) => {
|
||||
res.status(status).json({ success: false, msg: message });
|
||||
};
|
||||
|
||||
module.exports = { handleErrors };
|
||||
export { handleErrors };
|
||||
@@ -1,7 +1,7 @@
|
||||
const jwt = require("jsonwebtoken");
|
||||
import jwt from "jsonwebtoken";
|
||||
const TOKEN_PREFIX = "Bearer ";
|
||||
const SERVICE_NAME = "allowedRoles";
|
||||
const { errorMessages } = require("../utils/messages");
|
||||
import { errorMessages } from "../utils/messages.js";
|
||||
|
||||
const isAllowed = (allowedRoles) => {
|
||||
return (req, res, next) => {
|
||||
@@ -52,4 +52,4 @@ const isAllowed = (allowedRoles) => {
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = { isAllowed };
|
||||
export { isAllowed };
|
||||
@@ -1,8 +1,9 @@
|
||||
const jwt = require("jsonwebtoken");
|
||||
import jwt from "jsonwebtoken";
|
||||
import { errorMessages } from "../utils/messages.js";
|
||||
import { handleError } from "../controllers/controllerUtils.js";
|
||||
|
||||
const SERVICE_NAME = "verifyJWT";
|
||||
const TOKEN_PREFIX = "Bearer ";
|
||||
const { errorMessages } = require("../utils/messages");
|
||||
const { handleError } = require("../controllers/controllerUtils");
|
||||
|
||||
/**
|
||||
* Verifies the JWT token
|
||||
@@ -91,4 +92,5 @@ function handleExpiredJwtToken(req, res, next) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { verifyJWT };
|
||||
export { verifyJWT };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const logger = require("../utils/logger");
|
||||
import logger from "../utils/logger.js";
|
||||
import { errorMessages } from "../utils/messages.js";
|
||||
const SERVICE_NAME = "verifyOwnership";
|
||||
const { errorMessages } = require("../utils/messages");
|
||||
|
||||
const verifyOwnership = (Model, paramName) => {
|
||||
return async (req, res, next) => {
|
||||
@@ -46,4 +46,4 @@ const verifyOwnership = (Model, paramName) => {
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = { verifyOwnership };
|
||||
export { verifyOwnership };
|
||||
Generated
+6789
-8041
File diff suppressed because it is too large.
Load diff
+7
-7
@@ -3,8 +3,9 @@
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "nyc mocha",
|
||||
"test": "c8 mocha",
|
||||
"dev": "nodemon index.js"
|
||||
},
|
||||
"keywords": [],
|
||||
@@ -15,7 +16,6 @@
|
||||
"axios": "^1.7.2",
|
||||
"bcrypt": "^5.1.1",
|
||||
"bullmq": "5.7.15",
|
||||
"chai": "5.1.1",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
@@ -25,21 +25,21 @@
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"mailersend": "^2.2.0",
|
||||
"mjml": "^5.0.0-alpha.4",
|
||||
"mocha": "10.7.3",
|
||||
"mongoose": "^8.3.3",
|
||||
"multer": "1.4.5-lts.1",
|
||||
"nodemailer": "^6.9.14",
|
||||
"ping": "0.4.4",
|
||||
"sharp": "0.33.4",
|
||||
"ssl-checker": "2.0.10",
|
||||
"swagger-ui-express": "5.0.1",
|
||||
"winston": "^3.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "3.1.0",
|
||||
"prettier": "^3.3.3",
|
||||
"nyc": "17.1.0",
|
||||
"proxyquire": "2.1.3",
|
||||
"chai": "5.1.1",
|
||||
"mocha": "10.7.3",
|
||||
"c8": "10.1.2",
|
||||
"esm": "3.2.25",
|
||||
"nodemon": "3.1.0",
|
||||
"sinon": "19.0.2"
|
||||
}
|
||||
}
|
||||
+12
-10
@@ -1,12 +1,14 @@
|
||||
const router = require("express").Router();
|
||||
const { verifyJWT } = require("../middleware/verifyJWT");
|
||||
const { verifyOwnership } = require("../middleware/verifyOwnership");
|
||||
const { isAllowed } = require("../middleware/isAllowed");
|
||||
const multer = require("multer");
|
||||
const upload = multer();
|
||||
const User = require("../db/models/User");
|
||||
import { Router } from "express";
|
||||
import { verifyJWT } from "../middleware/verifyJWT.js";
|
||||
import { verifyOwnership } from "../middleware/verifyOwnership.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import multer from "multer";
|
||||
import User from "../db/models/User.js";
|
||||
|
||||
const {
|
||||
const router = Router();
|
||||
const upload = multer();
|
||||
|
||||
import {
|
||||
registerUser,
|
||||
loginUser,
|
||||
editUser,
|
||||
@@ -16,7 +18,7 @@ const {
|
||||
checkSuperadminExists,
|
||||
getAllUsers,
|
||||
deleteUser,
|
||||
} = require("../controllers/authController");
|
||||
} from "../controllers/authController.js";
|
||||
|
||||
//Auth routes
|
||||
router.post("/register", upload.single("profileImage"), registerUser);
|
||||
@@ -31,4 +33,4 @@ router.post("/recovery/request", requestRecovery);
|
||||
router.post("/recovery/validate", validateRecovery);
|
||||
router.post("/recovery/reset/", resetPassword);
|
||||
|
||||
module.exports = router;
|
||||
export default router;
|
||||
+21
-20
@@ -1,33 +1,34 @@
|
||||
const router = require("express").Router();
|
||||
const checkController = require("../controllers/checkController");
|
||||
const { verifyOwnership } = require("../middleware/verifyOwnership");
|
||||
const { isAllowed } = require("../middleware/isAllowed");
|
||||
const Monitor = require("../db/models/Monitor");
|
||||
import { Router } from "express";
|
||||
import {
|
||||
createCheck,
|
||||
getChecks,
|
||||
deleteChecks,
|
||||
getTeamChecks,
|
||||
deleteChecksByTeamId,
|
||||
updateChecksTTL,
|
||||
} from "../controllers/checkController.js";
|
||||
import { verifyOwnership } from "../middleware/verifyOwnership.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import Monitor from "../db/models/Monitor.js";
|
||||
|
||||
router.get("/:monitorId", checkController.getChecks);
|
||||
router.post(
|
||||
"/:monitorId",
|
||||
verifyOwnership(Monitor, "monitorId"),
|
||||
checkController.createCheck
|
||||
);
|
||||
const router = Router();
|
||||
|
||||
router.get("/:monitorId", getChecks);
|
||||
router.post("/:monitorId", verifyOwnership(Monitor, "monitorId"), createCheck);
|
||||
router.delete(
|
||||
"/:monitorId",
|
||||
verifyOwnership(Monitor, "monitorId"),
|
||||
checkController.deleteChecks
|
||||
deleteChecks
|
||||
);
|
||||
|
||||
router.get("/team/:teamId", checkController.getTeamChecks);
|
||||
router.get("/team/:teamId", getTeamChecks);
|
||||
|
||||
router.delete(
|
||||
"/team/:teamId",
|
||||
isAllowed(["admin", "superadmin"]),
|
||||
checkController.deleteChecksByTeamId
|
||||
deleteChecksByTeamId
|
||||
);
|
||||
|
||||
router.put(
|
||||
"/team/ttl",
|
||||
isAllowed(["admin", "superadmin"]),
|
||||
checkController.updateChecksTTL
|
||||
);
|
||||
router.put("/team/ttl", isAllowed(["admin", "superadmin"]), updateChecksTTL);
|
||||
|
||||
module.exports = router;
|
||||
export default router;
|
||||
@@ -1,11 +1,12 @@
|
||||
const router = require("express").Router();
|
||||
const { verifyJWT } = require("../middleware/verifyJWT");
|
||||
const { isAllowed } = require("../middleware/isAllowed");
|
||||
|
||||
const {
|
||||
import { Router } from "express";
|
||||
import { verifyJWT } from "../middleware/verifyJWT.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import {
|
||||
issueInvitation,
|
||||
inviteVerifyController,
|
||||
} = require("../controllers/inviteController");
|
||||
} from "../controllers/inviteController.js";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.post(
|
||||
"/",
|
||||
@@ -15,4 +16,4 @@ router.post(
|
||||
);
|
||||
router.post("/verify", issueInvitation);
|
||||
|
||||
module.exports = router;
|
||||
export default router;
|
||||
@@ -1,22 +1,31 @@
|
||||
const router = require("express").Router();
|
||||
const maintenanceWindowController = require("../controllers/maintenanceWindowController");
|
||||
const { verifyOwnership } = require("../middleware/verifyOwnership");
|
||||
const Monitor = require("../db/models/Monitor");
|
||||
import { Router } from "express";
|
||||
import {
|
||||
createMaintenanceWindows,
|
||||
getMaintenanceWindowById,
|
||||
getMaintenanceWindowsByTeamId,
|
||||
getMaintenanceWindowsByMonitorId,
|
||||
deleteMaintenanceWindow,
|
||||
editMaintenanceWindow,
|
||||
} from "../controllers/maintenanceWindowController.js";
|
||||
import { verifyOwnership } from "../middleware/verifyOwnership.js";
|
||||
import Monitor from "../db/models/Monitor.js";
|
||||
|
||||
router.post("/", maintenanceWindowController.createMaintenanceWindows);
|
||||
const router = Router();
|
||||
|
||||
router.post("/", createMaintenanceWindows);
|
||||
|
||||
router.get(
|
||||
"/monitor/:monitorId",
|
||||
verifyOwnership(Monitor, "monitorId"),
|
||||
maintenanceWindowController.getMaintenanceWindowsByMonitorId
|
||||
getMaintenanceWindowsByMonitorId
|
||||
);
|
||||
|
||||
router.get("/team/", maintenanceWindowController.getMaintenanceWindowsByTeamId);
|
||||
router.get("/team/", getMaintenanceWindowsByTeamId);
|
||||
|
||||
router.get("/:id", maintenanceWindowController.getMaintenanceWindowById);
|
||||
router.get("/:id", getMaintenanceWindowById);
|
||||
|
||||
router.put("/:id", maintenanceWindowController.editMaintenanceWindow);
|
||||
router.put("/:id", editMaintenanceWindow);
|
||||
|
||||
router.delete("/:id", maintenanceWindowController.deleteMaintenanceWindow);
|
||||
router.delete("/:id", deleteMaintenanceWindow);
|
||||
|
||||
module.exports = router;
|
||||
export default router;
|
||||
@@ -1,51 +1,42 @@
|
||||
const router = require("express").Router();
|
||||
const monitorController = require("../controllers/monitorController");
|
||||
const { isAllowed } = require("../middleware/isAllowed");
|
||||
import { Router } from "express";
|
||||
import {
|
||||
getAllMonitors,
|
||||
getMonitorStatsById,
|
||||
getMonitorCertificate,
|
||||
getMonitorById,
|
||||
getMonitorsAndSummaryByTeamId,
|
||||
getMonitorsByTeamId,
|
||||
createMonitor,
|
||||
deleteMonitor,
|
||||
deleteAllMonitors,
|
||||
editMonitor,
|
||||
pauseMonitor,
|
||||
addDemoMonitors,
|
||||
} from "../controllers/monitorController.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
import { fetchMonitorCertificate } from "../controllers/controllerUtils.js";
|
||||
|
||||
router.get("/", monitorController.getAllMonitors);
|
||||
router.get("/stats/:monitorId", monitorController.getMonitorStatsById);
|
||||
router.get("/certificate/:monitorId", monitorController.getMonitorCertificate);
|
||||
router.get("/:monitorId", monitorController.getMonitorById);
|
||||
router.get(
|
||||
"/team/summary/:teamId",
|
||||
monitorController.getMonitorsAndSummaryByTeamId
|
||||
);
|
||||
router.get("/team/:teamId", monitorController.getMonitorsByTeamId);
|
||||
const router = Router();
|
||||
|
||||
router.post(
|
||||
"/",
|
||||
isAllowed(["admin", "superadmin"]),
|
||||
monitorController.createMonitor
|
||||
);
|
||||
router.get("/", getAllMonitors);
|
||||
router.get("/stats/:monitorId", getMonitorStatsById);
|
||||
router.get("/certificate/:monitorId", (req, res, next) => {
|
||||
getMonitorCertificate(req, res, next, fetchMonitorCertificate);
|
||||
});
|
||||
router.get("/:monitorId", getMonitorById);
|
||||
router.get("/team/summary/:teamId", getMonitorsAndSummaryByTeamId);
|
||||
router.get("/team/:teamId", getMonitorsByTeamId);
|
||||
|
||||
router.delete(
|
||||
"/:monitorId",
|
||||
isAllowed(["admin", "superadmin"]),
|
||||
monitorController.deleteMonitor
|
||||
);
|
||||
router.post("/", isAllowed(["admin", "superadmin"]), createMonitor);
|
||||
|
||||
router.put(
|
||||
"/:monitorId",
|
||||
isAllowed(["admin", "superadmin"]),
|
||||
monitorController.editMonitor
|
||||
);
|
||||
router.delete("/:monitorId", isAllowed(["admin", "superadmin"]), deleteMonitor);
|
||||
|
||||
router.delete(
|
||||
"/",
|
||||
isAllowed(["superadmin"]),
|
||||
monitorController.deleteAllMonitors
|
||||
);
|
||||
router.put("/:monitorId", isAllowed(["admin", "superadmin"]), editMonitor);
|
||||
|
||||
router.post(
|
||||
"/pause/:monitorId",
|
||||
isAllowed(["admin", "superadmin"]),
|
||||
monitorController.pauseMonitor
|
||||
);
|
||||
router.delete("/", isAllowed(["superadmin"]), deleteAllMonitors);
|
||||
|
||||
router.post(
|
||||
"/demo",
|
||||
isAllowed(["admin", "superadmin"]),
|
||||
monitorController.addDemoMonitors
|
||||
);
|
||||
router.post("/pause/:monitorId", isAllowed(["admin", "superadmin"]), pauseMonitor);
|
||||
|
||||
module.exports = router;
|
||||
router.post("/demo", isAllowed(["admin", "superadmin"]), addDemoMonitors);
|
||||
|
||||
export default router;
|
||||
@@ -1,15 +1,21 @@
|
||||
const router = require("express").Router();
|
||||
const queueController = require("../controllers/queueController");
|
||||
import { Router } from "express";
|
||||
import {
|
||||
getMetrics,
|
||||
getJobs,
|
||||
addJob,
|
||||
obliterateQueue,
|
||||
} from "../controllers/queueController.js";
|
||||
|
||||
router.get("/metrics", queueController.getMetrics);
|
||||
const router = Router();
|
||||
router.get("/metrics", getMetrics);
|
||||
|
||||
// Get Jobs
|
||||
router.get("/jobs", queueController.getJobs);
|
||||
router.get("/jobs", getJobs);
|
||||
|
||||
// Add Job
|
||||
router.post("/jobs", queueController.addJob);
|
||||
router.post("/jobs", addJob);
|
||||
|
||||
// Obliterate Queue
|
||||
router.post("/obliterate", queueController.obliterateQueue);
|
||||
router.post("/obliterate", obliterateQueue);
|
||||
|
||||
module.exports = router;
|
||||
export default router;
|
||||
@@ -1,13 +1,13 @@
|
||||
const router = require("express").Router();
|
||||
const settingsController = require("../controllers/settingsController");
|
||||
const { isAllowed } = require("../middleware/isAllowed");
|
||||
const Monitor = require("../db/models/Monitor");
|
||||
import { Router } from "express";
|
||||
import {
|
||||
getAppSettings,
|
||||
updateAppSettings,
|
||||
} from "../controllers/settingsController.js";
|
||||
import { isAllowed } from "../middleware/isAllowed.js";
|
||||
|
||||
router.get("/", settingsController.getAppSettings);
|
||||
router.put(
|
||||
"/",
|
||||
isAllowed(["superadmin"]),
|
||||
settingsController.updateAppSettings
|
||||
);
|
||||
const router = Router();
|
||||
|
||||
module.exports = router;
|
||||
router.get("/", getAppSettings);
|
||||
router.put("/", isAllowed(["superadmin"]), updateAppSettings);
|
||||
|
||||
export default router;
|
||||
@@ -1,10 +1,15 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const nodemailer = require("nodemailer");
|
||||
const { compile } = require("handlebars");
|
||||
const mjml2html = require("mjml");
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import nodemailer from "nodemailer";
|
||||
import pkg from "handlebars";
|
||||
const { compile } = pkg;
|
||||
import mjml2html from "mjml";
|
||||
import logger from "../utils/logger.js";
|
||||
import { fileURLToPath } from "url";
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const SERVICE_NAME = "EmailService";
|
||||
const logger = require("../utils/logger");
|
||||
|
||||
/**
|
||||
* Represents an email service that can load templates, build, and send emails.
|
||||
@@ -134,5 +139,4 @@ class EmailService {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = EmailService;
|
||||
export default EmailService;
|
||||
@@ -1,9 +1,9 @@
|
||||
const { Queue, Worker, Job } = require("bullmq");
|
||||
import { Queue, Worker, Job } from "bullmq";
|
||||
const QUEUE_NAME = "monitors";
|
||||
|
||||
const JOBS_PER_WORKER = 5;
|
||||
const logger = require("../utils/logger");
|
||||
const { errorMessages, successMessages } = require("../utils/messages");
|
||||
import logger from "../utils/logger.js";
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
const SERVICE_NAME = "JobQueue";
|
||||
/**
|
||||
* JobQueue
|
||||
@@ -360,4 +360,4 @@ class JobQueue {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = JobQueue;
|
||||
export default JobQueue;
|
||||
@@ -1,8 +1,8 @@
|
||||
const axios = require("axios");
|
||||
const ping = require("ping");
|
||||
const logger = require("../utils/logger");
|
||||
const http = require("http");
|
||||
const { errorMessages, successMessages } = require("../utils/messages");
|
||||
import axios from "axios";
|
||||
import ping from "ping";
|
||||
import logger from "../utils/logger.js";
|
||||
import http from "http";
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
|
||||
/**
|
||||
* NetworkService
|
||||
@@ -329,4 +329,4 @@ class NetworkService {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NetworkService;
|
||||
export default NetworkService;
|
||||
@@ -1,5 +1,4 @@
|
||||
const { env } = require("process");
|
||||
const AppSettings = require("../db/models/AppSettings");
|
||||
import AppSettings from "../db/models/AppSettings.js";
|
||||
const SERVICE_NAME = "SettingsService";
|
||||
const envConfig = {
|
||||
logLevel: undefined,
|
||||
@@ -83,4 +82,4 @@ class SettingsService {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SettingsService;
|
||||
export default SettingsService;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,16 +1,16 @@
|
||||
const {
|
||||
import {
|
||||
createCheck,
|
||||
getChecks,
|
||||
getTeamChecks,
|
||||
deleteChecks,
|
||||
deleteChecksByTeamId,
|
||||
updateChecksTTL,
|
||||
} = require("../../controllers/checkController");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const { errorMessages, successMessages } = require("../../utils/messages");
|
||||
const sinon = require("sinon");
|
||||
|
||||
} from "../../controllers/checkController.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { errorMessages, successMessages } from "../../utils/messages.js";
|
||||
import sinon from "sinon";
|
||||
describe("Check Controller - createCheck", () => {
|
||||
let req, res, next, handleError;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
@@ -88,6 +88,7 @@ describe("Check Controller - createCheck", () => {
|
||||
});
|
||||
|
||||
describe("Check Controller - getChecks", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
@@ -143,6 +144,7 @@ describe("Check Controller - getChecks", () => {
|
||||
});
|
||||
|
||||
describe("Check Controller - getTeamChecks", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
@@ -197,6 +199,7 @@ describe("Check Controller - getTeamChecks", () => {
|
||||
});
|
||||
|
||||
describe("Check Controller - deleteChecks", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
@@ -248,6 +251,7 @@ describe("Check Controller - deleteChecks", () => {
|
||||
});
|
||||
|
||||
describe("Check Controller - deleteChecksByTeamId", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
@@ -301,6 +305,7 @@ describe("Check Controller - deleteChecksByTeamId", () => {
|
||||
});
|
||||
|
||||
describe("Check Controller - updateCheckTTL", () => {
|
||||
let stub, req, res, next;
|
||||
beforeEach(() => {
|
||||
stub = sinon.stub(jwt, "verify").callsFake(() => {
|
||||
return { teamId: "123" };
|
||||
|
||||
@@ -1,105 +1,210 @@
|
||||
const {
|
||||
handleValidationError,
|
||||
handleError,
|
||||
} = require("../../controllers/controllerUtils");
|
||||
import sinon from "sinon";
|
||||
|
||||
import {
|
||||
handleValidationError,
|
||||
handleError,
|
||||
fetchMonitorCertificate,
|
||||
} from "../../controllers/controllerUtils.js";
|
||||
import { expect } from "chai";
|
||||
|
||||
describe("controllerUtils - handleValidationError", () => {
|
||||
it("should set status to 422", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.status).to.equal(422);
|
||||
});
|
||||
it("should set status to 422", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.status).to.equal(422);
|
||||
});
|
||||
|
||||
it("should set service to the provided serviceName", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.service).to.equal(serviceName);
|
||||
});
|
||||
it("should set service to the provided serviceName", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.service).to.equal(serviceName);
|
||||
});
|
||||
|
||||
it("should set message to error.details[0].message if present", () => {
|
||||
const error = {
|
||||
details: [{ message: "Detail message" }],
|
||||
};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.message).to.equal("Detail message");
|
||||
});
|
||||
it("should set message to error.details[0].message if present", () => {
|
||||
const error = {
|
||||
details: [{ message: "Detail message" }],
|
||||
};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.message).to.equal("Detail message");
|
||||
});
|
||||
|
||||
it("should set message to error.message if error.details is not present", () => {
|
||||
const error = {
|
||||
message: "Error message",
|
||||
};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.message).to.equal("Error message");
|
||||
});
|
||||
it("should set message to error.message if error.details is not present", () => {
|
||||
const error = {
|
||||
message: "Error message",
|
||||
};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.message).to.equal("Error message");
|
||||
});
|
||||
|
||||
it('should set message to "Validation Error" if neither error.details nor error.message is present', () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.message).to.equal("Validation Error");
|
||||
});
|
||||
it('should set message to "Validation Error" if neither error.details nor error.message is present', () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const result = handleValidationError(error, serviceName);
|
||||
expect(result.message).to.equal("Validation Error");
|
||||
});
|
||||
});
|
||||
|
||||
describe("handleError", () => {
|
||||
it("should set stats to the provided status if error.code is undefined", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const status = 400;
|
||||
const result = handleError(error, serviceName, method, status);
|
||||
expect(result.status).to.equal(status);
|
||||
});
|
||||
describe("controllerUtils - handleError", () => {
|
||||
it("should set stats to the provided status if error.code is undefined", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const status = 400;
|
||||
const result = handleError(error, serviceName, method, status);
|
||||
expect(result.status).to.equal(status);
|
||||
});
|
||||
|
||||
it("should not overwrite error.code if it is already defined", () => {
|
||||
const error = { status: 404 };
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const status = 400;
|
||||
const result = handleError(error, serviceName, method, status);
|
||||
expect(result.status).to.equal(404);
|
||||
});
|
||||
it("should not overwrite error.code if it is already defined", () => {
|
||||
const error = { status: 404 };
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const status = 400;
|
||||
const result = handleError(error, serviceName, method, status);
|
||||
expect(result.status).to.equal(404);
|
||||
});
|
||||
|
||||
it("should set service to the provided serviceName if error.service is undefined", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.service).to.equal(serviceName);
|
||||
});
|
||||
it("should set service to the provided serviceName if error.service is undefined", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.service).to.equal(serviceName);
|
||||
});
|
||||
|
||||
it("should not overwrite error.service if it is already defined", () => {
|
||||
const error = { service: "ExistingService" };
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.service).to.equal("ExistingService");
|
||||
});
|
||||
it("should not overwrite error.service if it is already defined", () => {
|
||||
const error = { service: "ExistingService" };
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.service).to.equal("ExistingService");
|
||||
});
|
||||
|
||||
it("should set method to the provided method if error.method is undefined", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.method).to.equal(method);
|
||||
});
|
||||
it("should set method to the provided method if error.method is undefined", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.method).to.equal(method);
|
||||
});
|
||||
|
||||
it("should not overwrite error.method if it is already defined", () => {
|
||||
const error = { method: "existingMethod" };
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.method).to.equal("existingMethod");
|
||||
});
|
||||
it("should not overwrite error.method if it is already defined", () => {
|
||||
const error = { method: "existingMethod" };
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.method).to.equal("existingMethod");
|
||||
});
|
||||
|
||||
it("should set code to 500 if error.code is undefined and no code is provided", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.status).to.equal(500);
|
||||
});
|
||||
it("should set code to 500 if error.code is undefined and no code is provided", () => {
|
||||
const error = {};
|
||||
const serviceName = "TestService";
|
||||
const method = "testMethod";
|
||||
const result = handleError(error, serviceName, method);
|
||||
expect(result.status).to.equal(500);
|
||||
});
|
||||
});
|
||||
|
||||
describe("controllerUtils - fetchMonitorCertificate", () => {
|
||||
const originalTls = {
|
||||
connect: sinon.stub().callsFake((options, callback) => {
|
||||
// Create socket stub with sinon stubs for all methods
|
||||
socket = {
|
||||
getPeerX509Certificate: sinon.stub().returns({
|
||||
subject: "CN=fake-cert",
|
||||
validTo: "Dec 31 23:59:59 2023 GMT",
|
||||
}),
|
||||
end: sinon.stub(),
|
||||
on: sinon.stub(),
|
||||
};
|
||||
|
||||
// Use process.nextTick to ensure async behavior
|
||||
process.nextTick(() => {
|
||||
callback.call(socket); // Ensure correct 'this' binding
|
||||
});
|
||||
|
||||
return socket;
|
||||
}),
|
||||
};
|
||||
|
||||
let tls, monitor, socket;
|
||||
beforeEach(() => {
|
||||
monitor = { url: "https://www.google.com" };
|
||||
tls = {
|
||||
connect: sinon.stub().callsFake((options, callback) => {
|
||||
// Create socket stub with sinon stubs for all methods
|
||||
socket = {
|
||||
getPeerX509Certificate: sinon.stub().returns({
|
||||
subject: "CN=fake-cert",
|
||||
validTo: "Dec 31 23:59:59 2023 GMT",
|
||||
}),
|
||||
end: sinon.stub(),
|
||||
on: sinon.stub(),
|
||||
};
|
||||
|
||||
// Use process.nextTick to ensure async behavior
|
||||
process.nextTick(() => {
|
||||
callback.call(socket); // Ensure correct 'this' binding
|
||||
});
|
||||
|
||||
return socket;
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
tls = { ...originalTls };
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it("should resolve with the certificate when the connection is successful", async () => {
|
||||
const certificate = await fetchMonitorCertificate(tls, monitor);
|
||||
expect(certificate.validTo).to.equal("Dec 31 23:59:59 2023 GMT");
|
||||
expect(socket.end.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it("should reject with an error when the connection fails", async () => {
|
||||
tls.connect = sinon.stub().throws(new Error("Connection error"));
|
||||
try {
|
||||
await fetchMonitorCertificate(tls, monitor);
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal("Connection error");
|
||||
}
|
||||
});
|
||||
|
||||
it("should reject with an error if monitorURL is invalid", async () => {
|
||||
monitor.url = "invalid-url";
|
||||
try {
|
||||
await fetchMonitorCertificate(tls, monitor);
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal("Invalid URL");
|
||||
}
|
||||
});
|
||||
it("should do a thing", async () => {
|
||||
tls = {
|
||||
connect: sinon.stub().callsFake((options, callback) => {
|
||||
// Create socket stub with sinon stubs for all methods
|
||||
socket = {
|
||||
getPeerX509Certificate: sinon.stub().throws(new Error("Certificate error")),
|
||||
end: sinon.stub(),
|
||||
on: sinon.stub(),
|
||||
};
|
||||
|
||||
// Use process.nextTick to ensure async behavior
|
||||
process.nextTick(() => {
|
||||
callback.call(socket); // Ensure correct 'this' binding
|
||||
});
|
||||
|
||||
return socket;
|
||||
}),
|
||||
};
|
||||
try {
|
||||
await fetchMonitorCertificate(tls, monitor);
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal("Certificate error");
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,12 +1,12 @@
|
||||
const {
|
||||
import {
|
||||
issueInvitation,
|
||||
inviteVerifyController,
|
||||
} = require("../../controllers/inviteController");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const { errorMessages, successMessages } = require("../../utils/messages");
|
||||
const sinon = require("sinon");
|
||||
const joi = require("joi");
|
||||
} from "../../controllers/inviteController.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import sinon from "sinon";
|
||||
import joi from "joi";
|
||||
describe("inviteController - issueInvitation", () => {
|
||||
let req, res, next, stub;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
headers: { authorization: "Bearer token" },
|
||||
@@ -154,6 +154,7 @@ describe("inviteController - issueInvitation", () => {
|
||||
});
|
||||
|
||||
describe("inviteController - inviteVerifyController", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
body: { token: "token" },
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
const {
|
||||
import {
|
||||
createMaintenanceWindows,
|
||||
getMaintenanceWindowById,
|
||||
getMaintenanceWindowsByTeamId,
|
||||
getMaintenanceWindowsByMonitorId,
|
||||
deleteMaintenanceWindow,
|
||||
editMaintenanceWindow,
|
||||
} = require("../../controllers/maintenanceWindowController");
|
||||
} from "../../controllers/maintenanceWindowController.js";
|
||||
|
||||
const jwt = require("jsonwebtoken");
|
||||
const { errorMessages, successMessages } = require("../../utils/messages");
|
||||
const sinon = require("sinon");
|
||||
import jwt from "jsonwebtoken";
|
||||
import { successMessages } from "../../utils/messages.js";
|
||||
import sinon from "sinon";
|
||||
|
||||
describe("maintenanceWindowController - createMaintenanceWindows", () => {
|
||||
let req, res, next, stub;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
body: {
|
||||
@@ -103,6 +104,7 @@ describe("maintenanceWindowController - createMaintenanceWindows", () => {
|
||||
});
|
||||
|
||||
describe("maintenanceWindowController - getMaintenanceWindowById", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
body: {},
|
||||
@@ -154,6 +156,7 @@ describe("maintenanceWindowController - getMaintenanceWindowById", () => {
|
||||
});
|
||||
|
||||
describe("maintenanceWindowController - getMaintenanceWindowsByTeamId", () => {
|
||||
let req, res, next, stub;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
body: {},
|
||||
@@ -220,6 +223,7 @@ describe("maintenanceWindowController - getMaintenanceWindowsByTeamId", () => {
|
||||
});
|
||||
|
||||
describe("maintenanceWindowController - getMaintenanceWindowsByMonitorId", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
body: {},
|
||||
@@ -283,6 +287,7 @@ describe("maintenanceWindowController - getMaintenanceWindowsByMonitorId", () =>
|
||||
});
|
||||
|
||||
describe("maintenanceWindowController - deleteMaintenanceWindow", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
body: {},
|
||||
@@ -338,6 +343,7 @@ describe("maintenanceWindowController - deleteMaintenanceWindow", () => {
|
||||
});
|
||||
|
||||
describe("maintenanceWindowController - editMaintenanceWindow", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
body: {
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,16 +1,15 @@
|
||||
const { afterEach } = require("node:test");
|
||||
const {
|
||||
import { afterEach } from "node:test";
|
||||
import {
|
||||
getMetrics,
|
||||
getJobs,
|
||||
addJob,
|
||||
obliterateQueue,
|
||||
} = require("../../controllers/queueController");
|
||||
const SERVICE_NAME = "JobQueueController";
|
||||
|
||||
const { errorMessages, successMessages } = require("../../utils/messages");
|
||||
const sinon = require("sinon");
|
||||
} from "../../controllers/queueController.js";
|
||||
import { successMessages } from "../../utils/messages.js";
|
||||
import sinon from "sinon";
|
||||
|
||||
describe("Queue Controller - getMetrics", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
headers: {},
|
||||
@@ -26,7 +25,6 @@ describe("Queue Controller - getMetrics", () => {
|
||||
json: sinon.stub(),
|
||||
};
|
||||
next = sinon.stub();
|
||||
handleError = sinon.stub();
|
||||
});
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
@@ -52,6 +50,7 @@ describe("Queue Controller - getMetrics", () => {
|
||||
});
|
||||
|
||||
describe("Queue Controller - getJobs", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
headers: {},
|
||||
@@ -67,7 +66,6 @@ describe("Queue Controller - getJobs", () => {
|
||||
json: sinon.stub(),
|
||||
};
|
||||
next = sinon.stub();
|
||||
handleError = sinon.stub();
|
||||
});
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
@@ -92,6 +90,7 @@ describe("Queue Controller - getJobs", () => {
|
||||
});
|
||||
|
||||
describe("Queue Controller - addJob", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
headers: {},
|
||||
@@ -107,7 +106,6 @@ describe("Queue Controller - addJob", () => {
|
||||
json: sinon.stub(),
|
||||
};
|
||||
next = sinon.stub();
|
||||
handleError = sinon.stub();
|
||||
});
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
@@ -130,6 +128,7 @@ describe("Queue Controller - addJob", () => {
|
||||
});
|
||||
|
||||
describe("Queue Controller - obliterateQueue", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
headers: {},
|
||||
@@ -145,7 +144,6 @@ describe("Queue Controller - obliterateQueue", () => {
|
||||
json: sinon.stub(),
|
||||
};
|
||||
next = sinon.stub();
|
||||
handleError = sinon.stub();
|
||||
});
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
const { afterEach } = require("node:test");
|
||||
const {
|
||||
import { afterEach } from "node:test";
|
||||
import {
|
||||
getAppSettings,
|
||||
updateAppSettings,
|
||||
} = require("../../controllers/settingsController");
|
||||
} from "../../controllers/settingsController.js";
|
||||
|
||||
const { errorMessages, successMessages } = require("../../utils/messages");
|
||||
const sinon = require("sinon");
|
||||
import { successMessages } from "../../utils/messages.js";
|
||||
import sinon from "sinon";
|
||||
|
||||
describe("Settings Controller - getAppSettings", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
headers: {},
|
||||
@@ -23,7 +24,6 @@ describe("Settings Controller - getAppSettings", () => {
|
||||
json: sinon.stub(),
|
||||
};
|
||||
next = sinon.stub();
|
||||
handleError = sinon.stub();
|
||||
});
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
@@ -49,6 +49,7 @@ describe("Settings Controller - getAppSettings", () => {
|
||||
});
|
||||
|
||||
describe("Settings Controller - updateAppSettings", () => {
|
||||
let req, res, next;
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
headers: {},
|
||||
@@ -66,7 +67,6 @@ describe("Settings Controller - updateAppSettings", () => {
|
||||
json: sinon.stub(),
|
||||
};
|
||||
next = sinon.stub();
|
||||
handleError = sinon.stub();
|
||||
});
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { NormalizeData, calculatePercentile } from "../../utils/dataUtils.js";
|
||||
import sinon from "sinon";
|
||||
|
||||
describe("NormalizeData", () => {
|
||||
it("should normalize response times when checks length is greater than 1", () => {
|
||||
const checks = [
|
||||
{ responseTime: 20, _doc: { id: 1 } },
|
||||
{ responseTime: 40, _doc: { id: 2 } },
|
||||
{ responseTime: 60, _doc: { id: 3 } },
|
||||
];
|
||||
const rangeMin = 1;
|
||||
const rangeMax = 100;
|
||||
|
||||
const result = NormalizeData(checks, rangeMin, rangeMax);
|
||||
|
||||
expect(result).to.be.an("array");
|
||||
expect(result).to.have.lengthOf(3);
|
||||
result.forEach((check) => {
|
||||
expect(check).to.have.property("responseTime").that.is.a("number");
|
||||
expect(check).to.have.property("originalResponseTime").that.is.a("number");
|
||||
});
|
||||
});
|
||||
|
||||
it("should return checks with original response times when checks length is 1", () => {
|
||||
const checks = [{ responseTime: 20, _doc: { id: 1 } }];
|
||||
const rangeMin = 1;
|
||||
const rangeMax = 100;
|
||||
|
||||
const result = NormalizeData(checks, rangeMin, rangeMax);
|
||||
expect(result).to.be.an("array");
|
||||
expect(result).to.have.lengthOf(1);
|
||||
expect(result[0]).to.have.property("originalResponseTime", 20);
|
||||
});
|
||||
|
||||
it("should handle edge cases with extreme response times", () => {
|
||||
const checks = [
|
||||
{ responseTime: 5, _doc: { id: 1 } },
|
||||
{ responseTime: 95, _doc: { id: 2 } },
|
||||
];
|
||||
const rangeMin = 1;
|
||||
const rangeMax = 100;
|
||||
|
||||
const result = NormalizeData(checks, rangeMin, rangeMax);
|
||||
|
||||
expect(result).to.be.an("array");
|
||||
expect(result).to.have.lengthOf(2);
|
||||
expect(result[0]).to.have.property("responseTime").that.is.at.least(rangeMin);
|
||||
expect(result[1]).to.have.property("responseTime").that.is.at.most(rangeMax);
|
||||
});
|
||||
});
|
||||
|
||||
describe("calculatePercentile", () => {
|
||||
it("should return the lower value when upper is greater than or equal to the length of the sorted array", () => {
|
||||
const checks = [
|
||||
{ responseTime: 10 },
|
||||
{ responseTime: 20 },
|
||||
{ responseTime: 30 },
|
||||
{ responseTime: 40 },
|
||||
{ responseTime: 50 },
|
||||
];
|
||||
|
||||
const percentile = 100;
|
||||
const result = calculatePercentile(checks, percentile);
|
||||
const expected = 50;
|
||||
console.log(result);
|
||||
expect(result).to.equal(expected);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import { expect } from "chai";
|
||||
import sinon from "sinon";
|
||||
import sharp from "sharp";
|
||||
import { GenerateAvatarImage } from "../../utils/imageProcessing.js";
|
||||
|
||||
describe("imageProcessing - GenerateAvatarImage", () => {
|
||||
it("should resize the image to 64x64 and return a base64 string", async () => {
|
||||
const file = {
|
||||
buffer: Buffer.from("test image buffer"),
|
||||
};
|
||||
|
||||
// Stub the sharp function
|
||||
const toBufferStub = sinon.stub().resolves(Buffer.from("resized image buffer"));
|
||||
const resizeStub = sinon.stub().returns({ toBuffer: toBufferStub });
|
||||
const sharpStub = sinon
|
||||
.stub(sharp.prototype, "resize")
|
||||
.returns({ toBuffer: toBufferStub });
|
||||
|
||||
const result = await GenerateAvatarImage(file);
|
||||
|
||||
// Verify the result
|
||||
const expected = Buffer.from("resized image buffer").toString("base64");
|
||||
expect(result).to.equal(expected);
|
||||
|
||||
// Verify that the sharp function was called with the correct arguments
|
||||
expect(sharpStub.calledOnceWith({ width: 64, height: 64, fit: "cover" })).to.be.true;
|
||||
expect(toBufferStub.calledOnce).to.be.true;
|
||||
|
||||
// Restore the stubbed functions
|
||||
sharpStub.restore();
|
||||
});
|
||||
|
||||
it("should throw an error if resizing fails", async () => {
|
||||
const file = {
|
||||
buffer: Buffer.from("test image buffer"),
|
||||
};
|
||||
|
||||
// Stub the sharp function to throw an error
|
||||
const toBufferStub = sinon.stub().rejects(new Error("Resizing failed"));
|
||||
const resizeStub = sinon.stub().returns({ toBuffer: toBufferStub });
|
||||
const sharpStub = sinon
|
||||
.stub(sharp.prototype, "resize")
|
||||
.returns({ toBuffer: toBufferStub });
|
||||
|
||||
try {
|
||||
await GenerateAvatarImage(file);
|
||||
// If no error is thrown, fail the test
|
||||
expect.fail("Expected error to be thrown");
|
||||
} catch (error) {
|
||||
// Verify that the error message is correct
|
||||
expect(error.message).to.equal("Resizing failed");
|
||||
}
|
||||
|
||||
// Restore the stubbed functions
|
||||
sharpStub.restore();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import { errorMessages, successMessages } from "../../utils/messages.js";
|
||||
describe("Messages", () => {
|
||||
describe("messages - errorMessages", () => {
|
||||
it("should have a DB_FIND_MONITOR_BY_ID function", () => {
|
||||
const monitorId = "12345";
|
||||
expect(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId)).to.equal(
|
||||
`Monitor with id ${monitorId} not found`
|
||||
);
|
||||
});
|
||||
|
||||
it("should have a DB_DELETE_CHECKS function", () => {
|
||||
const monitorId = "12345";
|
||||
expect(errorMessages.DB_DELETE_CHECKS(monitorId)).to.equal(
|
||||
`No checks found for monitor with id ${monitorId}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("messages - successMessages", () => {
|
||||
it("should have a MONITOR_GET_BY_USER_ID function", () => {
|
||||
const userId = "12345";
|
||||
expect(successMessages.MONITOR_GET_BY_USER_ID(userId)).to.equal(
|
||||
`Got monitor for ${userId} successfully"`
|
||||
);
|
||||
});
|
||||
|
||||
// Add more tests for other success messages as needed
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { ParseBoolean, getTokenFromHeaders } from "../../utils/utils.js";
|
||||
|
||||
describe("utils - ParseBoolean", () => {
|
||||
it("should return true", () => {
|
||||
const result = ParseBoolean("true");
|
||||
expect(result).to.be.true;
|
||||
});
|
||||
|
||||
it("should return false", () => {
|
||||
const result = ParseBoolean("false");
|
||||
expect(result).to.be.false;
|
||||
});
|
||||
|
||||
it("should return false", () => {
|
||||
const result = ParseBoolean(null);
|
||||
expect(result).to.be.false;
|
||||
});
|
||||
|
||||
it("should return false", () => {
|
||||
const result = ParseBoolean(undefined);
|
||||
expect(result).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe("utils - getTokenFromHeaders", () => {
|
||||
it("should throw an error if authorization header is missing", () => {
|
||||
const headers = {};
|
||||
expect(() => getTokenFromHeaders(headers)).to.throw("No auth headers");
|
||||
});
|
||||
|
||||
it("should throw an error if authorization header does not start with Bearer", () => {
|
||||
const headers = { authorization: "Basic abcdef" };
|
||||
expect(() => getTokenFromHeaders(headers)).to.throw("Invalid auth headers");
|
||||
});
|
||||
|
||||
it("should return the token if authorization header is correctly formatted", () => {
|
||||
const headers = { authorization: "Bearer abcdef" };
|
||||
expect(getTokenFromHeaders(headers)).to.equal("abcdef");
|
||||
});
|
||||
|
||||
it("should throw an error if authorization header has more than two parts", () => {
|
||||
const headers = { authorization: "Bearer abc def" };
|
||||
expect(() => getTokenFromHeaders(headers)).to.throw("Invalid auth headers");
|
||||
});
|
||||
|
||||
it("should throw an error if authorization header has less than two parts", () => {
|
||||
const headers = { authorization: "Bearer" };
|
||||
expect(() => getTokenFromHeaders(headers)).to.throw("Invalid auth headers");
|
||||
});
|
||||
});
|
||||
+35
-41
@@ -1,50 +1,44 @@
|
||||
const calculatePercentile = (arr, percentile) => {
|
||||
const sorted = arr.slice().sort((a, b) => a.responseTime - b.responseTime);
|
||||
const index = (percentile / 100) * (sorted.length - 1);
|
||||
const lower = Math.floor(index);
|
||||
const upper = lower + 1;
|
||||
const weight = index % 1;
|
||||
if (upper >= sorted.length) return sorted[lower].responseTime;
|
||||
return (
|
||||
sorted[lower].responseTime * (1 - weight) +
|
||||
sorted[upper].responseTime * weight
|
||||
);
|
||||
const sorted = arr.slice().sort((a, b) => a.responseTime - b.responseTime);
|
||||
const index = (percentile / 100) * (sorted.length - 1);
|
||||
const lower = Math.floor(index);
|
||||
const upper = lower + 1;
|
||||
const weight = index % 1;
|
||||
if (upper >= sorted.length) return sorted[lower].responseTime;
|
||||
return sorted[lower].responseTime * (1 - weight) + sorted[upper].responseTime * weight;
|
||||
};
|
||||
|
||||
const NormalizeData = (checks, rangeMin, rangeMax) => {
|
||||
if (checks.length > 1) {
|
||||
// Get the 5th and 95th percentile
|
||||
const min = calculatePercentile(checks, 0);
|
||||
const max = calculatePercentile(checks, 95);
|
||||
if (checks.length > 1) {
|
||||
// Get the 5th and 95th percentile
|
||||
const min = calculatePercentile(checks, 0);
|
||||
const max = calculatePercentile(checks, 95);
|
||||
|
||||
const normalizedChecks = checks.map((check) => {
|
||||
const originalResponseTime = check.responseTime;
|
||||
// Normalize the response time between 1 and 100
|
||||
let normalizedResponseTime =
|
||||
rangeMin +
|
||||
((check.responseTime - min) * (rangeMax - rangeMin)) / (max - min);
|
||||
const normalizedChecks = checks.map((check) => {
|
||||
const originalResponseTime = check.responseTime;
|
||||
// Normalize the response time between 1 and 100
|
||||
let normalizedResponseTime =
|
||||
rangeMin + ((check.responseTime - min) * (rangeMax - rangeMin)) / (max - min);
|
||||
|
||||
// Put a floor on the response times so we don't have extreme outliers
|
||||
// Better visuals
|
||||
normalizedResponseTime = Math.max(
|
||||
rangeMin,
|
||||
Math.min(rangeMax, normalizedResponseTime)
|
||||
);
|
||||
return {
|
||||
...check._doc,
|
||||
responseTime: normalizedResponseTime,
|
||||
originalResponseTime: originalResponseTime,
|
||||
};
|
||||
});
|
||||
// Put a floor on the response times so we don't have extreme outliers
|
||||
// Better visuals
|
||||
normalizedResponseTime = Math.max(
|
||||
rangeMin,
|
||||
Math.min(rangeMax, normalizedResponseTime)
|
||||
);
|
||||
return {
|
||||
...check._doc,
|
||||
responseTime: normalizedResponseTime,
|
||||
originalResponseTime: originalResponseTime,
|
||||
};
|
||||
});
|
||||
|
||||
return normalizedChecks;
|
||||
} else {
|
||||
return checks.map((check) => {
|
||||
return { ...check._doc, originalResponseTime: check.responseTime };
|
||||
});
|
||||
}
|
||||
return normalizedChecks;
|
||||
} else {
|
||||
return checks.map((check) => {
|
||||
return { ...check._doc, originalResponseTime: check.responseTime };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
NormalizeData,
|
||||
};
|
||||
export { calculatePercentile, NormalizeData };
|
||||
@@ -1,4 +1,4 @@
|
||||
const sharp = require("sharp");
|
||||
import sharp from "sharp";
|
||||
/**
|
||||
* Generates a 64 * 64 pixel image from a given image
|
||||
* @param {} file
|
||||
@@ -22,6 +22,4 @@ const GenerateAvatarImage = async (file) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
GenerateAvatarImage,
|
||||
};
|
||||
export { GenerateAvatarImage };
|
||||
+10
-10
@@ -1,8 +1,8 @@
|
||||
const winston = require('winston');
|
||||
import winston from "winston";
|
||||
/**
|
||||
* @module
|
||||
* @example
|
||||
* logger.info("Registered a new user!")
|
||||
* logger.info("Registered a new user!")
|
||||
* logger.warn("User not found!")
|
||||
* logger.error("Cannot save")
|
||||
* @example
|
||||
@@ -12,15 +12,15 @@ const winston = require('winston');
|
||||
* logger.error("User not found!",{"service":"Auth"})
|
||||
*/
|
||||
const logger = winston.createLogger({
|
||||
level: 'info',
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp(),
|
||||
winston.format.json()
|
||||
),
|
||||
transports: [
|
||||
level: "info",
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp(),
|
||||
winston.format.json()
|
||||
),
|
||||
transports: [
|
||||
new winston.transports.Console(),
|
||||
new winston.transports.File({ filename: 'app.log' }),
|
||||
new winston.transports.File({ filename: "app.log" }),
|
||||
],
|
||||
});
|
||||
|
||||
module.exports = logger;
|
||||
export default logger;
|
||||
@@ -121,7 +121,4 @@ const successMessages = {
|
||||
UPDATE_APP_SETTINGS: "Updated app settings successfully",
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
errorMessages,
|
||||
successMessages,
|
||||
};
|
||||
export { errorMessages, successMessages };
|
||||
+19
-23
@@ -4,36 +4,32 @@
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const ParseBoolean = (value) => {
|
||||
if (value === true || value === "true") {
|
||||
return true;
|
||||
} else if (
|
||||
value === false ||
|
||||
value === "false" ||
|
||||
value === null ||
|
||||
value === undefined
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (value === true || value === "true") {
|
||||
return true;
|
||||
} else if (
|
||||
value === false ||
|
||||
value === "false" ||
|
||||
value === null ||
|
||||
value === undefined
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
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 tokenType = Object.freeze({
|
||||
ACCESS_TOKEN: "Access token",
|
||||
REFRESH_TOKEN: "Refresh token"
|
||||
ACCESS_TOKEN: "Access token",
|
||||
REFRESH_TOKEN: "Refresh token",
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
ParseBoolean,
|
||||
getTokenFromHeaders,
|
||||
tokenType,
|
||||
};
|
||||
export { ParseBoolean, getTokenFromHeaders, tokenType };
|
||||
@@ -1,7 +1,4 @@
|
||||
const exp = require("constants");
|
||||
const joi = require("joi");
|
||||
const { normalize } = require("path");
|
||||
const { start } = require("repl");
|
||||
import joi from "joi";
|
||||
|
||||
//****************************************
|
||||
// Custom Validators
|
||||
@@ -143,7 +140,7 @@ const inviteBodyValidation = joi.object({
|
||||
teamId: joi.string().required(),
|
||||
});
|
||||
|
||||
const inviteVerifciationBodyValidation = joi.object({
|
||||
const inviteVerificationBodyValidation = joi.object({
|
||||
token: joi.string().required(),
|
||||
});
|
||||
|
||||
@@ -427,7 +424,7 @@ const updateAppSettingsBodyValidation = joi.object({
|
||||
systemEmailPassword: joi.string().allow(""),
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
export {
|
||||
roleValidatior,
|
||||
loginValidation,
|
||||
registrationBodyValidation,
|
||||
@@ -436,7 +433,7 @@ module.exports = {
|
||||
newPasswordValidation,
|
||||
inviteRoleValidation,
|
||||
inviteBodyValidation,
|
||||
inviteVerificationBodyValidation: inviteVerifciationBodyValidation,
|
||||
inviteVerificationBodyValidation,
|
||||
createMonitorBodyValidation,
|
||||
getMonitorByIdParamValidation,
|
||||
getMonitorByIdQueryValidation,
|
||||
|
||||
Reference in new issue
Block a user