

Payload comes with open-ended access control. You can define whatever type of pattern that you can dream up, and best of all—it's all done with simple JavaScript.
A common pattern is Role-Based Access Control. Here, we'll walk you through how to create your own RBAC pattern on both the collection-level and field-level.
In more detail, here are the pieces that we will be building:
role fieldWe'll be using create-payload-app to build out the initial project.
npx create-payload-app payload-rbacjavascript for languageblank for our templateThis will give us a simple project with a Payload config and Users collection. The structure of the project will be:
First, we will add the role field to our Users collection with 2 options: admin and user.
Next, we will create a new Orders.js collection in our collections/ directory and scaffold out basic fields and values - including the createdBy relationship to the user.
The Orders collection has an array field for items and a createdBy field which is a relationship to our Users collection. The createdBy field will feature a strict update access control function so that it can never be changed.
Notice we also have a condition function under the createdBy field's access. This will hide createdBy until it has a value.
createdBy Attribute Using a HookNext, we'll add a hook that will run before any order is created. This is done by adding a beforeChange hook to our collection definition.
The logic in this hook sets the createdBy field to be the current user's id value, only if it is on a create operation. This will create a relationship between an order and the user who created it.
Next, the access control for the collection can be defined. Payload's access control is based on functions. An access control function returns either a boolean value to allow/disallow access or it returns a query constraint that filters the data.
We want our function to handle a few scenarios:
Once defined, this function is added to the access property of the collection definition:
With this function added to the read, update, and delete access properties, the function will run whenever these operations are attempted on the collection.
The last step is to add the collection to our payload.config.js
Let's verify the functionality:
Start up the project by running npm run dev or yarn dev and navigate to http://localhost:3000/admin
Create your initial user with the admin role.

Create an Order with the admin user.


Create an additional user with the user role by navigating to the Users collection, selecting Create New, entering an email/password, then saving.


Log out of your admin user by selecting the icon in the bottom left, then log in with the second user.

You'll notice if we go to the Orders collection, no Orders will be shown. This indicates that the access control is working properly.


Create another Order. Note that the current user will be saved to Created By in the sidebar.

Navigate back to Orders list on the dashboard. There will only be the single order created by the current user.

Log out, then back in with your admin user. You should be able to see the original Order as well as the Order created by the second user.

With everything working at the collection level, we can carry the concepts further and see how they can be applied at the field level. Suppose we wanted to add a paymentID field only for Admin users. Create an isAdmin function that checks the role as we did earlier.
Add a new field to Orders and set create, read or update access calls to use the isAdmin function.
The new paymentID field is not available to the users even on one's own Order. Field level access controls allow for greater granularity over document level access for Collections and Globals. This shows how easy it is to manage exact permissions throughout the admin UI, GraphQL and REST endpoints; it even works when querying relationships to keep data secure.
Now that we have a basic example working. What are some ways that this could be improved?
editor role which allows reading and editing, but disallows creating. This all can be customized specifically to your needs.I hope you enjoyed the introduction to doing role-based access control with Payload!
Come join the Payload discussions on GitHub.