Dynamic Role-Based Access Control (RBAC) in Payload CMS

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();
});


Leave a comment

Your email address will not be published. Required fields are marked *