npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

payload-rbac-plugin

v1.1.0

Published

RBAC plugin for payloadcms

Readme

Payload CMS Dynamic RBAC Plugin

NPM Version NPM Downloads License CI Status

A professional, database-backed Role-Based Access Control (RBAC) system for Payload CMS (v3).

This plugin emphasizes checking permissions instead of roles to avoid hard-coded authorization logic in your source code, making your access control highly scalable, modular, and dynamic.


Features

  • Attribute-Based Access Control (ABAC): Support for dynamic, Row-Level Security conditions configured right from the Payload Admin UI. No code updates required!
  • Dynamic Collections: Automatically injects database-backed Roles and Permissions collections.
  • Auth Collection Extension: Injects a roles relationship field into your target auth collection (e.g., users) with saveToJWT: true for zero-cost runtime checks.
  • Bulk Permission Generator: In the Admin UI, easily switch between creating a single permission or using the Bulk CRUD Generator to automatically generate separate permissions (e.g., posts:create, posts:read, posts:update, posts:delete) at once.
  • UI-Only Helpers: Bulk generator fields (type, collectionName, CRUD checkboxes) are purely for the UI and are never saved to your database, keeping your collections clean.
  • Customizable Schemas: Allow developers to inject additional custom fields into both Roles and Permissions schemas.
  • Granular Control: Set visibility permissions (hideRoles, hidePermissions) dynamically or statically for the RBAC admin interface.
  • Helper Utilities: Simple and robust functions to check permissions (hasPermission) and access control wrappers (checkPermission).
  • Fully Tested: Powered by a robust integration and unit test suite built with Vitest.

Screenshots

1. Permissions List View

Shows flat generated permissions (e.g. posts:create, posts:read) and legacy system permissions. Permissions List View

2. Single Permission Form

Create individual custom permissions. Single Permission Form

3. Bulk CRUD Generator Form

Select a collection and check CRUD actions to instantly generate multiple permissions. Bulk CRUD Generator Form

4. Roles List View

Displays roles and all permissions associated with them. Roles List View

5. Role Configuration Form

Assign permissions directly to roles in the admin UI. Role Configuration Form


Installation

Add the plugin to your project:

pnpm add payload-rbac-plugin
# or
npm install payload-rbac-plugin
# or
yarn add payload-rbac-plugin

Setup & Configuration

Import and configure the plugin in your payload.config.ts:

import { buildConfig } from 'payload'
import { rbac, hasPermission } from 'payload-rbac-plugin'

export default buildConfig({
  collections: [
    {
      slug: 'posts',
      fields: [],
    },
  ],
  plugins: [
    rbac({
      enabled: true,
      // Optional configurations:
      authCollectionSlug: 'users',        // Default: 'users'
      rolesCollectionSlug: 'roles',        // Default: 'roles'
      permissionsCollectionSlug: 'permissions', // Default: 'permissions'
      
      // Control access/visibility of the RBAC panel:
      hidePermissions: ({ user }) => !hasPermission(user, 'access:permissions'),
      hideRoles: ({ user }) => !hasPermission(user, 'access:roles'),
    }),
  ],
})

Configuration Options

| Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | enabled | boolean | true | Enable or disable the plugin. | | authCollectionSlug | string | 'users' | The collection slug representing the users collection. | | rolesCollectionSlug | string | 'roles' | The slug for the automatically injected Roles collection. | | permissionsCollectionSlug | string | 'permissions' | The slug for the automatically injected Permissions collection. | | rolesFields | Field[] | [] | Extra custom fields to inject into the Roles collection. | | permissionsFields | Field[] | [] | Extra custom fields to inject into the Permissions collection. | | hideRoles | boolean \| ((args: { user: any }) => boolean) | false | Hide the Roles collection from the sidebar navigation. | | hidePermissions | boolean \| ((args: { user: any }) => boolean) | false | Hide the Permissions collection from the sidebar navigation. | | permissionsAccess | CollectionConfig['access'] | { ... } | Access control functions for the generated Permissions collection (defaults to public). | | rolesAccess | CollectionConfig['access'] | { ... } | Access control functions for the generated Roles collection (defaults to public). |


Usage

1. Protecting Collections (Access Control)

You can protect collections using the checkPermission Higher-Order Function. It returns a standard Payload Access control resolver.

import { checkPermission } from 'payload-rbac-plugin'

export const PostsCollection = {
  slug: 'posts',
  access: {
    create: checkPermission('posts:create'),
    read: checkPermission('posts:read'),
    update: checkPermission('posts:update'),
    delete: checkPermission('posts:delete'),
  },
  fields: [],
}

2. Dynamic Row-Level Security (ABAC)

The checkPermission wrapper natively supports Attribute-Based Access Control (ABAC). If an administrator assigns a permission with conditions in the Admin UI (e.g. sender equals {{user.id}}), checkPermission will automatically map it to a Payload Where object without any code changes!

If you need to construct these queries manually outside of standard access control, you can use the getPermissionQuery utility:

import { getPermissionQuery } from 'payload-rbac-plugin'

export const CustomEndpoint = async (req) => {
  // Returns `true`, `false`, or a Payload Where object depending on UI conditions
  const accessQuery = getPermissionQuery(req.user, 'posts:read')
  
  if (!accessQuery) return Response.json({ error: 'Forbidden' }, { status: 403 })

  const posts = await req.payload.find({
    collection: 'posts',
    where: typeof accessQuery === 'object' ? accessQuery : undefined,
  })
}

Supported Dynamic Variables

When defining conditional Values in the UI, you can inject variables:

  • {{user.id}} - Replaced with the current user's ID
  • {{user.roles}} - Replaced with an array of the user's role IDs (useful for the in operator)
  • {{user.role}} - Replaced with the user's role ID (if using a single custom role field)
  • true / false - Properly parsed into booleans (useful for the exists operator)

3. Manual Permission Verification (hasPermission)

For custom endpoints, hooks, or conditionally rendering logic, use the hasPermission utility:

import { hasPermission } from 'payload-rbac-plugin'

const myCustomEndpoint = (req, res) => {
  const user = req.user
  
  if (hasPermission(user, 'export:reports')) {
    // allow operation
  } else {
    res.status(403).send('Forbidden')
  }
}

Bulk Permission Generator UI

When navigating to the Permissions collection in your Payload Admin panel:

  1. Select Bulk CRUD Generator in the Type select box (visible only during document creation).
  2. Enter the target collection slug (e.g. posts) in the Collection Name field.
  3. Check the CRUD operations you wish to generate (e.g., create, read).
  4. Save the document.
  5. The plugin runs a beforeChange hook that creates individual flat records (posts:create, posts:read) in the database, and avoids saving any temporary helper fields to the database.

Development & Testing

If you are developing this plugin locally, you can run the test suite:

# Run unit and integration tests
pnpm test:int

# Run tests in watch mode
pnpm test:int --watch

License

MIT