@zealamic/payload-plugin-rbac
v1.3.0
Published
A plugin for Payload CMS to manage authentication and authorization
Readme
@zealamic/payload-plugin-rbac
Centralized role-based access control (RBAC) for Payload CMS v3 (payload ^3.84.1). Not compatible with Payload 2.x.

Permissions live in the database (feature + action), are assigned to roles, and enforced via reusable access helpers — editable in Admin without redeploying policy code.
Row-level access (
dataScope): list collection slugs intargetCollectionsfor auto ownership field + create hook, then wiregetPermissionAccess. → COLLECTIONS — targetCollections · manual setup → UTILS
Documentation
| Guide | Read when you need to… |
| ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- |
| COLLECTIONS | Plugin collections, users augmentation, dataScope, permission matrix, field/access overrides |
| UTILS | getPermissionAccess, data-scope filters, field merge helpers |
| TRANSLATIONS | Admin labels, select options, matrix UI strings (en, vi, …) |
| CUSTOM_COMPONENTS | Custom matrix checkboxes / search input (client field component) |
Typical flow: install → register plugin with targetCollections (COLLECTIONS) → run migration → seed RBAC data (COLLECTIONS) → add getPermissionAccess on app collections (UTILS) → translate Admin UI (TRANSLATIONS).
Demos in this repo: dev/rbac.ts, dev/collections/posts.ts, dev/components/role-permission-matrix-field.tsx.
Key features
- Five RBAC collections — features, actions, permissions, roles, join table (details)
- Multi-role users — union of enabled grants across assigned roles
- Granular permissions — any
featureCode+actionCodepair (helpers) - Data scope —
own/hierarchy/all; usetargetCollectionsfor ownership field + hook, or add manually (UTILS) targetCollections— auto-add hidden ownership field + create hook on app collections (COLLECTIONS)- Auth users slug —
config.admin.user(defaultusers) for hierarchy +options.usersCollectionSlug - Permission matrix — role update UI; syncs draft →
roles-permissionson save - Reorder drawers — drag-and-drop
sortOrderfor permission features and actions on each collection list view - Custom matrix UI — optional client field component + render props (CUSTOM_COMPONENTS)
- TypeScript — typed plugin config and exported helpers/types from the main package
- i18n — plugin translations merged into Payload i18n (guide)
Installation
npm install @zealamic/payload-plugin-rbac
# or: yarn add / pnpm add @zealamic/payload-plugin-rbacQuick start
1. Register the plugin
import { payloadPluginRBAC } from "@zealamic/payload-plugin-rbac";
export default buildConfig({
plugins: [
payloadPluginRBAC({
autoModifyUsersCollection: true, // roles, isSuperAdmin, parent, default user access
targetCollections: ["posts"], // ownership field + create hook — see step 4
// collections: { ... } → https://github.com/zealamic/payload-plugin-rbac/blob/main/docs/COLLECTIONS.md
// translations: { ... } → https://github.com/zealamic/payload-plugin-rbac/blob/main/docs/TRANSLATIONS.md
// components: { rolePermissionMatrixField: "..." } → custom matrix Field (client module)
}),
],
});2. Migration
After adding the plugin (and especially after changing targetCollections), update your database schema:
yarn payload migrate:create
yarn payload migrate(npm run / pnpm equivalents work too.)
Run migrate:create when new fields are added to collections (e.g. first time you list a slug in targetCollections). Then migrate to apply pending migrations.
Bootstrap a super admin: RBAC collections are restricted to super admins by default. Set
isSuperAdmin: trueon at least one user (via seed script, Local API, or direct database update) before you can manage roles, permissions, and the permission matrix in Admin.
3. Seed RBAC data (Admin or script)
- permission-features — e.g.
posts,users(code=featureCodein access helpers); use Reorder on the list view to set row order in the matrix - permission-actions — e.g.
create,read,update,delete(main/subtypes); use Reorder to set main column and sub-action order - permissions — one row per feature + action pair (
status: active) - roles — set dataScope; open update screen, configure matrix → Save
- users — assign roles; bootstrap isSuperAdmin via seed/API
→ Full reference: COLLECTIONS
4. Protect app collections
Recommended: list slugs in targetCollections — the plugin adds a hidden ownership field (createdBy text by default) and a create hook. You only wire getPermissionAccess on the collection. Full options → COLLECTIONS — targetCollections.
// payload.config.ts
payloadPluginRBAC({
targetCollections: ["posts"],
});
// collections/posts.ts — no manual createdBy field or hook needed
import type { CollectionConfig } from "payload";
import { getPermissionAccess } from "@zealamic/payload-plugin-rbac";
export const Posts: CollectionConfig = {
slug: "posts",
access: {
read: getPermissionAccess({ featureCode: "posts", actionCode: "read", options: {} }),
create: getPermissionAccess({ featureCode: "posts", actionCode: "create" }),
update: getPermissionAccess({ featureCode: "posts", actionCode: "update", mode: "modify" }),
delete: getPermissionAccess({ featureCode: "posts", actionCode: "delete", mode: "modify" }),
},
fields: [{ name: "title", type: "text", required: true }],
};After adding or changing targetCollections, run yarn payload migrate:create then yarn payload migrate.
Manual setup (visible fields, custom layout, or full control): add ownership field + create hook yourself → UTILS — Ownership field · relationship demo: dev/collections/posts.ts
Access order: no user → deny · super admin → allow · else → matrix permission (+ scope when options / mode: "modify").
Reorder overview (features & actions)
List views for permission-features and permission-actions include a Reorder drawer to set sortOrder (hidden on edit forms). Order drives the role permission matrix: features → rows, main actions → columns, sub actions → checkbox order under each row.

