From 8e6cd0de7170a935ede40061df847c661a6cafe3 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 22 Jul 2024 11:49:22 -0700 Subject: [PATCH 1/2] Added verifyAdmin middleware. Implemented getAllUsers route --- Server/controllers/authController.js | 13 +++++++ Server/db/MongoDB.js | 12 ++++++ Server/middleware/verifyAdmin.js | 57 ++++++++++++++++++++++++++++ Server/routes/authRoute.js | 3 ++ Server/utils/messages.js | 1 + 5 files changed, 86 insertions(+) create mode 100644 Server/middleware/verifyAdmin.js diff --git a/Server/controllers/authController.js b/Server/controllers/authController.js index 53fc9c384..28126c0a2 100644 --- a/Server/controllers/authController.js +++ b/Server/controllers/authController.js @@ -428,6 +428,18 @@ const deleteUserController = async (req, res, next) => { } }; +const getAllUsersController = async (req, res) => { + try { + const allUsers = await req.db.getAllUsers(req, res); + res + .status(200) + .json({ success: true, msg: "Got all users", data: allUsers }); + } catch (error) { + error.service = SERVICE_NAME; + next(error); + } +}; + module.exports = { registerController, loginController, @@ -438,4 +450,5 @@ module.exports = { validateRecoveryTokenController, resetPasswordController, deleteUserController, + getAllUsersController, }; diff --git a/Server/db/MongoDB.js b/Server/db/MongoDB.js index a59822f98..52dc59084 100644 --- a/Server/db/MongoDB.js +++ b/Server/db/MongoDB.js @@ -159,6 +159,17 @@ const deleteUser = async (req, res) => { } }; +const getAllUsers = async (req, res) => { + try { + const users = await UserModel.find() + .select("-password") + .select("-profileImage"); + return users; + } catch (error) { + throw error; + } +}; + const requestInviteToken = async (req, res) => { try { await InviteToken.deleteMany({ email: req.body.email }); @@ -629,6 +640,7 @@ module.exports = { getUserByEmail, updateUser, deleteUser, + getAllUsers, requestInviteToken, requestRecoveryToken, validateRecoveryToken, diff --git a/Server/middleware/verifyAdmin.js b/Server/middleware/verifyAdmin.js new file mode 100644 index 000000000..7ef123451 --- /dev/null +++ b/Server/middleware/verifyAdmin.js @@ -0,0 +1,57 @@ +const jwt = require("jsonwebtoken"); +const logger = require("../utils/logger"); +const SERVICE_NAME = "verifyAdmin"; +const TOKEN_PREFIX = "Bearer "; +const { errorMessages } = require("../utils/messages"); +/** + * Verifies the JWT token + * @function + * @param {express.Request} req + * @param {express.Response} res + * @param {express.NextFunction} next + * @returns {express.Response} + */ +const verifyAdmin = (req, res, next) => { + const token = req.headers["authorization"]; + // Make sure a token is provided + if (!token) { + const error = new Error(errorMessages.NO_AUTH_TOKEN); + error.status = 401; + error.service = SERVICE_NAME; + next(error); + return; + } + // Make sure it is properly formatted + if (!token.startsWith(TOKEN_PREFIX)) { + const error = new Error(errorMessages.INVALID_AUTH_TOKEN); // Instantiate a new Error object for improperly formatted token + error.status = 400; + error.service = SERVICE_NAME; + next(error); + return; + } + + const parsedToken = token.slice(TOKEN_PREFIX.length, token.length); + // verify admin role is present + jwt.verify(parsedToken, process.env.JWT_SECRET, (err, decoded) => { + if (err) { + logger.error(errorMessages.INVALID_AUTH_TOKEN, { + service: SERVICE_NAME, + }); + return res + .status(401) + .json({ success: false, msg: errorMessages.INVALID_AUTH_TOKEN }); + } + + if (decoded.role.includes("admin") === false) { + logger.error(errorMessages.INVALID_AUTH_TOKEN, { + service: SERVICE_NAME, + }); + return res + .status(401) + .json({ success: false, msg: errorMessages.UNAUTHORIZED }); + } + next(); + }); +}; + +module.exports = { verifyAdmin }; diff --git a/Server/routes/authRoute.js b/Server/routes/authRoute.js index 219032e26..02a1a67dd 100644 --- a/Server/routes/authRoute.js +++ b/Server/routes/authRoute.js @@ -1,5 +1,6 @@ const router = require("express").Router(); const { verifyJWT } = require("../middleware/verifyJWT"); +const { verifyAdmin } = require("../middleware/verifyAdmin"); const { verifyOwnership } = require("../middleware/verifyOwnership"); const multer = require("multer"); const upload = multer(); @@ -13,6 +14,7 @@ const { validateRecoveryTokenController, resetPasswordController, checkAdminController, + getAllUsersController, deleteUserController, inviteController, } = require("../controllers/authController"); @@ -27,6 +29,7 @@ router.post( userEditController ); router.get("/users/admin", checkAdminController); +router.get("/users", verifyJWT, verifyAdmin, getAllUsersController); router.delete( "/user/:userId", verifyJWT, diff --git a/Server/utils/messages.js b/Server/utils/messages.js index 787adc8f6..9ef5c6938 100644 --- a/Server/utils/messages.js +++ b/Server/utils/messages.js @@ -2,6 +2,7 @@ const errorMessages = { // General Errors: FRIENDLY_ERROR: "Something went wrong...", UNKNOWN_ERROR: "An unknown error occurred", + // Auth Controller UNAUTHORIZED: "Unauthorized access", AUTH_ADMIN_EXISTS: "Admin already exists", From d8947d090e81b9cc203922570a521f31e7c29387 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 22 Jul 2024 11:56:16 -0700 Subject: [PATCH 2/2] Added docs --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/README.md b/README.md index 16d5232c9..eae2d9e8c 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ You can see the designs [here](https://www.figma.com/design/RPSfaw66HjzSwzntKcgD - POST [/api/v1/auth/register](#post-register) - POST [/api/v1/auth/login](#post-login) - POST [/api/v1/auth/user/{userId}](#post-auth-user-edit-id) + - GET [/api/v1/auth/users](#get-all-users-id) - POST [/api/v1/auth/recovery/request](#post-auth-recovery-request-id) - POST [/api/v1/auth/recovery/validate](#post-auth-recovery-validate-id) - POST [/api/v1/auth/recovery/reset](#post-auth-recovery-reset-id) @@ -453,6 +454,55 @@ curl --request POST \ +
+GET/api/v1/auth/users + +###### Method/Headers + +> | Method/Headers | Value | +> | -------------- | ----- | +> | Method | GET | + +###### Response Payload + +> | Type | Notes | +> | ------------- | ------------------------------------- | +> | `Array` | Returns an array containing all users | + +##### Sample CURL request + +``` +curl --request GET \ + --url http://localhost:5000/api/v1/auth/users \ + --header 'Authorization: \ + --header 'User-Agent: insomnia/2023.5.8' +``` + +##### Sample Resonse + +```json +{ + "success": true, + "msg": "Got all users", + "data": [ + { + "_id": "669e90072d5663d25808bc7b", + "firstName": "Alex", + "lastName": "Holliday", + "email": "test@test.com", + "isActive": true, + "isVerified": false, + "role": ["admin"], + "createdAt": "2024-07-22T16:59:51.695Z", + "updatedAt": "2024-07-22T16:59:51.695Z", + "__v": 0 + } + ] +} +``` + +
+
POST/api/v1/auth/recovery/request