diff --git a/src/config/auth.js b/src/config/auth.js new file mode 100644 index 0000000..ec146ed --- /dev/null +++ b/src/config/auth.js @@ -0,0 +1,53 @@ +const jwt = require("jsonwebtoken"); +const { JWT_SECRET } = require("./env"); +const User = require("../models/User"); +const constants = require("./constants"); + +const authenticate = async (token) => { + const decodedToken = jwt.verify(token, JWT_SECRET); + if (decodedToken) { + return await User.findById(decodedToken.id) + .populate({ path: "roles", populate: "permissions" }) + .populate("permissions"); + } +}; + +const authorize = async ( + user, + requiredRoles = [], + requiredPermissions = [] +) => { + const userRoles = user.roles.map((_) => _._id); + const userPermissions = [ + ...user.permissions.map((_) => _._id), + ...userRoles.map((_) => _.permissions).flat(), + ]; + + return ( + user != undefined && + requiredRoles.every((_) => userRoles.includes(_)) && + requiredPermissions.every((_) => userPermissions.includes(_)) + ); +}; + +module.exports = { + AuthenticateMiddleware: async (req, res, next) => { + try { + const token = req.headers.authorization || ""; + if (token) { + const user = authenticate(token); + res.locals.user = user; + next(); + } + } catch (error) { + res + .status(401) + .send({ + success: false, + error: constants.AUTHENTICATION_FAILURE_ERROR_MESSAGE, + }); + } + }, + + AuthorizeUser: authorize, +}; diff --git a/src/config/authenticator.js b/src/config/authenticator.js deleted file mode 100644 index e77515a..0000000 --- a/src/config/authenticator.js +++ /dev/null @@ -1,25 +0,0 @@ -const jwt = require("jsonwebtoken"); -const { JWT_SECRET } = require("./env"); -const User = require("./../models/User"); - -const authenticate = async (token) => { - const decodedToken = jwt.verify(token, JWT_SECRET); - if (decodedToken) { - return await User.findById(decodedToken.id); - } -}; - -module.exports = { - AuthenticateMiddleware: async (req, res, next) => { - try { - const token = req.headers.authorization || ""; - if (token) { - const user = authenticate(token); - res.locals.user = user; - next(); - } - } catch (error) { - res.status(401).send({ success: false, error: "Authentication Failed!" }); - } - }, -}; diff --git a/src/config/constants.js b/src/config/constants.js index 13fdf47..7373070 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -40,10 +40,22 @@ const CustomAttributeTypes = [ "Enumerable", ]; +const AUTHENTICATION_FAILURE_ERROR_MESSAGE = + "Authentication Failed!"; +const AUTHORIZATION_FAILURE_ERROR_MESSAGE = + "User not permitted due to lack of access!"; + module.exports = { UserActions, InventoryScopes, WarehouseScopes, InventoryTypes, CustomAttributeTypes, + SUPER_ADMIN_ROLE: "super-admin", + COMPANY_ADMIN_ROLE: "company-admin", + WAREHOUSE_ADMIN_ROLE: "warehouse-admin", + ZONE_ADMIN_ROLE: "zone-admin", + AREA_ADMIN_ROLE: "area-admin", + AUTHENTICATION_FAILURE_ERROR_MESSAGE, + AUTHORIZATION_FAILURE_ERROR_MESSAGE, }; diff --git a/src/controller/index.js b/src/controller/index.js index 89d95b4..6d2d094 100644 --- a/src/controller/index.js +++ b/src/controller/index.js @@ -2,7 +2,7 @@ const router = require("express").Router(); const userRouter = require("./user.router"); const userRoleRouter = require("./userRole.router"); const userPermissionRouter = require("./userPermission.router"); -const { AuthenticateMiddleware } = require("../config/authenticator"); +const { AuthenticateMiddleware } = require("../config/auth"); router.use("/user", userRouter); router.use("/user-role", AuthenticateMiddleware, userRoleRouter); diff --git a/src/controller/user.router.js b/src/controller/user.router.js index 420395b..7c0c39d 100644 --- a/src/controller/user.router.js +++ b/src/controller/user.router.js @@ -1,17 +1,20 @@ const router = require("express").Router(); const controller = require("./user.controller"); -const { AuthenticateMiddleware } = require("../config/authenticator"); +const { AuthenticateMiddleware } = require("../config/auth"); +const { SuperAdminCheck } = require("./utils/authorize"); router.post("/register", controller.registerUser); router.post("/login", controller.loginUser); router.post( "/:id/addAccess", AuthenticateMiddleware, + SuperAdminCheck, controller.addUserAccessControl ); router.post( "/:id/removeAccess", AuthenticateMiddleware, + SuperAdminCheck, controller.removeUserAccessControl ); diff --git a/src/controller/utils/authorize.js b/src/controller/utils/authorize.js new file mode 100644 index 0000000..4c17cdc --- /dev/null +++ b/src/controller/utils/authorize.js @@ -0,0 +1,16 @@ +const UserRole = require("../../models/UserRole"); +const { AuthorizeUser } = require("../../config/auth"); +const { SUPER_ADMIN_ROLE, AUTHORIZATION_FAILURE_ERROR_MESSAGE } = require("../../config/constants"); + +module.exports = { + SuperAdminCheck: async (req, res, next) => { + const SuperAdmin = await UserRole.findOne({ name: SUPER_ADMIN_ROLE }); + if (AuthorizeUser(req.locals.user, [SuperAdmin.id])) { + next(); + } else { + res + .status(403) + .send({ success: false, error: AUTHORIZATION_FAILURE_ERROR_MESSAGE }); + } + }, +};