Files
mbmanager-api/middlewares/permissionMiddleware.js
2026-08-18 00:08:04 +03:30

121 lines
4.2 KiB
JavaScript

const Permission = require('../components/permission/permissionModel')
const Role = require('../components/role/roleModel')
const AppError = require('../globalErrorHandler/AppError')
const User = require('../components/user/userModel')
const ErrorLocalization = require('../globalErrorHandler/errorLocalization')
const el = new ErrorLocalization()
let checker = (arr, target) => {
if (!Array.isArray(arr)) return false
return arr.some((item) => {
const id = (item?._id || item)?.toString()
const key = item?.key
return id === target?.toString() || (key && key === target)
})
}
const requires = (...permissions) => {
return async (req, res, next) => {
try {
if (!req.user) {
return next(new AppError('NotLoggedIn', 401, {}))
}
const superAdminRoleId = process.env.SUPER_ADMIN_ROLE_ID || '66a2da5b9b989a8909948848'
// Super Admin bypass: full access to all endpoints
if (
req.user.isAdmin === true ||
req.user.role?.englishName === 'SuperAdmin' ||
req.user.role?._id?.toString() === superAdminRoleId ||
req.user.role?.toString() === superAdminRoleId
) {
return next()
}
// Retrieve role and its permissions
let role = req.user.role
if (role && (typeof role === 'string' || !role.permissions || !role.englishName)) {
role = await Role.findById(role._id || role).populate('permissions')
}
const rolePermissions = role?.permissions || []
const userExtraPermissions = req.user.extraPermissions || []
// Find target permissions from DB
const targetPerms = await Permission.find({ key: { $in: permissions } })
const targetIds = targetPerms.map((p) => p._id.toString())
const targetKeys = permissions
// Check if any required permission is present in role or user extra permissions
const hasPermission =
rolePermissions.some((rp) => {
const rpId = (rp._id || rp).toString()
const rpKey = rp.key
return targetIds.includes(rpId) || targetKeys.includes(rpKey)
}) ||
userExtraPermissions.some((up) => {
const upId = (up._id || up).toString()
const upKey = up.key
return targetIds.includes(upId) || targetKeys.includes(upKey)
})
if (!hasPermission) {
return next(new AppError('NoPermissionAccess', 403, {}))
}
next()
} catch (err) {
next(err)
}
}
}
const adminCheck = () => {
return async (req, res, next) => {
try {
const user = await User.findOne({
phoneNumber: req.body.phoneNumber,
}).populate('role')
if (!user) {
return next(new AppError('UserDoesNotExist', 403, {}))
}
const superAdminRoleId = process.env.SUPER_ADMIN_ROLE_ID || '66a2da5b9b989a8909948848'
if (
user.isAdmin === true ||
user.role?.englishName === 'SuperAdmin' ||
user.role?._id?.toString() === superAdminRoleId ||
user.role?.toString() === superAdminRoleId
) {
return next()
}
const perm = await Permission.findOne({ key: 'admindashboard' })
let rolePerm = user.role?.permissions || []
let userPerm = user.extraPermissions || []
if (!checker(rolePerm, perm?._id) && !checker(userPerm, perm?._id)) {
return next(new AppError('NoPermissionAccess', 403, {}))
}
next()
} catch (err) {
console.log(err)
err.message = el.getErrorText(err.name, err.parameters, 'persian')
res.status(500).json({
status: 'error',
message: err.message || 'An error occurred while checking permissions.',
})
}
}
}
module.exports = {
checker,
requires,
adminCheck,
}