100 lines
2.2 KiB
JavaScript
100 lines
2.2 KiB
JavaScript
/**
|
|
* Copyright (c) 2026 Niolla
|
|
* All rights reserved.
|
|
*
|
|
* This source code is proprietary and confidential.
|
|
* Unauthorized copying, modification, distribution, or use
|
|
* of this file, via any medium, is strictly prohibited.
|
|
*/
|
|
|
|
// app/middleware/permission.middleware.js
|
|
|
|
const hasPermission = (userPermissions, requiredPermission) => {
|
|
return userPermissions.some(p => {
|
|
if (p === requiredPermission) return true;
|
|
|
|
// wildcard support
|
|
if (p.endsWith(".*")) {
|
|
const prefix = p.slice(0, -2);
|
|
return requiredPermission.startsWith(prefix);
|
|
}
|
|
|
|
return false;
|
|
});
|
|
};
|
|
|
|
const methodToAction = {
|
|
GET: "view",
|
|
POST: "create",
|
|
PUT: "update",
|
|
PATCH: "update",
|
|
DELETE: "delete"
|
|
};
|
|
|
|
const checkPermission = (baseOrFull, options = {}) => {
|
|
return (req, res, next) => {
|
|
if (!req.user) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: "Unauthorized"
|
|
});
|
|
}
|
|
|
|
// admin bypass
|
|
if (req.user.accountType === "admin") {
|
|
return next();
|
|
}
|
|
|
|
if (typeof baseOrFull !== "string") {
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: "Permission must be a string"
|
|
});
|
|
}
|
|
|
|
let requiredPermission;
|
|
|
|
if (options.custom) {
|
|
requiredPermission = baseOrFull;
|
|
} else {
|
|
const action = methodToAction[req.method];
|
|
|
|
if (!action) {
|
|
return res.status(500).json({
|
|
success: false,
|
|
message: "Unknown HTTP method"
|
|
});
|
|
}
|
|
|
|
requiredPermission = `${baseOrFull}.${action}`;
|
|
}
|
|
|
|
const userPermissions = req.user.permissions || [];
|
|
|
|
const hasPermission =
|
|
userPermissions.includes(requiredPermission) ||
|
|
userPermissions.includes(`${baseOrFull}.*`);
|
|
|
|
if (!hasPermission) {
|
|
return res.status(403).json({
|
|
success: false,
|
|
message: `Forbidden - Missing ${requiredPermission}`
|
|
});
|
|
}
|
|
|
|
next();
|
|
};
|
|
};
|
|
|
|
const authorizedAccountType = (allowedTypes) => {
|
|
return (req, res, next) => {
|
|
if (!req.user || !allowedTypes.includes(req.user.accountType)) {
|
|
return res
|
|
.status(403)
|
|
.json({ success: false, message: "Forbidden" });
|
|
}
|
|
next();
|
|
}
|
|
}
|
|
|
|
module.exports = {authorizedAccountType, checkPermission}; |