mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-27 04:09:46 -06:00
refactor controllers to be class based
This commit is contained in:
@@ -17,500 +17,501 @@ import { handleValidationError, handleError } from "./controllerUtils.js";
|
||||
const SERVICE_NAME = "authController";
|
||||
dotenv.config();
|
||||
|
||||
/**
|
||||
* Creates and returns JWT token with an arbitrary payload
|
||||
* @function
|
||||
* @param {Object} payload
|
||||
* @param {tokenType} typeOfToken - Whether to generate refresh token with long TTL or access token with short TTL.
|
||||
* @param {Object} appSettings
|
||||
* @returns {String}
|
||||
* @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;
|
||||
|
||||
return jwt.sign(payloadData, tokenSecret, { expiresIn: tokenTTL });
|
||||
} catch (error) {
|
||||
throw handleError(error, SERVICE_NAME, "issueToken");
|
||||
class AuthController {
|
||||
constructor(db, settingsService, emailService, jobQueue) {
|
||||
this.db = db;
|
||||
this.settingsService = settingsService;
|
||||
this.emailService = emailService;
|
||||
this.jobQueue = jobQueue;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a new user. If the user is the first account, a JWT secret is created. If not, an invite token is required.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.inviteToken - The invite token for registration.
|
||||
* @property {Object} req.file - The file object for the user's profile image.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the creation of the user, the created user data, and a JWT token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const registerUser = async (req, res, next) => {
|
||||
// joi validation
|
||||
try {
|
||||
await registrationBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
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 });
|
||||
/**
|
||||
* Creates and returns JWT token with an arbitrary payload
|
||||
* @function
|
||||
* @param {Object} payload
|
||||
* @param {tokenType} typeOfToken - Whether to generate refresh token with long TTL or access token with short TTL.
|
||||
* @param {Object} appSettings
|
||||
* @returns {String}
|
||||
* @throws {Error}
|
||||
*/
|
||||
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;
|
||||
|
||||
return jwt.sign(payloadData, tokenSecret, { expiresIn: tokenTTL });
|
||||
} catch (error) {
|
||||
throw handleError(error, SERVICE_NAME, "issueToken");
|
||||
}
|
||||
};
|
||||
|
||||
const newUser = await req.db.insertUser({ ...req.body }, req.file);
|
||||
logger.info({
|
||||
message: successMessages.AUTH_CREATE_USER,
|
||||
service: SERVICE_NAME,
|
||||
details: newUser._id,
|
||||
});
|
||||
/**
|
||||
* Registers a new user. If the user is the first account, a JWT secret is created. If not, an invite token is required.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.inviteToken - The invite token for registration.
|
||||
* @property {Object} req.file - The file object for the user's profile image.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the creation of the user, the created user data, and a JWT token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
registerUser = async (req, res, next) => {
|
||||
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 this.db.checkSuperadmin(req, res);
|
||||
if (superAdminExists) {
|
||||
await this.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 this.db.updateAppSettings({ jwtSecret });
|
||||
}
|
||||
|
||||
const userForToken = { ...newUser._doc };
|
||||
delete userForToken.profileImage;
|
||||
delete userForToken.avatarImage;
|
||||
|
||||
const appSettings = await req.settingsService.getSettings();
|
||||
|
||||
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({
|
||||
message: error.message,
|
||||
service: SERVICE_NAME,
|
||||
method: "registerUser",
|
||||
stack: error.stack,
|
||||
});
|
||||
const newUser = await this.db.insertUser({ ...req.body }, req.file);
|
||||
logger.info({
|
||||
message: successMessages.AUTH_CREATE_USER,
|
||||
service: SERVICE_NAME,
|
||||
details: newUser._id,
|
||||
});
|
||||
|
||||
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"));
|
||||
}
|
||||
};
|
||||
const userForToken = { ...newUser._doc };
|
||||
delete userForToken.profileImage;
|
||||
delete userForToken.avatarImage;
|
||||
|
||||
/**
|
||||
* Logs in a user by validating the user's credentials and issuing a JWT token.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.email - The email of the user.
|
||||
* @property {string} req.body.password - The password of the user.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the login of the user, the user data (without password and avatar image), and a JWT token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422) or the password is incorrect.
|
||||
*/
|
||||
const 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;
|
||||
const appSettings = await this.settingsService.getSettings();
|
||||
|
||||
// Check if user exists
|
||||
const user = await req.db.getUserByEmail(email);
|
||||
const token = this.issueToken(userForToken, tokenType.ACCESS_TOKEN, appSettings);
|
||||
const refreshToken = this.issueToken({}, tokenType.REFRESH_TOKEN, appSettings);
|
||||
|
||||
// Compare password
|
||||
const match = await user.comparePassword(password);
|
||||
if (match !== true) {
|
||||
next(new Error(errorMessages.AUTH_INCORRECT_PASSWORD));
|
||||
this.emailService
|
||||
.buildAndSendEmail(
|
||||
"welcomeEmailTemplate",
|
||||
{ name: newUser.firstName },
|
||||
newUser.email,
|
||||
"Welcome to Uptime Monitor"
|
||||
)
|
||||
.catch((error) => {
|
||||
logger.error({
|
||||
message: error.message,
|
||||
service: SERVICE_NAME,
|
||||
method: "registerUser",
|
||||
stack: error.stack,
|
||||
});
|
||||
});
|
||||
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs in a user by validating the user's credentials and issuing a JWT token.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.email - The email of the user.
|
||||
* @property {string} req.body.password - The password of the user.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the login of the user, the user data (without password and avatar image), and a JWT token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422) or the password is incorrect.
|
||||
*/
|
||||
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 this.db.getUserByEmail(email);
|
||||
|
||||
// Compare password
|
||||
const match = await user.comparePassword(password);
|
||||
if (match !== true) {
|
||||
next(new Error(errorMessages.AUTH_INCORRECT_PASSWORD));
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove password from user object. Should this be abstracted to DB layer?
|
||||
const userWithoutPassword = { ...user._doc };
|
||||
delete userWithoutPassword.password;
|
||||
delete userWithoutPassword.avatarImage;
|
||||
|
||||
// Happy path, return token
|
||||
const appSettings = await this.settingsService.getSettings();
|
||||
const token = this.issueToken(
|
||||
userWithoutPassword,
|
||||
tokenType.ACCESS_TOKEN,
|
||||
appSettings
|
||||
);
|
||||
const refreshToken = this.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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates new auth token if the refresh token is valid
|
||||
* @async
|
||||
* @param {Express.Request} req - The Express request object.
|
||||
* @property {Object} req.headers - The parameter of the request.
|
||||
* @param {Express.Response} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating new auth token is generated.
|
||||
* @throws {Error} If there is an error during the process such as any of the token is not received
|
||||
*/
|
||||
refreshAuthToken = async (req, res, next) => {
|
||||
try {
|
||||
// check for refreshToken
|
||||
const refreshToken = req.headers["x-refresh-token"];
|
||||
|
||||
if (!refreshToken) {
|
||||
// No refresh token provided
|
||||
const error = new Error(errorMessages.NO_REFRESH_TOKEN);
|
||||
error.status = 401;
|
||||
error.service = SERVICE_NAME;
|
||||
error.method = "refreshAuthToken";
|
||||
return next(error);
|
||||
}
|
||||
|
||||
// Verify refresh token
|
||||
const appSettings = await this.settingsService.getSettings();
|
||||
const { refreshTokenSecret } = appSettings;
|
||||
jwt.verify(refreshToken, refreshTokenSecret, async (refreshErr, refreshDecoded) => {
|
||||
if (refreshErr) {
|
||||
// Invalid or expired refresh token, trigger logout
|
||||
const errorMessage =
|
||||
refreshErr.name === "TokenExpiredError"
|
||||
? errorMessages.EXPIRED_REFRESH_TOKEN
|
||||
: errorMessages.INVALID_REFRESH_TOKEN;
|
||||
const error = new Error(errorMessage);
|
||||
error.status = 401;
|
||||
error.service = SERVICE_NAME;
|
||||
return next(error);
|
||||
}
|
||||
});
|
||||
// Refresh token is valid and unexpired, generate new access token
|
||||
const oldAuthToken = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = await this.settingsService.getSettings();
|
||||
const payloadData = jwt.verify(oldAuthToken, jwtSecret, { ignoreExpiration: true });
|
||||
// delete old token related data
|
||||
delete payloadData.iat;
|
||||
delete payloadData.exp;
|
||||
const newAuthToken = this.issueToken(
|
||||
payloadData,
|
||||
tokenType.ACCESS_TOKEN,
|
||||
appSettings
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_TOKEN_REFRESHED,
|
||||
data: { user: payloadData, token: newAuthToken, refreshToken: refreshToken },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "refreshAuthToken"));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Edits a user's information. If the user wants to change their password, the current password is checked before updating to the new password.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.userId - The ID of the user to be edited.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.password - The current password of the user.
|
||||
* @property {string} req.body.newPassword - The new password of the user.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the update of the user, and the updated user data.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422), the user is unauthorized (401), or the password is incorrect (403).
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
// Remove password from user object. Should this be abstracted to DB layer?
|
||||
const userWithoutPassword = { ...user._doc };
|
||||
delete userWithoutPassword.password;
|
||||
delete userWithoutPassword.avatarImage;
|
||||
|
||||
// Happy path, return token
|
||||
const appSettings = 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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates new auth token if the refresh token is valid
|
||||
* @async
|
||||
* @param {Express.Request} req - The Express request object.
|
||||
* @property {Object} req.headers - The parameter of the request.
|
||||
* @param {Express.Response} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating new auth token is generated.
|
||||
* @throws {Error} If there is an error during the process such as any of the token is not received
|
||||
*/
|
||||
const refreshAuthToken = async (req, res, next) => {
|
||||
try {
|
||||
// check for refreshToken
|
||||
const refreshToken = req.headers["x-refresh-token"];
|
||||
|
||||
if (!refreshToken) {
|
||||
// No refresh token provided
|
||||
const error = new Error(errorMessages.NO_REFRESH_TOKEN);
|
||||
// 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;
|
||||
error.method = "refreshAuthToken";
|
||||
return next(error);
|
||||
next(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify refresh token
|
||||
const appSettings = await req.settingsService.getSettings();
|
||||
const { refreshTokenSecret } = appSettings;
|
||||
jwt.verify(refreshToken, refreshTokenSecret, async (refreshErr, refreshDecoded) => {
|
||||
if (refreshErr) {
|
||||
// Invalid or expired refresh token, trigger logout
|
||||
const errorMessage =
|
||||
refreshErr.name === "TokenExpiredError"
|
||||
? errorMessages.EXPIRED_REFRESH_TOKEN
|
||||
: errorMessages.INVALID_REFRESH_TOKEN;
|
||||
const error = new Error(errorMessage);
|
||||
error.status = 401;
|
||||
error.service = SERVICE_NAME;
|
||||
return next(error);
|
||||
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 } = this.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 this.db.getUserByEmail(email);
|
||||
// Compare passwords
|
||||
const match = await user.comparePassword(req.body.password);
|
||||
// If not a match, throw a 403
|
||||
// 403 instead of 401 to avoid triggering axios interceptor
|
||||
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;
|
||||
}
|
||||
});
|
||||
// Refresh token is valid and unexpired, generate new access token
|
||||
const oldAuthToken = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = await req.settingsService.getSettings();
|
||||
const payloadData = jwt.verify(oldAuthToken, jwtSecret, { ignoreExpiration: true });
|
||||
// delete old token related data
|
||||
delete payloadData.iat;
|
||||
delete payloadData.exp;
|
||||
const newAuthToken = issueToken(payloadData, tokenType.ACCESS_TOKEN, appSettings);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_TOKEN_REFRESHED,
|
||||
data: { user: payloadData, token: newAuthToken, refreshToken: refreshToken },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "refreshAuthToken"));
|
||||
}
|
||||
};
|
||||
const updatedUser = await this.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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Edits a user's information. If the user wants to change their password, the current password is checked before updating to the new password.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.userId - The ID of the user to be edited.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.password - The current password of the user.
|
||||
* @property {string} req.body.newPassword - The new password of the user.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the update of the user, and the updated user data.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422), the user is unauthorized (401), or the password is incorrect (403).
|
||||
*/
|
||||
const 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;
|
||||
}
|
||||
|
||||
// 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
|
||||
// 403 instead of 401 to avoid triggering axios interceptor
|
||||
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;
|
||||
/**
|
||||
* Checks if a superadmin account exists in the database.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the existence of a superadmin, and a boolean indicating the existence of a superadmin.
|
||||
* @throws {Error} If there is an error during the process.
|
||||
*/
|
||||
checkSuperadminExists = async (req, res, next) => {
|
||||
try {
|
||||
const superAdminExists = await this.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"));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Requests a recovery token for a user. The user's email is validated and a recovery token is created and sent via email.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.email - The email of the user requesting recovery.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the creation of the recovery token, and the message ID of the sent email.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
requestRecovery = async (req, res, next) => {
|
||||
try {
|
||||
await recoveryValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
const validationError = handleValidationError(error, SERVICE_NAME);
|
||||
next(validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a superadmin account exists in the database.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the existence of a superadmin, and a boolean indicating the existence of a superadmin.
|
||||
* @throws {Error} If there is an error during the process.
|
||||
*/
|
||||
const checkSuperadminExists = async (req, res, next) => {
|
||||
try {
|
||||
const superAdminExists = await req.db.checkSuperadmin(req, res);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_ADMIN_EXISTS,
|
||||
data: superAdminExists,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "checkSuperadminController"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Requests a recovery token for a user. The user's email is validated and a recovery token is created and sent via email.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.email - The email of the user requesting recovery.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the creation of the recovery token, and the message ID of the sent email.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const requestRecovery = async (req, res, next) => {
|
||||
try {
|
||||
await recoveryValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
const validationError = handleValidationError(error, SERVICE_NAME);
|
||||
next(validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { email } = req.body;
|
||||
const user = await req.db.getUserByEmail(email);
|
||||
const recoveryToken = await req.db.requestRecoveryToken(req, res);
|
||||
const name = user.firstName;
|
||||
const { clientHost } = req.settingsService.getSettings();
|
||||
const url = `${clientHost}/set-new-password/${recoveryToken.token}`;
|
||||
const msgId = await req.emailService.buildAndSendEmail(
|
||||
"passwordResetTemplate",
|
||||
{
|
||||
name,
|
||||
try {
|
||||
const { email } = req.body;
|
||||
const user = await this.db.getUserByEmail(email);
|
||||
const recoveryToken = await this.db.requestRecoveryToken(req, res);
|
||||
const name = user.firstName;
|
||||
const { clientHost } = this.settingsService.getSettings();
|
||||
const url = `${clientHost}/set-new-password/${recoveryToken.token}`;
|
||||
const msgId = await this.emailService.buildAndSendEmail(
|
||||
"passwordResetTemplate",
|
||||
{
|
||||
name,
|
||||
email,
|
||||
url,
|
||||
},
|
||||
email,
|
||||
url,
|
||||
},
|
||||
email,
|
||||
"Checkmate Password Reset"
|
||||
);
|
||||
"Checkmate Password Reset"
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN,
|
||||
data: msgId,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "recoveryRequestController"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates a recovery token. The recovery token is validated and if valid, a success message is returned.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.token - The recovery token to be validated.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status and a message indicating the validation of the recovery token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const validateRecovery = async (req, res, next) => {
|
||||
try {
|
||||
await recoveryTokenValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Resets a user's password. The new password is validated and if valid, the user's password is updated in the database and a new JWT token is issued.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.token - The recovery token.
|
||||
* @property {string} req.body.password - The new password of the user.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the reset of the password, the updated user data (without password and avatar image), and a new JWT token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const resetPassword = async (req, res, next) => {
|
||||
try {
|
||||
await newPasswordValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a user and all associated monitors, checks, and alerts.
|
||||
*
|
||||
* @param {Object} req - The request object.
|
||||
* @param {Object} res - The response object.
|
||||
* @param {Function} next - The next middleware function.
|
||||
* @returns {Object} The response object with success status and message.
|
||||
* @throws {Error} If user validation fails or user is not found in the database.
|
||||
*/
|
||||
const deleteUser = async (req, res, next) => {
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const decodedToken = jwt.decode(token);
|
||||
const { email } = decodedToken;
|
||||
|
||||
// Check if the user exists
|
||||
const user = await req.db.getUserByEmail(email);
|
||||
// 1. Find all the monitors associated with the team ID if superadmin
|
||||
|
||||
const result = await req.db.getMonitorsByTeamId({
|
||||
params: { teamId: user.teamId },
|
||||
});
|
||||
|
||||
if (user.role.includes("superadmin")) {
|
||||
//2. Remove all jobs, delete checks and alerts
|
||||
result?.monitors.length > 0 &&
|
||||
(await Promise.all(
|
||||
result.monitors.map(async (monitor) => {
|
||||
await req.jobQueue.deleteJob(monitor);
|
||||
await req.db.deleteChecks(monitor._id);
|
||||
await req.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
||||
await req.db.deleteNotificationsByMonitorId(monitor._id);
|
||||
})
|
||||
));
|
||||
|
||||
// 3. Delete team
|
||||
await req.db.deleteTeam(user.teamId);
|
||||
// 4. Delete all other team members
|
||||
await req.db.deleteAllOtherUsers();
|
||||
// 5. Delete each monitor
|
||||
await req.db.deleteMonitorsByUserId(user._id);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN,
|
||||
data: msgId,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "recoveryRequestController"));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Validates a recovery token. The recovery token is validated and if valid, a success message is returned.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.token - The recovery token to be validated.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status and a message indicating the validation of the recovery token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
validateRecovery = async (req, res, next) => {
|
||||
try {
|
||||
await recoveryTokenValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
const validationError = handleValidationError(error, SERVICE_NAME);
|
||||
next(validationError);
|
||||
return;
|
||||
}
|
||||
// 6. Delete the user by id
|
||||
await req.db.deleteUser(user._id);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_DELETE_USER,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteUserController"));
|
||||
}
|
||||
};
|
||||
|
||||
const getAllUsers = async (req, res, next) => {
|
||||
try {
|
||||
const allUsers = await req.db.getAllUsers(req, res);
|
||||
res.status(200).json({ success: true, msg: "Got all users", data: allUsers });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAllUsersController"));
|
||||
}
|
||||
};
|
||||
try {
|
||||
await this.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"));
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
issueToken,
|
||||
registerUser,
|
||||
loginUser,
|
||||
refreshAuthToken,
|
||||
editUser,
|
||||
checkSuperadminExists,
|
||||
requestRecovery,
|
||||
validateRecovery,
|
||||
resetPassword,
|
||||
deleteUser,
|
||||
getAllUsers,
|
||||
};
|
||||
/**
|
||||
* Resets a user's password. The new password is validated and if valid, the user's password is updated in the database and a new JWT token is issued.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.token - The recovery token.
|
||||
* @property {string} req.body.password - The new password of the user.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the reset of the password, the updated user data (without password and avatar image), and a new JWT token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
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 this.db.resetPassword(req, res);
|
||||
const appSettings = await this.settingsService.getSettings();
|
||||
const token = this.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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a user and all associated monitors, checks, and alerts.
|
||||
*
|
||||
* @param {Object} req - The request object.
|
||||
* @param {Object} res - The response object.
|
||||
* @param {Function} next - The next middleware function.
|
||||
* @returns {Object} The response object with success status and message.
|
||||
* @throws {Error} If user validation fails or user is not found in the database.
|
||||
*/
|
||||
deleteUser = async (req, res, next) => {
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const decodedToken = jwt.decode(token);
|
||||
const { email } = decodedToken;
|
||||
|
||||
// Check if the user exists
|
||||
const user = await this.db.getUserByEmail(email);
|
||||
// 1. Find all the monitors associated with the team ID if superadmin
|
||||
|
||||
const result = await this.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 this.jobQueue.deleteJob(monitor);
|
||||
await this.db.deleteChecks(monitor._id);
|
||||
await this.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
||||
await this.db.deleteNotificationsByMonitorId(monitor._id);
|
||||
})
|
||||
));
|
||||
|
||||
// 3. Delete team
|
||||
await this.db.deleteTeam(user.teamId);
|
||||
// 4. Delete all other team members
|
||||
await this.db.deleteAllOtherUsers();
|
||||
// 5. Delete each monitor
|
||||
await this.db.deleteMonitorsByUserId(user._id);
|
||||
}
|
||||
// 6. Delete the user by id
|
||||
await this.db.deleteUser(user._id);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.AUTH_DELETE_USER,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteUserController"));
|
||||
}
|
||||
};
|
||||
|
||||
getAllUsers = async (req, res, next) => {
|
||||
try {
|
||||
const allUsers = await this.db.getAllUsers(req, res);
|
||||
res.status(200).json({ success: true, msg: "Got all users", data: allUsers });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAllUsersController"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default AuthController;
|
||||
|
||||
@@ -16,139 +16,138 @@ import { handleValidationError, handleError } from "./controllerUtils.js";
|
||||
|
||||
const SERVICE_NAME = "checkController";
|
||||
|
||||
const createCheck = async (req, res, next) => {
|
||||
try {
|
||||
await createCheckParamValidation.validateAsync(req.params);
|
||||
await createCheckBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
class CheckController {
|
||||
constructor(db, settingsService) {
|
||||
this.db = db;
|
||||
this.settingsService = settingsService;
|
||||
}
|
||||
|
||||
try {
|
||||
const checkData = { ...req.body };
|
||||
const check = await req.db.createCheck(checkData);
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: successMessages.CHECK_CREATE, data: check });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "createCheck"));
|
||||
}
|
||||
};
|
||||
createCheck = async (req, res, next) => {
|
||||
try {
|
||||
await createCheckParamValidation.validateAsync(req.params);
|
||||
await createCheckBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
const getChecks = async (req, res, next) => {
|
||||
try {
|
||||
await getChecksParamValidation.validateAsync(req.params);
|
||||
await getChecksQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const checkData = { ...req.body };
|
||||
const check = await this.db.createCheck(checkData);
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: successMessages.CHECK_CREATE, data: check });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "createCheck"));
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const checks = await req.db.getChecks(req);
|
||||
const checksCount = await req.db.getChecksCount(req);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_GET,
|
||||
data: { checksCount, checks },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getChecks"));
|
||||
}
|
||||
};
|
||||
getChecks = async (req, res, next) => {
|
||||
try {
|
||||
await getChecksParamValidation.validateAsync(req.params);
|
||||
await getChecksQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
const getTeamChecks = async (req, res, next) => {
|
||||
try {
|
||||
await getTeamChecksParamValidation.validateAsync(req.params);
|
||||
await getTeamChecksQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const checkData = await req.db.getTeamChecks(req);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_GET,
|
||||
data: checkData,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getTeamChecks"));
|
||||
}
|
||||
};
|
||||
try {
|
||||
const checks = await this.db.getChecks(req);
|
||||
const checksCount = await this.db.getChecksCount(req);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_GET,
|
||||
data: { checksCount, checks },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getChecks"));
|
||||
}
|
||||
};
|
||||
|
||||
const deleteChecks = async (req, res, next) => {
|
||||
try {
|
||||
await deleteChecksParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
getTeamChecks = async (req, res, next) => {
|
||||
try {
|
||||
await getTeamChecksParamValidation.validateAsync(req.params);
|
||||
await getTeamChecksQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const checkData = await this.db.getTeamChecks(req);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_GET,
|
||||
data: checkData,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getTeamChecks"));
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const deletedCount = await req.db.deleteChecks(req.params.monitorId);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_DELETE,
|
||||
data: { deletedCount },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteChecks"));
|
||||
}
|
||||
};
|
||||
deleteChecks = async (req, res, next) => {
|
||||
try {
|
||||
await deleteChecksParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
const deleteChecksByTeamId = async (req, res, next) => {
|
||||
try {
|
||||
await deleteChecksByTeamIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const deletedCount = await this.db.deleteChecks(req.params.monitorId);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_DELETE,
|
||||
data: { deletedCount },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteChecks"));
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const deletedCount = await req.db.deleteChecksByTeamId(req.params.teamId);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_DELETE,
|
||||
data: { deletedCount },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteChecksByTeamId"));
|
||||
}
|
||||
};
|
||||
deleteChecksByTeamId = async (req, res, next) => {
|
||||
try {
|
||||
await deleteChecksByTeamIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
const updateChecksTTL = async (req, res, next) => {
|
||||
const SECONDS_PER_DAY = 86400;
|
||||
try {
|
||||
const deletedCount = await this.db.deleteChecksByTeamId(req.params.teamId);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_DELETE,
|
||||
data: { deletedCount },
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteChecksByTeamId"));
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
await updateChecksTTLBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
updateChecksTTL = async (req, res, next) => {
|
||||
const SECONDS_PER_DAY = 86400;
|
||||
|
||||
try {
|
||||
// Get user's teamId
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = req.settingsService.getSettings();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const ttl = parseInt(req.body.ttl, 10) * SECONDS_PER_DAY;
|
||||
await req.db.updateChecksTTL(teamId, ttl);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_UPDATE_TTL,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "updateTTL"));
|
||||
}
|
||||
};
|
||||
try {
|
||||
await updateChecksTTLBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
export {
|
||||
createCheck,
|
||||
getChecks,
|
||||
getTeamChecks,
|
||||
deleteChecks,
|
||||
deleteChecksByTeamId,
|
||||
updateChecksTTL,
|
||||
};
|
||||
try {
|
||||
// Get user's teamId
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = this.settingsService.getSettings();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const ttl = parseInt(req.body.ttl, 10) * SECONDS_PER_DAY;
|
||||
await this.db.updateChecksTTL(teamId, ttl);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.CHECK_UPDATE_TTL,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "updateTTL"));
|
||||
}
|
||||
};
|
||||
}
|
||||
export default CheckController;
|
||||
|
||||
@@ -4,83 +4,90 @@ import {
|
||||
inviteVerificationBodyValidation,
|
||||
} 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";
|
||||
|
||||
/**
|
||||
* Issues an invitation to a new user. Only admins can invite new users. An invitation token is created and sent via email.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.headers - The headers of the request.
|
||||
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.email - The email of the user to be invited.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the sending of the invitation, and the invitation token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const issueInvitation = async (req, res, next) => {
|
||||
try {
|
||||
// Only admins can invite
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { role, firstname, teamId } = jwt.decode(token);
|
||||
req.body.teamId = teamId;
|
||||
class InviteController {
|
||||
constructor(db, settingsService, emailService) {
|
||||
this.db = db;
|
||||
this.settingsService = settingsService;
|
||||
this.emailService = emailService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues an invitation to a new user. Only admins can invite new users. An invitation token is created and sent via email.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.headers - The headers of the request.
|
||||
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {string} req.body.email - The email of the user to be invited.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the sending of the invitation, and the invitation token.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
issueInvitation = async (req, res, next) => {
|
||||
try {
|
||||
await inviteRoleValidation.validateAsync({ roles: role });
|
||||
await inviteBodyValidation.validateAsync(req.body);
|
||||
// Only admins can invite
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { role, firstname, teamId } = jwt.decode(token);
|
||||
req.body.teamId = teamId;
|
||||
try {
|
||||
await inviteRoleValidation.validateAsync({ roles: role });
|
||||
await inviteBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
const inviteToken = await this.db.requestInviteToken({ ...req.body });
|
||||
const { clientHost } = this.settingsService.getSettings();
|
||||
this.emailService
|
||||
.buildAndSendEmail(
|
||||
"employeeActivationTemplate",
|
||||
{
|
||||
name: firstname,
|
||||
link: `${clientHost}/register/${inviteToken.token}`,
|
||||
},
|
||||
req.body.email,
|
||||
"Welcome to Uptime Monitor"
|
||||
)
|
||||
.catch((error) => {
|
||||
logger.error({
|
||||
message: error.message,
|
||||
service: SERVICE_NAME,
|
||||
method: "issueInvitation",
|
||||
stack: error.stack,
|
||||
});
|
||||
});
|
||||
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: "Invite sent", data: inviteToken });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "inviteController"));
|
||||
}
|
||||
};
|
||||
|
||||
inviteVerifyController = async (req, res, next) => {
|
||||
try {
|
||||
await inviteVerificationBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
const inviteToken = await req.db.requestInviteToken({ ...req.body });
|
||||
const { clientHost } = req.settingsService.getSettings();
|
||||
req.emailService
|
||||
.buildAndSendEmail(
|
||||
"employeeActivationTemplate",
|
||||
{
|
||||
name: firstname,
|
||||
link: `${clientHost}/register/${inviteToken.token}`,
|
||||
},
|
||||
req.body.email,
|
||||
"Welcome to Uptime Monitor"
|
||||
)
|
||||
.catch((error) => {
|
||||
logger.error({
|
||||
message: error.message,
|
||||
service: SERVICE_NAME,
|
||||
method: "issueInvitation",
|
||||
stack: error.stack,
|
||||
});
|
||||
});
|
||||
try {
|
||||
const invite = await this.db.getInviteToken(req.body.token);
|
||||
res.status(200).json({ status: "success", msg: "Invite verified", data: invite });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "inviteVerifyController"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return res.status(200).json({ success: true, msg: "Invite sent", data: inviteToken });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "inviteController"));
|
||||
}
|
||||
};
|
||||
|
||||
const inviteVerifyController = async (req, res, next) => {
|
||||
try {
|
||||
await inviteVerificationBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const invite = await req.db.getInviteToken(req.body.token);
|
||||
res.status(200).json({ status: "success", msg: "Invite verified", data: invite });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "inviteVerifyController"));
|
||||
}
|
||||
};
|
||||
|
||||
export { issueInvitation, inviteVerifyController };
|
||||
export default InviteController;
|
||||
|
||||
@@ -11,157 +11,156 @@ 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) => {
|
||||
try {
|
||||
await createMaintenanceWindowBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
class MaintenanceWindowController {
|
||||
constructor(db, settingsService) {
|
||||
this.db = db;
|
||||
this.settingsService = settingsService;
|
||||
}
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = req.settingsService.getSettings();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const monitorIds = req.body.monitors;
|
||||
const dbTransactions = monitorIds.map((monitorId) => {
|
||||
return req.db.createMaintenanceWindow({
|
||||
teamId,
|
||||
monitorId,
|
||||
name: req.body.name,
|
||||
active: req.body.active ? req.body.active : true,
|
||||
repeat: req.body.repeat,
|
||||
start: req.body.start,
|
||||
end: req.body.end,
|
||||
|
||||
createMaintenanceWindows = async (req, res, next) => {
|
||||
try {
|
||||
await createMaintenanceWindowBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = this.settingsService.getSettings();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const monitorIds = req.body.monitors;
|
||||
const dbTransactions = monitorIds.map((monitorId) => {
|
||||
return this.db.createMaintenanceWindow({
|
||||
teamId,
|
||||
monitorId,
|
||||
name: req.body.name,
|
||||
active: req.body.active ? req.body.active : true,
|
||||
repeat: req.body.repeat,
|
||||
start: req.body.start,
|
||||
end: req.body.end,
|
||||
});
|
||||
});
|
||||
});
|
||||
await Promise.all(dbTransactions);
|
||||
return res.status(201).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_CREATE,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "createMaintenanceWindow"));
|
||||
}
|
||||
};
|
||||
await Promise.all(dbTransactions);
|
||||
return res.status(201).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_CREATE,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "createMaintenanceWindow"));
|
||||
}
|
||||
};
|
||||
|
||||
const getMaintenanceWindowById = async (req, res, next) => {
|
||||
try {
|
||||
await getMaintenanceWindowByIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const maintenanceWindow = await req.db.getMaintenanceWindowById(req.params.id);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_ID,
|
||||
data: maintenanceWindow,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMaintenanceWindowById"));
|
||||
}
|
||||
};
|
||||
getMaintenanceWindowById = async (req, res, next) => {
|
||||
try {
|
||||
await getMaintenanceWindowByIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const maintenanceWindow = await this.db.getMaintenanceWindowById(req.params.id);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_ID,
|
||||
data: maintenanceWindow,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMaintenanceWindowById"));
|
||||
}
|
||||
};
|
||||
|
||||
const getMaintenanceWindowsByTeamId = async (req, res, next) => {
|
||||
try {
|
||||
await getMaintenanceWindowsByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
getMaintenanceWindowsByTeamId = async (req, res, next) => {
|
||||
try {
|
||||
await getMaintenanceWindowsByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = req.settingsService.getSettings();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const maintenanceWindows = await req.db.getMaintenanceWindowsByTeamId(
|
||||
teamId,
|
||||
req.query
|
||||
);
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = this.settingsService.getSettings();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const maintenanceWindows = await this.db.getMaintenanceWindowsByTeamId(
|
||||
teamId,
|
||||
req.query
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_TEAM,
|
||||
data: maintenanceWindows,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMaintenanceWindowsByUserId"));
|
||||
}
|
||||
};
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_TEAM,
|
||||
data: maintenanceWindows,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMaintenanceWindowsByUserId"));
|
||||
}
|
||||
};
|
||||
|
||||
const getMaintenanceWindowsByMonitorId = async (req, res, next) => {
|
||||
try {
|
||||
await getMaintenanceWindowsByMonitorIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
getMaintenanceWindowsByMonitorId = async (req, res, next) => {
|
||||
try {
|
||||
await getMaintenanceWindowsByMonitorIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const maintenanceWindows = await req.db.getMaintenanceWindowsByMonitorId(
|
||||
req.params.monitorId
|
||||
);
|
||||
try {
|
||||
const maintenanceWindows = await this.db.getMaintenanceWindowsByMonitorId(
|
||||
req.params.monitorId
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_USER,
|
||||
data: maintenanceWindows,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMaintenanceWindowsByMonitorId"));
|
||||
}
|
||||
};
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_GET_BY_USER,
|
||||
data: maintenanceWindows,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMaintenanceWindowsByMonitorId"));
|
||||
}
|
||||
};
|
||||
|
||||
const deleteMaintenanceWindow = async (req, res, next) => {
|
||||
try {
|
||||
await deleteMaintenanceWindowByIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await req.db.deleteMaintenanceWindowById(req.params.id);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_DELETE,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteMaintenanceWindow"));
|
||||
}
|
||||
};
|
||||
deleteMaintenanceWindow = async (req, res, next) => {
|
||||
try {
|
||||
await deleteMaintenanceWindowByIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.db.deleteMaintenanceWindowById(req.params.id);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_DELETE,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteMaintenanceWindow"));
|
||||
}
|
||||
};
|
||||
|
||||
const editMaintenanceWindow = async (req, res, next) => {
|
||||
try {
|
||||
await editMaintenanceWindowByIdParamValidation.validateAsync(req.params);
|
||||
await editMaintenanceByIdWindowBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const editedMaintenanceWindow = await req.db.editMaintenanceWindowById(
|
||||
req.params.id,
|
||||
req.body
|
||||
);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_EDIT,
|
||||
data: editedMaintenanceWindow,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "editMaintenanceWindow"));
|
||||
}
|
||||
};
|
||||
editMaintenanceWindow = async (req, res, next) => {
|
||||
try {
|
||||
await editMaintenanceWindowByIdParamValidation.validateAsync(req.params);
|
||||
await editMaintenanceByIdWindowBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const editedMaintenanceWindow = await this.db.editMaintenanceWindowById(
|
||||
req.params.id,
|
||||
req.body
|
||||
);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MAINTENANCE_WINDOW_EDIT,
|
||||
data: editedMaintenanceWindow,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "editMaintenanceWindow"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
createMaintenanceWindows,
|
||||
getMaintenanceWindowById,
|
||||
getMaintenanceWindowsByTeamId,
|
||||
getMaintenanceWindowsByMonitorId,
|
||||
deleteMaintenanceWindow,
|
||||
editMaintenanceWindow,
|
||||
};
|
||||
export default MaintenanceWindowController;
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
getCertificateParamValidation,
|
||||
} from "../validation/joi.js";
|
||||
import sslChecker from "ssl-checker";
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
import { successMessages } from "../utils/messages.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { getTokenFromHeaders } from "../utils/utils.js";
|
||||
import logger from "../utils/logger.js";
|
||||
@@ -23,510 +23,503 @@ import axios from "axios";
|
||||
|
||||
const SERVICE_NAME = "monitorController";
|
||||
|
||||
/**
|
||||
* Returns all monitors
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @param {function} next
|
||||
* @returns {Promise<Express.Response>}
|
||||
* @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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all monitors with uptime stats for 1,7,30, and 90 days
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @param {function} next
|
||||
* @returns {Promise<Express.Response>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
const getAllMonitorsWithUptimeStats = async (req, res, next) => {
|
||||
try {
|
||||
const monitors = await req.db.getAllMonitorsWithUptimeStats();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_ALL,
|
||||
data: monitors,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAllMonitorsWithUptimeStats"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns monitor stats for monitor with matching ID
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @param {function} next
|
||||
* @returns {Promise<Express.Response>}
|
||||
* @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;
|
||||
class MonitorController {
|
||||
constructor(db, settingsService, jobQueue) {
|
||||
this.db = db;
|
||||
this.settingsService = settingsService;
|
||||
this.jobQueue = jobQueue;
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Returns all monitors
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @param {function} next
|
||||
* @returns {Promise<Express.Response>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
getAllMonitors = async (req, res, next) => {
|
||||
try {
|
||||
const monitors = await this.db.getAllMonitors();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_ALL,
|
||||
data: monitors,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAllMonitors"));
|
||||
}
|
||||
};
|
||||
|
||||
const getMonitorCertificate = async (req, res, next, fetchMonitorCertificate) => {
|
||||
try {
|
||||
await getCertificateParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
}
|
||||
/**
|
||||
* Returns all monitors with uptime stats for 1,7,30, and 90 days
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @param {function} next
|
||||
* @returns {Promise<Express.Response>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
getAllMonitorsWithUptimeStats = async (req, res, next) => {
|
||||
try {
|
||||
const monitors = await this.db.getAllMonitorsWithUptimeStats();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_ALL,
|
||||
data: monitors,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAllMonitorsWithUptimeStats"));
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const { monitorId } = req.params;
|
||||
const monitor = await req.db.getMonitorById(monitorId);
|
||||
const certificate = await fetchMonitorCertificate(sslChecker, monitor);
|
||||
/**
|
||||
* Returns monitor stats for monitor with matching ID
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @param {function} next
|
||||
* @returns {Promise<Express.Response>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
getMonitorStatsById = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorStatsByIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorStatsByIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_CERTIFICATE,
|
||||
data: {
|
||||
certificateDate: new Date(certificate.validTo),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorCertificate"));
|
||||
}
|
||||
};
|
||||
try {
|
||||
const monitorStats = await this.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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves a monitor by its ID.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.monitorId - The ID of the monitor to be retrieved.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message, and the retrieved monitor data.
|
||||
* @throws {Error} If there is an error during the process, especially if the monitor is not found (404) or if there is a validation error (422).
|
||||
*/
|
||||
const getMonitorById = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorByIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
getMonitorCertificate = async (req, res, next, fetchMonitorCertificate) => {
|
||||
try {
|
||||
await getCertificateParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
}
|
||||
|
||||
try {
|
||||
const monitor = await req.db.getMonitorById(req.params.monitorId);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_ID,
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorById"));
|
||||
}
|
||||
};
|
||||
try {
|
||||
const { monitorId } = req.params;
|
||||
const monitor = await this.db.getMonitorById(monitorId);
|
||||
const certificate = await fetchMonitorCertificate(sslChecker, monitor);
|
||||
|
||||
/**
|
||||
* Retrieves all monitors and a summary for a team based on the team ID.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.teamId - The ID of the team.
|
||||
* @property {Object} req.query - The query parameters of the request.
|
||||
* @property {string} req.query.type - The type of the request.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message, and the data containing the monitors and summary for the team.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const getMonitorsAndSummaryByTeamId = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorsAndSummaryByTeamIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorsAndSummaryByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_CERTIFICATE,
|
||||
data: {
|
||||
certificateDate: new Date(certificate.validTo),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorCertificate"));
|
||||
}
|
||||
};
|
||||
|
||||
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"));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Retrieves a monitor by its ID.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.monitorId - The ID of the monitor to be retrieved.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message, and the retrieved monitor data.
|
||||
* @throws {Error} If there is an error during the process, especially if the monitor is not found (404) or if there is a validation error (422).
|
||||
*/
|
||||
getMonitorById = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorByIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all monitors associated with a team by the team's ID.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.teamId - The ID of the team.
|
||||
* @property {Object} req.query - The query parameters of the request.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message, and the data containing the monitors for the team.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const getMonitorsByTeamId = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorsByTeamIdValidation.validateAsync(req.params);
|
||||
await getMonitorsByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const monitor = await this.db.getMonitorById(req.params.monitorId);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_ID,
|
||||
data: monitor,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMonitorById"));
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Retrieves all monitors and a summary for a team based on the team ID.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.teamId - The ID of the team.
|
||||
* @property {Object} req.query - The query parameters of the request.
|
||||
* @property {string} req.query.type - The type of the request.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message, and the data containing the monitors and summary for the team.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
getMonitorsAndSummaryByTeamId = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorsAndSummaryByTeamIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorsAndSummaryByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new monitor and adds it to the job queue.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {Array} req.body.notifications - The notifications associated with the monitor.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the creation of the monitor, and the created monitor data.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const createMonitor = async (req, res, next) => {
|
||||
try {
|
||||
await createMonitorBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const { teamId } = req.params;
|
||||
const { type } = req.query;
|
||||
const monitorsSummary = await this.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 notifications = req.body.notifications;
|
||||
const monitor = await req.db.createMonitor(req, res);
|
||||
/**
|
||||
* Retrieves all monitors associated with a team by the team's ID.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.teamId - The ID of the team.
|
||||
* @property {Object} req.query - The query parameters of the request.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message, and the data containing the monitors for the team.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
getMonitorsByTeamId = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorsByTeamIdValidation.validateAsync(req.params);
|
||||
await getMonitorsByTeamIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
if (notifications && notifications.length > 0) {
|
||||
monitor.notifications = await Promise.all(
|
||||
notifications.map(async (notification) => {
|
||||
notification.monitorId = monitor._id;
|
||||
return await req.db.createNotification(notification);
|
||||
try {
|
||||
const teamId = req.params.teamId;
|
||||
const monitors = await this.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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new monitor and adds it to the job queue.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {Array} req.body.notifications - The notifications associated with the monitor.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the creation of the monitor, and the created monitor data.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
createMonitor = async (req, res, next) => {
|
||||
try {
|
||||
await createMonitorBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const notifications = req.body.notifications;
|
||||
const monitor = await this.db.createMonitor(req, res);
|
||||
|
||||
if (notifications && notifications.length > 0) {
|
||||
monitor.notifications = await Promise.all(
|
||||
notifications.map(async (notification) => {
|
||||
notification.monitorId = monitor._id;
|
||||
return await this.db.createNotification(notification);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
await monitor.save();
|
||||
// Add monitor to job queue
|
||||
this.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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the endpoint can be resolved
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.query - The query parameters of the request.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message, and the resolution result.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
checkEndpointResolution = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorURLByQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { monitorURL } = req.query;
|
||||
const parsedUrl = new URL(monitorURL);
|
||||
const response = await axios.get(parsedUrl, {
|
||||
timeout: 5000,
|
||||
validateStatus: () => true,
|
||||
});
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
code: response.status,
|
||||
statusText: response.statusText,
|
||||
msg: `URL resolved successfully`,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "checkEndpointResolution"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a monitor by its ID and also deletes associated checks, alerts, and notifications.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.monitorId - The ID of the monitor to be deleted.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status and a message indicating the deletion of the monitor.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422) or an error in deleting associated records.
|
||||
*/
|
||||
deleteMonitor = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const monitor = await this.db.deleteMonitor(req, res, next);
|
||||
// Delete associated checks,alerts,and notifications
|
||||
try {
|
||||
await this.jobQueue.deleteJob(monitor);
|
||||
await this.db.deleteChecks(monitor._id);
|
||||
await this.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
||||
await this.db.deleteNotificationsByMonitorId(monitor._id);
|
||||
await this.db.deleteHardwareChecksByMonitorId(monitor._id);
|
||||
} catch (error) {
|
||||
logger.error({
|
||||
message: `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
||||
service: SERVICE_NAME,
|
||||
method: "deleteMonitor",
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
return res.status(200).json({ success: true, msg: successMessages.MONITOR_DELETE });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteMonitor"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes all monitors associated with a team.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.headers - The headers of the request.
|
||||
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next
|
||||
* @returns {Object} The response object with a success status and a message indicating the number of deleted monitors.
|
||||
* @throws {Error} If there is an error during the deletion process.
|
||||
*/
|
||||
deleteAllMonitors = async (req, res, next) => {
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = this.settingsService.getSettings();
|
||||
const { teamId } = jwt.verify(token, jwtSecret);
|
||||
const { monitors, deletedCount } = await this.db.deleteAllMonitors(teamId);
|
||||
await Promise.all(
|
||||
monitors.map(async (monitor) => {
|
||||
try {
|
||||
await this.jobQueue.deleteJob(monitor);
|
||||
await this.db.deleteChecks(monitor._id);
|
||||
await this.db.deletePageSpeedChecksByMonitorId(monitor._id);
|
||||
await this.db.deleteNotificationsByMonitorId(monitor._id);
|
||||
} catch (error) {
|
||||
logger.error({
|
||||
message: `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
||||
service: SERVICE_NAME,
|
||||
method: "deleteAllMonitors",
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the endpoint can be resolved
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.query - The query parameters of the request.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message, and the resolution result.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const checkEndpointResolution = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorURLByQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { monitorURL } = req.query;
|
||||
const parsedUrl = new URL(monitorURL);
|
||||
const response = await axios.get(parsedUrl, {
|
||||
timeout: 5000,
|
||||
validateStatus: () => true,
|
||||
});
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
code: response.status,
|
||||
statusText: response.statusText,
|
||||
msg: `URL resolved successfully`,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "checkEndpointResolution"));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a monitor by its ID and also deletes associated checks, alerts, and notifications.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.monitorId - The ID of the monitor to be deleted.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status and a message indicating the deletion of the monitor.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422) or an error in deleting associated records.
|
||||
*/
|
||||
const deleteMonitor = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
} 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);
|
||||
await req.db.deleteHardwareChecksByMonitorId(monitor._id);
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: `Deleted ${deletedCount} monitors` });
|
||||
} catch (error) {
|
||||
logger.error({
|
||||
message: `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
||||
service: SERVICE_NAME,
|
||||
method: "deleteMonitor",
|
||||
stack: error.stack,
|
||||
});
|
||||
next(handleError(error, SERVICE_NAME, "deleteAllMonitors"));
|
||||
}
|
||||
return res.status(200).json({ success: true, msg: successMessages.MONITOR_DELETE });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteMonitor"));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes all monitors associated with a team.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.headers - The headers of the request.
|
||||
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next
|
||||
* @returns {Object} The response object with a success status and a message indicating the number of deleted monitors.
|
||||
* @throws {Error} If there is an error during the deletion process.
|
||||
*/
|
||||
const deleteAllMonitors = async (req, res, next) => {
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = req.settingsService.getSettings();
|
||||
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({
|
||||
message: `Error deleting associated records for monitor ${monitor._id} with name ${monitor.name}`,
|
||||
service: SERVICE_NAME,
|
||||
method: "deleteAllMonitors",
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: `Deleted ${deletedCount} monitors` });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "deleteAllMonitors"));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Edits a monitor by its ID, updates its notifications, and updates its job in the job queue.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.monitorId - The ID of the monitor to be edited.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {Array} req.body.notifications - The notifications to be associated with the monitor.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the editing of the monitor, and the edited monitor data.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
editMonitor = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
await editMonitorBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits a monitor by its ID, updates its notifications, and updates its job in the job queue.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.monitorId - The ID of the monitor to be edited.
|
||||
* @property {Object} req.body - The body of the request.
|
||||
* @property {Array} req.body.notifications - The notifications to be associated with the monitor.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the editing of the monitor, and the edited monitor data.
|
||||
* @throws {Error} If there is an error during the process, especially if there is a validation error (422).
|
||||
*/
|
||||
const editMonitor = async (req, res, next) => {
|
||||
try {
|
||||
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 this.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 this.db.editMonitor(monitorId, req.body);
|
||||
|
||||
const editedMonitor = await req.db.editMonitor(monitorId, req.body);
|
||||
await this.db.deleteNotificationsByMonitorId(editedMonitor._id);
|
||||
|
||||
await req.db.deleteNotificationsByMonitorId(editedMonitor._id);
|
||||
await Promise.all(
|
||||
notifications &&
|
||||
notifications.map(async (notification) => {
|
||||
notification.monitorId = editedMonitor._id;
|
||||
await this.db.createNotification(notification);
|
||||
})
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
notifications &&
|
||||
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 this.jobQueue.deleteJob(monitorBeforeEdit);
|
||||
// Add the new job back to the queue
|
||||
await this.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"));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Pauses or resumes a monitor based on its current state.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.monitorId - The ID of the monitor to be paused or resumed.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the new state of the monitor, and the updated monitor data.
|
||||
* @throws {Error} If there is an error during the process.
|
||||
*/
|
||||
pauseMonitor = async (req, res, next) => {
|
||||
try {
|
||||
await pauseMonitorParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses or resumes a monitor based on its current state.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.params - The parameters of the request.
|
||||
* @property {string} req.params.monitorId - The ID of the monitor to be paused or resumed.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the new state of the monitor, and the updated monitor data.
|
||||
* @throws {Error} If there is an error during the process.
|
||||
*/
|
||||
const pauseMonitor = async (req, res, next) => {
|
||||
try {
|
||||
await pauseMonitorParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
}
|
||||
try {
|
||||
const monitor = await this.db.getMonitorById(req.params.monitorId);
|
||||
monitor.isActive === true
|
||||
? await this.jobQueue.deleteJob(monitor)
|
||||
: await this.jobQueue.addJob(monitor._id, monitor);
|
||||
|
||||
try {
|
||||
const monitor = await req.db.getMonitorById(req.params.monitorId);
|
||||
monitor.isActive === true
|
||||
? await req.jobQueue.deleteJob(monitor)
|
||||
: 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"));
|
||||
}
|
||||
};
|
||||
|
||||
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"));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Adds demo monitors for a team.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.headers - The headers of the request.
|
||||
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the addition of demo monitors, and the number of demo monitors added.
|
||||
* @throws {Error} If there is an error during the process.
|
||||
*/
|
||||
addDemoMonitors = async (req, res, next) => {
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
const { jwtSecret } = this.settingsService.getSettings();
|
||||
const { _id, teamId } = jwt.verify(token, jwtSecret);
|
||||
const demoMonitors = await this.db.addDemoMonitors(_id, teamId);
|
||||
await Promise.all(
|
||||
demoMonitors.map((monitor) => this.jobQueue.addJob(monitor._id, monitor))
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds demo monitors for a team.
|
||||
* @async
|
||||
* @param {Object} req - The Express request object.
|
||||
* @property {Object} req.headers - The headers of the request.
|
||||
* @property {string} req.headers.authorization - The authorization header containing the JWT token.
|
||||
* @param {Object} res - The Express response object.
|
||||
* @param {function} next - The next middleware function.
|
||||
* @returns {Object} The response object with a success status, a message indicating the addition of demo monitors, and the number of demo monitors added.
|
||||
* @throws {Error} If there is an error during the process.
|
||||
*/
|
||||
const addDemoMonitors = async (req, res, next) => {
|
||||
try {
|
||||
const token = getTokenFromHeaders(req.headers);
|
||||
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"));
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
getAllMonitors,
|
||||
getAllMonitorsWithUptimeStats,
|
||||
getMonitorStatsById,
|
||||
getMonitorCertificate,
|
||||
getMonitorById,
|
||||
getMonitorsAndSummaryByTeamId,
|
||||
getMonitorsByTeamId,
|
||||
createMonitor,
|
||||
checkEndpointResolution,
|
||||
deleteMonitor,
|
||||
deleteAllMonitors,
|
||||
editMonitor,
|
||||
pauseMonitor,
|
||||
addDemoMonitors,
|
||||
};
|
||||
export default MonitorController;
|
||||
|
||||
@@ -1,57 +1,64 @@
|
||||
import { handleError } from "./controllerUtils.js";
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
import { successMessages } from "../utils/messages.js";
|
||||
|
||||
const SERVICE_NAME = "JobQueueController";
|
||||
|
||||
const getMetrics = async (req, res, next) => {
|
||||
try {
|
||||
const metrics = await req.jobQueue.getMetrics();
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.QUEUE_GET_METRICS,
|
||||
data: metrics,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMetrics"));
|
||||
return;
|
||||
class JobQueueController {
|
||||
constructor(jobQueue) {
|
||||
this.jobQueue = jobQueue;
|
||||
}
|
||||
};
|
||||
|
||||
const getJobs = async (req, res, next) => {
|
||||
try {
|
||||
const jobs = await req.jobQueue.getJobStats();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.QUEUE_GET_METRICS,
|
||||
data: jobs,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getJobs"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
getMetrics = async (req, res, next) => {
|
||||
try {
|
||||
const metrics = await this.jobQueue.getMetrics();
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.QUEUE_GET_METRICS,
|
||||
data: metrics,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getMetrics"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const addJob = async (req, res, next) => {
|
||||
try {
|
||||
await req.jobQueue.addJob(Math.random().toString(36).substring(7));
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.QUEUE_ADD_JOB,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "addJob"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
getJobs = async (req, res, next) => {
|
||||
try {
|
||||
const jobs = await this.jobQueue.getJobStats();
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.QUEUE_GET_METRICS,
|
||||
data: jobs,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getJobs"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const obliterateQueue = async (req, res, next) => {
|
||||
try {
|
||||
await req.jobQueue.obliterate();
|
||||
return res.status(200).json({ success: true, msg: successMessages.QUEUE_OBLITERATE });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "obliterateQueue"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
addJob = async (req, res, next) => {
|
||||
try {
|
||||
await this.jobQueue.addJob(Math.random().toString(36).substring(7));
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.QUEUE_ADD_JOB,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "addJob"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
export { getMetrics, getJobs, addJob, obliterateQueue };
|
||||
obliterateQueue = async (req, res, next) => {
|
||||
try {
|
||||
await this.jobQueue.obliterate();
|
||||
return res
|
||||
.status(200)
|
||||
.json({ success: true, msg: successMessages.QUEUE_OBLITERATE });
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "obliterateQueue"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
export default JobQueueController;
|
||||
|
||||
@@ -3,40 +3,47 @@ import { updateAppSettingsBodyValidation } from "../validation/joi.js";
|
||||
import { handleValidationError, handleError } from "./controllerUtils.js";
|
||||
const SERVICE_NAME = "SettingsController";
|
||||
|
||||
const getAppSettings = async (req, res, next) => {
|
||||
try {
|
||||
const settings = { ...(await req.settingsService.getSettings()) };
|
||||
delete settings.jwtSecret;
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.GET_APP_SETTINGS,
|
||||
data: settings,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAppSettings"));
|
||||
}
|
||||
};
|
||||
|
||||
const updateAppSettings = async (req, res, next) => {
|
||||
try {
|
||||
await updateAppSettingsBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
class SettingsController {
|
||||
constructor(db, settingsService) {
|
||||
this.db = db;
|
||||
this.settingsService = settingsService;
|
||||
}
|
||||
|
||||
try {
|
||||
await req.db.updateAppSettings(req.body);
|
||||
const updatedSettings = { ...(await req.settingsService.reloadSettings()) };
|
||||
delete updatedSettings.jwtSecret;
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.UPDATE_APP_SETTINGS,
|
||||
data: updatedSettings,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "updateAppSettings"));
|
||||
}
|
||||
};
|
||||
getAppSettings = async (req, res, next) => {
|
||||
try {
|
||||
const settings = { ...(await this.settingsService.getSettings()) };
|
||||
delete settings.jwtSecret;
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.GET_APP_SETTINGS,
|
||||
data: settings,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getAppSettings"));
|
||||
}
|
||||
};
|
||||
|
||||
export { getAppSettings, updateAppSettings };
|
||||
updateAppSettings = async (req, res, next) => {
|
||||
try {
|
||||
await updateAppSettingsBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.db.updateAppSettings(req.body);
|
||||
const updatedSettings = { ...(await this.settingsService.reloadSettings()) };
|
||||
delete updatedSettings.jwtSecret;
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.UPDATE_APP_SETTINGS,
|
||||
data: updatedSettings,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "updateAppSettings"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default SettingsController;
|
||||
|
||||
@@ -7,45 +7,50 @@ import { successMessages } from "../utils/messages.js";
|
||||
|
||||
const SERVICE_NAME = "statusPageController";
|
||||
|
||||
const createStatusPage = async (req, res, next) => {
|
||||
try {
|
||||
await createStatusPageBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
class StatusPageController {
|
||||
constructor(db) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
try {
|
||||
const statusPage = await req.db.createStatusPage(req.body);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.STATUS_PAGE_CREATE,
|
||||
data: statusPage,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "createStatusPage"));
|
||||
}
|
||||
};
|
||||
createStatusPage = async (req, res, next) => {
|
||||
try {
|
||||
await createStatusPageBodyValidation.validateAsync(req.body);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
const getStatusPageByUrl = async (req, res, next) => {
|
||||
try {
|
||||
await getStatusPageParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const statusPage = await this.db.createStatusPage(req.body);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.STATUS_PAGE_CREATE,
|
||||
data: statusPage,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "createStatusPage"));
|
||||
}
|
||||
};
|
||||
getStatusPageByUrl = async (req, res, next) => {
|
||||
try {
|
||||
await getStatusPageParamValidation.validateAsync(req.params);
|
||||
} catch (error) {
|
||||
next(handleValidationError(error, SERVICE_NAME));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { url } = req.params;
|
||||
const statusPage = await req.db.getStatusPageByUrl(url);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.STATUS_PAGE_BY_URL,
|
||||
data: statusPage,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getStatusPage"));
|
||||
}
|
||||
};
|
||||
try {
|
||||
const { url } = req.params;
|
||||
const statusPage = await this.db.getStatusPageByUrl(url);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
msg: successMessages.STATUS_PAGE_BY_URL,
|
||||
data: statusPage,
|
||||
});
|
||||
} catch (error) {
|
||||
next(handleError(error, SERVICE_NAME, "getStatusPage"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export { createStatusPage, getStatusPageByUrl };
|
||||
export default StatusPageController;
|
||||
|
||||
Reference in New Issue
Block a user