| Step | Action | | ---- | ------ | | Features | Permission Features → Reorder → drag → Save order | | Actions | Permission Actions → Reorder → pick Main or Sub → drag → Save order |

API: POST /api/permission-features/reorder · POST /api/permission-actions/reorder — body { "sortedItems": [{ "id": "…", "sortOrder": 0 }] }. Requires update access (super admin by default). Details → COLLECTIONS · labels → TRANSLATIONS — Reorder drawers.
Plugin options
| Option | Default | Description |
| -------------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| disabled | false | Skip runtime i18n/onInit wiring; collections still register in schema |
| autoModifyUsersCollection | true | Add RBAC fields, parent-path hooks, and default access on the auth users collection |
| targetCollections | — | Auto ownership field + create hook on listed app collections → COLLECTIONS |
| translations | — | Admin + matrix i18n → TRANSLATIONS |
| collections | — | Per-collection fields / access / admin overrides → COLLECTIONS |
| components.rolePermissionMatrixField | default client export | Import-map path to a custom matrix Field component (client module) |
Types import from the main entry:
import type {
RBACTranslations,
PayloadPluginRBACConfig,
TargetCollection,
} from "@zealamic/payload-plugin-rbac";Exported helpers (summary)
Full reference: UTILS
| Function | Purpose |
| -------------------------------------------------------------------- | --------------------------------------------------------------------- |
| getPermissionAccess | Unified access: permission-only, read Where, or modify per-document |
| targetCollections (plugin config) | Quick ownership field + hook — COLLECTIONS |
| getCreatedByRelationshipField / createCreatedByOnCreateBeforeChangeHook | Manual ownership field + hook → UTILS |
| resolveUsersCollectionSlug | Same admin.user → slug resolution as the plugin |
| getSuperAdminAccess | Super admin only (default on RBAC collections) |
| getAuthenticatedOrSuperAdminAccess | Owner or super admin |
| canAccessDocumentByDataScope | Low-level single-document RBAC + scope check |
| resolveEffectiveDataScope / getHierarchyVisibleUserIds | Scope resolution |
| getDataScopeReadWhere / mergeDataScopeWhere | Query filters |
| getMergedFieldAffectingData / getArrayOfMergedFieldAffectingData | Field merge for overrides |
Constants: CONSTANTS.ROLE.DATA_SCOPE, CONSTANTS.PERMISSION_ACTION.TYPE, etc.
Package exports
| Import | Contents |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| @zealamic/payload-plugin-rbac | payloadPluginRBAC, utils, constants, TypeScript types |
| @zealamic/payload-plugin-rbac/client | RolePermissionMatrixClient, PermissionActionReorderClient, PermissionFeatureReorderClient, createRolePermissionMatrixClient, and related types |
Images from demo

Reorder screenshots: Reorder overview above.
License
MIT
If this plugin helps your team ship safer access control with less friction, thank you for giving it a place in your stack.
