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, }