From 5dbd8378e28d3dedaeba6dd3e49d9b200e9855bf Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Wed, 25 Sep 2024 15:12:07 +0800 Subject: [PATCH] require invite token to register except for initial registration --- Client/src/Pages/Auth/Register/Register.jsx | 5 ++-- Client/src/Validation/validation.js | 1 + Server/controllers/authController.js | 5 ++++ Server/db/mongo/MongoDB.js | 2 ++ Server/db/mongo/modules/inviteModule.js | 30 ++++++++++++++++++++- Server/validation/joi.js | 2 ++ 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Client/src/Pages/Auth/Register/Register.jsx b/Client/src/Pages/Auth/Register/Register.jsx index 7f5ed6390..eb331304c 100644 --- a/Client/src/Pages/Auth/Register/Register.jsx +++ b/Client/src/Pages/Auth/Register/Register.jsx @@ -596,6 +596,7 @@ const Register = ({ isSuperAdmin }) => { let registerForm = { ...form, role: isSuperAdmin ? ["superadmin"] : form.role, + inviteToken: token ? token : "", }; let error = validateForm(registerForm, { context: { password: form.password }, @@ -608,8 +609,8 @@ const Register = ({ isSuperAdmin }) => { delete registerForm.confirm; const action = await dispatch(register(registerForm)); if (action.payload.success) { - const token = action.payload.data; - localStorage.setItem("token", token); + const authToken = action.payload.data; + localStorage.setItem("token", authToken); navigate("/"); createToast({ body: "Welcome! Your account was created successfully.", diff --git a/Client/src/Validation/validation.js b/Client/src/Validation/validation.js index 3d11482d1..25ad79923 100644 --- a/Client/src/Validation/validation.js +++ b/Client/src/Validation/validation.js @@ -77,6 +77,7 @@ const credentials = joi.object({ }), role: joi.array(), teamId: joi.string().allow("").optional(), + inviteToken: joi.string().allow(""), }); const monitorValidation = joi.object({ diff --git a/Server/controllers/authController.js b/Server/controllers/authController.js index f39ffb019..6357d25de 100644 --- a/Server/controllers/authController.js +++ b/Server/controllers/authController.js @@ -51,6 +51,11 @@ const registerController = async (req, res, next) => { } // Create a new user try { + const { inviteToken } = req.body; + const superAdminExists = await req.db.checkSuperadmin(req, res); + if (superAdminExists) { + await req.db.getInviteTokenAndDelete(inviteToken); + } const newUser = await req.db.insertUser({ ...req.body }, req.file); logger.info(successMessages.AUTH_CREATE_USER, { service: SERVICE_NAME, diff --git a/Server/db/mongo/MongoDB.js b/Server/db/mongo/MongoDB.js index c5fcff08c..0cc2d5b57 100644 --- a/Server/db/mongo/MongoDB.js +++ b/Server/db/mongo/MongoDB.js @@ -47,6 +47,7 @@ const { const { requestInviteToken, getInviteToken, + getInviteTokenAndDelete, } = require("./modules/inviteModule"); //**************************************** @@ -128,6 +129,7 @@ module.exports = { logoutUser, requestInviteToken, getInviteToken, + getInviteTokenAndDelete, requestRecoveryToken, validateRecoveryToken, resetPassword, diff --git a/Server/db/mongo/modules/inviteModule.js b/Server/db/mongo/modules/inviteModule.js index 6e810ec8b..1b7d698cd 100644 --- a/Server/db/mongo/modules/inviteModule.js +++ b/Server/db/mongo/modules/inviteModule.js @@ -32,7 +32,7 @@ const requestInviteToken = async (userData) => { }; /** - * Retrieves and deletes an invite token. + * Retrieves an invite token * * This function searches for an invite token in the database and deletes it. * If the invite token is not found, it throws an error. @@ -42,6 +42,33 @@ const requestInviteToken = async (userData) => { * @throws {Error} If the invite token is not found or there is another error. */ const getInviteToken = async (token) => { + console.log(token); + try { + const invite = await InviteToken.findOne({ + token, + }); + if (invite === null) { + throw new Error(errorMessages.AUTH_INVITE_NOT_FOUND); + } + return invite; + } catch (error) { + error.service = SERVICE_NAME; + error.method = "getInviteToken"; + throw error; + } +}; + +/** + * Retrieves and deletes an invite token + * + * This function searches for an invite token in the database and deletes it. + * If the invite token is not found, it throws an error. + * + * @param {string} token - The invite token to search for. + * @returns {Promise} The invite token data. + * @throws {Error} If the invite token is not found or there is another error. + */ +const getInviteTokenAndDelete = async (token) => { try { const invite = await InviteToken.findOneAndDelete({ token, @@ -60,4 +87,5 @@ const getInviteToken = async (token) => { module.exports = { requestInviteToken, getInviteToken, + getInviteTokenAndDelete, }; diff --git a/Server/validation/joi.js b/Server/validation/joi.js index f61432595..0a83b6e74 100644 --- a/Server/validation/joi.js +++ b/Server/validation/joi.js @@ -74,6 +74,7 @@ const registrationBodyValidation = joi.object({ .min(1) .required(), teamId: joi.string().allow("").required(), + inviteToken: joi.string().allow("").required(), }); const editUserParamValidation = joi.object({ @@ -137,6 +138,7 @@ const inviteBodyValidation = joi.object({ "string.email": "Must be a valid email address", }), role: joi.array().required(), + teamId: joi.string().required(), }); const inviteVerifciationBodyValidation = joi.object({