Merge branch 'master' into feat/ping

This commit is contained in:
Alexander Holliday authored and GitHub committed 2024-06-15 20:05:14 -07:00
commit caaf604c9f
12 files changed
+216 -64

No files matched your search

+11 -9
View File
@@ -10,7 +10,7 @@ const {
editAlertBodyValidation,
deleteAlertParamValidation,
} = require("../validation/joi");
const { successMessages } = require("../utils/messages");
const SERVICE_NAME = "alerts";
/**
@@ -38,7 +38,7 @@ const createAlert = async (req, res, next) => {
const alert = await req.db.createAlert(alertData);
return res
.status(200)
.json({ success: true, msg: "Alert created", data: alert });
.json({ success: true, msg: successMessages.ALERT_CREATE, data: alert });
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -66,9 +66,11 @@ const getAlertsByUserId = async (req, res, next) => {
try {
const alerts = await req.db.getAlertsByUserId(req.params.userId);
return res
.status(200)
.json({ success: true, msg: "Got alerts", data: alerts });
return res.status(200).json({
success: true,
msg: successMessages.ALERT_GET_BY_USER,
data: alerts,
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -90,7 +92,7 @@ const getAlertsByMonitorId = async (req, res, next) => {
const alerts = await req.db.getAlertsByMonitorId(req.params.monitorId);
return res.status(200).json({
success: true,
msg: "Got alerts by Monitor",
msg: successMessages.ALERT_GET_BY_MONITOR,
data: alerts,
});
} catch (error) {
@@ -114,7 +116,7 @@ const getAlertById = async (req, res, next) => {
const alert = await req.db.getAlertById(req.params.alertId);
return res.status(200).json({
success: true,
msg: "Got Alert By alertID",
msg: successMessages.ALERT_GET_BY_ID,
data: alert,
});
} catch (error) {
@@ -141,7 +143,7 @@ const editAlert = async (req, res, next) => {
const alert = await req.db.editAlert(req.params.alertId, alertData);
return res.status(200).json({
success: true,
msg: "Edited alert",
msg: successMessages.ALERT_EDIT,
data: alert,
});
} catch (error) {
@@ -164,7 +166,7 @@ const deleteAlert = async (req, res, next) => {
const deleted = await req.db.deleteAlert(req.params.alertId);
return res.status(200).json({
success: true,
msg: "Deleted alert",
msg: successMessages.ALERT_DELETE,
data: deleted,
});
} catch (error) {
+28 -15
View File
@@ -10,6 +10,7 @@ const {
} = require("../validation/joi");
const logger = require("../utils/logger");
require("dotenv").config();
const { errorMessages, successMessages } = require("../utils/messages");
var jwt = require("jsonwebtoken");
const SERVICE_NAME = "auth";
const { sendEmail } = require("../utils/sendEmail");
@@ -49,7 +50,7 @@ const registerController = async (req, res, next) => {
// Create a new user
try {
const newUser = await req.db.insertUser(req, res);
logger.info("New user created!", {
logger.info(successMessages.AUTH_CREATE_USER, {
service: SERVICE_NAME,
userId: newUser._id,
});
@@ -64,9 +65,11 @@ const registerController = async (req, res, next) => {
"Registered."
);
return res
.status(200)
.json({ success: true, msg: "User created", data: token });
return res.status(200).json({
success: true,
msg: successMessages.AUTH_CREATE_USER,
data: token,
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -92,7 +95,7 @@ const loginController = async (req, res, next) => {
const match = await user.comparePassword(req.body.password);
if (match !== true) {
throw new Error("Incorrect password");
throw new Error(errorMessages.AUTH_INCORRECT_PASSWORD);
}
// Remove password from user object. Should this be abstracted to DB layer?
@@ -101,9 +104,11 @@ const loginController = async (req, res, next) => {
// Happy path, return token
const token = issueToken(userWithoutPassword);
return res
.status(200)
.json({ success: true, msg: "Found user", data: token });
return res.status(200).json({
success: true,
msg: successMessages.AUTH_LOGIN_USER,
data: token,
});
} catch (error) {
error.status = 500;
// Anything else should be an error
@@ -124,7 +129,7 @@ const userEditController = async (req, res, next) => {
}
if (req.params.userId !== req.user._id.toString()) {
const error = new Error("Unauthorized access");
const error = new Error(errorMessages.AUTH_UNAUTHORIZED);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
@@ -133,9 +138,11 @@ const userEditController = async (req, res, next) => {
try {
const updatedUser = await req.db.updateUser(req, res);
return res
.status(200)
.json({ success: true, msg: "User updated", data: updatedUser });
return res.status(200).json({
success: true,
msg: successMessages.AUTH_UPDATE_USER,
data: updatedUser,
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -166,7 +173,7 @@ const recoveryRequestController = async (req, res, next) => {
);
return res.status(200).json({
success: true,
msg: "Created recovery token",
msg: successMessages.AUTH_CREATE_RECOVERY_TOKEN,
});
}
// TODO Email token to user
@@ -193,7 +200,7 @@ const validateRecoveryTokenController = async (req, res, next) => {
// TODO Redirect user to reset password after validating token
return res.status(200).json({
success: true,
msg: "Token is valid",
msg: successMessages.AUTH_VERIFY_RECOVERY_TOKEN,
});
} catch (error) {
error.service = SERVICE_NAME;
@@ -216,7 +223,13 @@ const resetPasswordController = async (req, res, next) => {
try {
await newPasswordValidation.validateAsync(req.body);
user = await req.db.resetPassword(req, res);
res.status(200).json({ success: true, msg: "Password reset", data: user });
res
.status(200)
.json({
success: true,
msg: successMessages.AUTH_RESET_PASSWORD,
data: user,
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
+8 -3
View File
@@ -4,6 +4,7 @@ const {
getChecksParamValidation,
deleteChecksParamValidation,
} = require("../validation/joi");
const { successMessages } = require("../utils/messages");
const SERVICE_NAME = "check";
const createCheck = async (req, res, next) => {
@@ -23,7 +24,7 @@ const createCheck = async (req, res, next) => {
const check = await req.db.createCheck(checkData);
return res
.status(200)
.json({ success: true, msg: "Check created", data: check });
.json({ success: true, msg: successMessages.CHECK_CREATE, data: check });
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -45,7 +46,7 @@ const getChecks = async (req, res, next) => {
const checks = await req.db.getChecks(req.params.monitorId);
return res
.status(200)
.json({ success: true, msg: "Checks retrieved", data: checks });
.json({ success: true, msg: successMessages.CHECK_GET, data: checks });
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -67,7 +68,11 @@ const deleteChecks = async (req, res, next) => {
const deletedCount = await req.db.deleteChecks(req.params.monitorId);
return res
.status(200)
.json({ success: true, msg: "Checks deleted", data: { deletedCount } });
.json({
success: true,
msg: successMessages.CHECK_DELETE,
data: { deletedCount },
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
+28 -10
View File
@@ -5,6 +5,8 @@ const {
} = require("../validation/joi");
const SERVICE_NAME = "monitorController";
const { errorMessages, successMessages } = require("../utils/messages");
const { error } = require("winston");
/**
* Returns all monitors
@@ -17,7 +19,11 @@ const SERVICE_NAME = "monitorController";
const getAllMonitors = async (req, res, next) => {
try {
const monitors = await req.db.getAllMonitors();
return res.json({ success: true, msg: "Monitors found", data: monitors });
return res.json({
success: true,
msg: successMessages.MONITOR_GET_ALL,
data: monitors,
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -45,12 +51,16 @@ const getMonitorById = async (req, res, next) => {
try {
const monitor = await req.db.getMonitorById(req, res);
if (!monitor) {
const error = new Error("Monitor not found");
const error = new Error(errorMessages.MONITOR_GET_BY_ID);
error.status = 404;
throw error;
}
return res.json({ success: true, msg: "Monitor found", data: monitor });
return res.json({
success: true,
msg: successMessages.MONTIOR_GET_BY_ID,
data: monitor,
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -78,14 +88,14 @@ const getMonitorsByUserId = async (req, res, next) => {
const monitors = await req.db.getMonitorsByUserId(req, res);
if (monitors && monitors.length === 0) {
const err = new Error("No monitors found");
const err = new Error(errorMessages.MONITOR_GET_BY_USER_ID);
err.status = 404;
throw err;
}
return res.json({
success: true,
msg: `Monitors for user ${userId} found`,
msg: successMessages.MONITOR_GET_BY_USER_ID(userId),
data: monitors,
});
} catch (error) {
@@ -118,9 +128,11 @@ const createMonitor = async (req, res, next) => {
const monitor = await req.db.createMonitor(req, res);
// Add monitor to job queue
req.jobQueue.addJob(monitor._id, monitor);
return res
.status(201)
.json({ success: true, msg: "Monitor created", data: monitor });
return res.status(201).json({
success: true,
msg: successMessages.MONITOR_CREATE,
data: monitor,
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -157,7 +169,9 @@ const deleteMonitor = async (req, res, next) => {
* when it is deleted so there is no orphaned data
* We also need to make sure to stop all running services for this monitor
*/
return res.status(200).json({ success: true, msg: "Monitor deleted" });
return res
.status(200)
.json({ success: true, msg: successMessages.MONITOR_DELETE });
} catch (error) {
error.service = SERVICE_NAME;
next(error);
@@ -188,7 +202,11 @@ const editMonitor = async (req, res, next) => {
const editedMonitor = await req.db.editMonitor(req, res);
return res
.status(200)
.json({ success: true, msg: "Monitor edited", data: editedMonitor });
.json({
success: true,
msg: successMessages.MONITOR_EDIT,
data: editedMonitor,
});
} catch (error) {
error.service = SERVICE_NAME;
next(error);
+12 -9
View File
@@ -6,7 +6,8 @@ const Alert = require("../models/Alert");
const RecoveryToken = require("../models/RecoveryToken");
const crypto = require("crypto");
const DUPLICATE_KEY_CODE = 11000; // MongoDB error code for duplicate key
const { errorMessages, successMessages } = require("../utils/messages");
const { error } = require("console");
const connect = async () => {
try {
await mongoose.connect(process.env.DB_CONNECTION_STRING);
@@ -36,7 +37,7 @@ const insertUser = async (req, res) => {
return await UserModel.findOne({ _id: newUser._id }).select("-password"); // .select() doesn't work with create, need to save then find
} catch (error) {
if (error.code === DUPLICATE_KEY_CODE) {
throw new Error("Email already exists");
throw new Error(errorMessages.DB_USER_EXISTS);
}
throw error;
}
@@ -61,7 +62,7 @@ const getUserByEmail = async (req, res) => {
if (user) {
return user;
} else {
throw new Error("User not found");
throw new Error(errorMessages.DB_USER_NOT_FOUND);
}
} catch (error) {
throw error;
@@ -125,7 +126,7 @@ const validateRecoveryToken = async (req, res) => {
if (recoveryToken !== null) {
return recoveryToken;
} else {
throw new Error("Token not found");
throw new Error(errorMessages.DB_TOKEN_NOT_FOUND);
}
} catch (error) {
throw error;
@@ -142,7 +143,7 @@ const resetPassword = async (req, res) => {
const match = await user.comparePassword(newPassword);
if (match === true) {
throw new Error("New password must be different from old password");
throw new Error(errorMessages.DB_RESET_PASSWORD_BAD_MATCH);
}
if (user !== null) {
@@ -155,7 +156,7 @@ const resetPassword = async (req, res) => {
}).select("-password");
return userWithoutPassword;
} else {
throw new Error("User not found");
throw new Error(errorMessages.DB_USER_NOT_FOUND);
}
} catch (error) {
throw error;
@@ -249,7 +250,7 @@ const deleteMonitor = async (req, res) => {
try {
const monitor = await Monitor.findByIdAndDelete(monitorId);
if (!monitor) {
throw new Error(`Monitor with id ${monitorId} not found`);
throw new Error(errorMessages.DB_FIND_MONTIOR_BY_ID(monitorId));
}
return monitor;
} catch (error) {
@@ -338,7 +339,7 @@ const deleteChecks = async (monitorId) => {
if (result.deletedCount > 0) {
return result.deletedCount;
} else {
throw new Error(`No checks found for monitor with id ${monitorId}`);
throw new Error(errorMessages.DB_DELETE_CHECKS(monitorId));
}
} catch (error) {
throw error;
@@ -458,7 +459,9 @@ const deleteAlert = async (alertId) => {
const result = await Alert.findByIdAndDelete(alertId);
if (result) {
return result;
} else throw new Error(`Alert with id ${alertId} not found`);
} else {
throw new Error(errorMessages.DB_DELETE_ALERT(alertId));
}
} catch (error) {
throw error;
}
+3 -2
View File
@@ -1,9 +1,10 @@
const logger = require("../utils/logger");
const { errorMessages } = require("../utils/messages");
const handleErrors = (error, req, res, next) => {
const status = error.status || 500;
const message = error.message || "Something went wrong";
const service = error.service || "Unknown service";
const message = error.message || errorMessages.FRIENDLY_ERROR;
const service = error.service || errorMessages.UNKNOWN_SERVICE;
logger.error(error.message, { service: service });
res.status(status).json({ success: false, msg: message });
};
+8 -4
View File
@@ -2,7 +2,7 @@ const jwt = require("jsonwebtoken");
const logger = require("../utils/logger");
const SERVICE_NAME = "verifyJWT";
const TOKEN_PREFIX = "Bearer ";
const { errorMessages } = require("../utils/messages");
/**
* Verifies the JWT token
* @function
@@ -15,7 +15,7 @@ const verifyJWT = (req, res, next) => {
const token = req.headers["authorization"];
// Make sure a token is provided
if (!token) {
const error = new Error("No token provided");
const error = new Error(error.errorMessages.NO_AUTH_TOKEN);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
@@ -27,8 +27,12 @@ const verifyJWT = (req, res, next) => {
// Verify the token's authenticity
jwt.verify(parsedToken, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
logger.error("Invalid token", { service: SERVICE_NAME });
return res.status(401).json({ success: false, msg: "Invalid token" });
logger.error(errorMessages.INVALID_AUTH_TOKEN, {
service: SERVICE_NAME,
});
return res
.status(401)
.json({ success: false, msg: errorMessages.INVALID_AUTH_TOKEN });
}
//Add the user to the request object for use in the route
req.user = decoded;
+4 -3
View File
@@ -1,5 +1,6 @@
const logger = require("../utils/logger");
const SERVICE_NAME = "verifyOwnership";
const { errorMessages } = require("../utils/messages");
const verifyOwnership = (Model, paramName) => {
return async (req, res, next) => {
@@ -9,10 +10,10 @@ const verifyOwnership = (Model, paramName) => {
const doc = await Model.findById(documentId);
//If the document is not found, return a 404 error
if (!doc) {
logger.error("Document not found", {
logger.error(errorMessages.VERIFY_OWNER_NOT_FOUND, {
service: SERVICE_NAME,
});
const error = new Error("Document not found");
const error = new Error(errorMessages.VERIFY_OWNER_NOT_FOUND);
error.status = 404;
throw error;
}
@@ -20,7 +21,7 @@ const verifyOwnership = (Model, paramName) => {
// If the userID does not match the document's userID, return a 403 error
if (userId.toString() !== doc.userId.toString()) {
console.log("boom");
const error = new Error("Unauthorized access");
const error = new Error(errorMessages.VERIFY_OWNER_UNAUTHORIZED);
error.status = 403;
throw error;
}
+10 -3
View File
@@ -6,6 +6,7 @@ const connection = {
};
const JOBS_PER_WORKER = 5;
const logger = require("../utils/logger");
const { errorMessages, successMessages } = require("../utils/messages");
const SERVICE_NAME = "JobQueue";
const axios = require("axios");
const ping = require("ping");
@@ -155,7 +156,9 @@ class JobQueue {
await worker.close();
} catch (error) {
// Catch the error instead of throwing it
console.error("Error closing worker", error);
logger.error(errorMessages.JOB_QUEUE_WORKER_CLOSE, {
service: SERVICE_NAME,
});
}
}
return true;
@@ -214,12 +217,12 @@ class JobQueue {
every: monitor.interval,
});
if (deleted) {
logger.info("Job removed from queue", {
logger.info(successMessages.JOB_QUEUE_DELETE_JOB, {
service: SERVICE_NAME,
jobId: monitor.id,
});
} else {
logger.error("Job not found in queue", {
logger.error(errorMessages.JOB_QUEUE_DELETE_JOB, {
service: SERVICE_NAME,
jobId: monitor.id,
});
@@ -241,8 +244,12 @@ class JobQueue {
}
console.log(jobs);
await this.queue.obliterate();
logger.info(successMessages.JOB_QUEUE_OBLITERATE, {
service: SERVICE_NAME,
});
return true;
} catch (error) {
logger.error(errorMessages.JOB_QUEUE_OBLITERATE);
throw error;
}
}
+81
View File
@@ -0,0 +1,81 @@
const errorMessages = {
// General Errors:
FRIENDLY_ERROR: "Something went wrong...",
UNKNOWN_ERROR: "An unknown error occurred",
// Auth Controller
UNAUTHORIZED: "Unauthorized access",
//Error handling middleware
UNKNOWN_SERVICE: "Unknown service",
NO_AUTH_TOKEN: "No auth token provided",
INVALID_AUTH_TOKEN: "Invalid auth token",
//Onwership Middleware
VERIFY_OWNER_NOT_FOUND: "Document not found",
VERIFY_OWNER_UNAUTHORIZED: "Unauthorized access",
//DB Errors
DB_USER_EXISTS: "User already exists",
DB_USER_NOT_FOUND: "User not found",
DB_TOKEN_NOT_FOUND: "Token not found",
DB_RESET_PASSWORD_BAD_MATCH:
"New password must be different from old password",
DB_FIND_MONTIOR_BY_ID: (monitorId) =>
`Monitor with id ${monitorId} not found`,
DB_DELETE_CHECKS: (monitorId) =>
`No checks found for monitor with id ${monitorId}`,
DB_DELETE_ALERT: (alertId) => `Alert with id ${alertId} not found`,
//Auth errors
AUTH_INCORRECT_PASSWORD: "Incorrect password",
AUTH_UNAUTHORIZED: "Unauthorized access",
// Monitor Errros
MONITOR_GET_BY_ID: "Monitor not found",
MONITOR_GET_BY_USER_ID: "No monitors found for user",
// Job Queue Errors
JOB_QUEUE_WORKER_CLOSE: "Error closing worker",
JOB_QUEUE_DELETE_JOB: "Job not found in queue",
JOB_QUEUE_OBLITERATE: "Error obliterating queue",
};
const successMessages = {
//Alert Controller
ALERT_CREATE: "Alert created successfully",
ALERT_GET_BY_USER: "Got alerts successfully",
ALERT_GET_BY_MONITOR: "Got alerts by Monitor successfully",
ALERT_GET_BY_ID: "Got alert by Id successfully",
ALERT_EDIT: "Alert edited successfully",
ALERT_DELETE: "Alert deleted successfully",
// Auth Controller
AUTH_CREATE_USER: "User created successfully",
AUTH_LOGIN_USER: "User logged in successfully",
AUTH_UPDATE_USER: "User updated successfully",
AUTH_CREATE_RECOVERY_TOKEN: "Recovery token created successfully",
AUTH_VERIFY_RECOVERY_TOKEN: "Recovery token verified successfully",
AUTH_RESET_PASSWORD: "Password reset successfully",
// Check Controller
CHECK_CREATE: "Check created successfully",
CHECK_GET: "Got checks successfully",
CHECK_DELETE: "Checks deleted successfully",
//Monitor Controller
MONITOR_GET_ALL: "Got all monitors successfully",
MONTIOR_GET_BY_ID: "Got monitor by Id successfully",
MONITOR_GET_BY_USER_ID: (userId) => `Got monitor for ${userId} successfully"`,
MONITOR_CREATE: "Monitor created successfully",
MONITOR_DELETE: "Monitor deleted successfully",
MONITOR_EDIT: "Monitor edited successfully",
//Job Queue
JOB_QUEUE_DELETE_JOB: "Job removed successfully",
JOB_QUEUE_OBLITERATE: "Queue OBLITERATED!!!",
};
module.exports = {
errorMessages,
successMessages,
};