overview: Payload CMS includes advanced Role-Based Access Control (RBAC) features that allow developers to assign dynamic permissions to users or groups. This ensures that sensitive data and functionality are accessible only to authorized personnel, making it ideal for managing complex systems or multi-user environments.
Use Case: Multi-Tiered User Permissions in an E-commerce Admin Panel
In an e-commerce platform, different user roles (e.g., Admin, Manager, Editor) need tailored access. Here’s how you can implement this feature:
Step 1: Define Roles and Permissions
Create roles such as Admin, Manager, and Editor, each with specific access rules.
module.exports = {
slug: "users",
access: {
admin: ({ req }) => req.user.role === "admin",
read: ({ req }) => ["admin", "manager"].includes(req.user.role),
create: ({ req }) => req.user.role === "admin",
update: ({ req }) => req.user.role === "admin",
delete: ({ req }) => req.user.role === "admin",
},
fields: [
{
name: "role",
type: "select",
options: [
{ value: "admin", label: "Admin" },
{ value: "manager", label: "Manager" },
{ value: "editor", label: "Editor" },
],
},
],
};
Step 2: Restrict Access at the Collection Level
Limit access to collections based on user roles. For example, only Admins can manage products, while Managers and Editors can view them.
module.exports = {
slug: "products",
access: {
read: ({ req }) => ["admin", "manager", "editor"].includes(req.user.role),
create: ({ req }) => req.user.role === "admin",
update: ({ req }) => ["admin", "manager"].includes(req.user.role),
delete: ({ req }) => req.user.role === "admin",
},
fields: [
{
name: "name",
type: "text",
},
{
name: "price",
type: "number",
},
{
name: "description",
type: "textarea",
},
],
};
Step 3: Implement Conditional UI Elements
Modify the admin panel UI to show or hide actions based on the user’s role.
import { useEffect, useState } from "react";
function AdminPanel({ user }) {
const [products, setProducts] = useState([]);
useEffect(() => {
fetch("/api/products")
.then((res) => res.json())
.then(setProducts);
}, []);
return (
<div>
<h1>Admin Panel</h1>
{user.role === "admin" && <button>Add Product</button>}
<ul>
{products.map((product) => (
<li key={product.id}>
{product.name} - ${product.price}
{(user.role === "admin" || user.role === "manager") && (
<button>Edit</button>
)}
{user.role === "admin" && <button>Delete</button>}
</li>
))}
</ul>
</div>
);
}
Step 4: Secure API Endpoints
Ensure that APIs respect the defined access rules.
app.use("/api/products", async (req, res, next) => {
const user = req.user;
if (!["admin", "manager"].includes(user.role)) {
return res.status(403).json({ message: "Access denied" });
}
next();
});