Merge pull request #257 from MuhammadKhalilzadeh/backend-completion

Backend completion
This commit is contained in:
Alexander Holliday
2024-07-06 22:19:37 -07:00
committed by GitHub
6 changed files with 257 additions and 370 deletions

View File

@@ -7,6 +7,7 @@ const {
recoveryValidation,
recoveryTokenValidation,
newPasswordValidation,
deleteUserParamValidation
} = require("../validation/joi");
const logger = require("../utils/logger");
require("dotenv").config();
@@ -261,6 +262,86 @@ const resetPasswordController = async (req, res, next) => {
next(error);
}
};
/**
* 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 deleteUserController = async (req, res, next) => {
try {
const token = req.headers.authorization.split(' ')[1];
const decodedToken = jwt.decode(token)
const { _id, email } = decodedToken;
const decodedTokenCastedAsRequest = {
params: {
userId: _id
},
body: {
email
}
}
// Validate user
await deleteUserParamValidation.validateAsync(decodedTokenCastedAsRequest.body);
// Check if the user exists
const user = await req.db.getUserByEmail(decodedTokenCastedAsRequest);
if (!user) {
throw new Error(errorMessages.DB_USER_NOT_FOUND);
}
// 1. Find all the monitors associated with the user id
const monitors = await req.db.getMonitorsByUserId(decodedTokenCastedAsRequest);
if (monitors) {
// 2. Delete jobs associated with each monitor
for (const monitor of monitors) {
await req.jobQueue.deleteJob(monitor);
}
// 3. Delete all checks associated with each monitor
for (const monitor of monitors) {
await req.db.deleteChecks(monitor._id);
}
// 4. Delete all alerts associated with each monitor
for (const monitor of monitors) {
await req.db.deleteAlertByMonitorId(monitor._id);
}
// 5. Delete each monitor
await req.db.deleteMonitorsByUserId(user._id);
// 6. Delete the user by id
await req.db.deleteUser(decodedTokenCastedAsRequest);
return res.status(200).json({
success: true,
msg: successMessages.AUTH_DELETE_USER,
});
} else {
return res.status(404).json({
success: false,
msg: errorMessages.MONITOR_GET_BY_USER_ID,
});
}
} catch (error) {
error.service = SERVICE_NAME;
next(error);
}
};
module.exports = {
registerController,
loginController,
@@ -269,4 +350,5 @@ module.exports = {
recoveryRequestController,
validateRecoveryTokenController,
resetPasswordController,
deleteUserController,
};

View File

@@ -115,6 +115,28 @@ const updateUser = async (req, res) => {
}
};
/**
* Delete a user by ID
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<UserModel>}
* @throws {Error}
*/
const deleteUser = async (req, res) => {
const userId = req.params.userId;
try {
const deletedUser = await UserModel.findByIdAndDelete(userId);
if (!deletedUser) {
throw new Error(errorMessages.DB_USER_NOT_FOUND);
}
return deletedUser;
} catch (error) {
throw error;
}
};
/**
* Request a recovery token
* @async
@@ -319,6 +341,21 @@ const deleteAllMonitors = async (req, res) => {
}
};
/**
* Delete all monitors associated with a user ID
* @async
* @param {string} userId - The ID of the user whose monitors are to be deleted.
* @returns {Promise} A promise that resolves when the operation is complete.
*/
const deleteMonitorsByUserId = async (userId) => {
try {
const result = await Monitor.deleteMany({ userId: userId });
return result;
} catch (error) {
throw error;
}
};
/**
* Edit a monitor by ID
* @async
@@ -520,6 +557,13 @@ const deleteAlert = async (alertId) => {
}
};
/**
* Deletes alerts by monitor ID.
*
* @param {string} monitorId - The ID of the monitor.
* @returns {Promise} A promise that resolves to the result of the delete operation.
* @throws {Error} If an error occurs while deleting the alerts.
*/
const deleteAlertByMonitorId = async (monitorId) => {
try {
const result = await Alert.deleteMany({ monitorId });
@@ -534,6 +578,7 @@ module.exports = {
insertUser,
getUserByEmail,
updateUser,
deleteUser,
requestRecoveryToken,
validateRecoveryToken,
resetPassword,
@@ -555,4 +600,5 @@ module.exports = {
editAlert,
deleteAlert,
deleteAlertByMonitorId,
deleteMonitorsByUserId
};

489
Server/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,9 @@
const router = require("express").Router();
const { verifyJWT } = require("../middleware/verifyJWT");
const { verifyOwnership } = require("../middleware/verifyOwnership");
const multer = require("multer");
const upload = multer();
const User = require("../models/user");
const {
registerController,
@@ -11,6 +13,7 @@ const {
validateRecoveryTokenController,
resetPasswordController,
checkAdminController,
deleteUserController
} = require("../controllers/authController");
//Auth routes
@@ -23,6 +26,7 @@ router.post(
userEditController
);
router.get("/users/admin", checkAdminController);
router.delete("/user/:userId", verifyJWT, verifyOwnership(User, "userId") , deleteUserController);
//Recovery routes
router.post("/recovery/request", recoveryRequestController);

View File

@@ -57,6 +57,7 @@ const successMessages = {
AUTH_VERIFY_RECOVERY_TOKEN: "Recovery token verified successfully",
AUTH_RESET_PASSWORD: "Password reset successfully",
AUTH_ADMIN_CHECK: "Admin check completed successfully",
AUTH_DELETE_USER: "User deleted successfully",
// Check Controller
CHECK_CREATE: "Check created successfully",

View File

@@ -46,6 +46,10 @@ const newPasswordValidation = joi.object({
confirm: joi.string(),
});
const deleteUserParamValidation = joi.object({
email: joi.string().email().required(),
});
//****************************************
// Monitors
//****************************************
@@ -161,4 +165,5 @@ module.exports = {
createCheckBodyValidation,
getChecksParamValidation,
deleteChecksParamValidation,
deleteUserParamValidation
};