Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Access Control

Access Control determines what a user can and cannot do with any given Document, as well as what they can and cannot see within the Admin Panel. By implementing Access Control, you can define granular restrictions based on the user, their roles (RBAC), Document data, or any other criteria your application requires.

Access Control functions are scoped to the operation, meaning you can have different rules for create, read, update, delete, etc. Access Control functions are executed before any changes are made and before any operations are completed. This allows you to determine if the user has the necessary permissions before fulfilling the request.

On-demand validation uses its own first-class validate operation for collection, global, and field access control. Its access policy falls back to the corresponding update function unless validate is configured explicitly.

There are many use cases for Access Control, including:

  • Allowing anyone read access to all posts
  • Only allowing public access to posts where a status field is equal to published
  • Giving only users with a role field equal to admin the ability to delete posts
  • Allowing anyone to submit contact forms, but only logged in users to read, update or delete them
  • Restricting a user to only be able to see their own orders, but no-one else's
  • Allowing users that belong to a certain organization to access only that organization's resources

There are three main types of Access Control in Payload:

Default Access Control

Payload provides default Access Control so that your data is secured behind Authentication without additional configuration. To do this, Payload sets a default function that checks that a user is present on the request and that the user belongs to the collection used to access the Admin Panel (config.admin.user). You can override this default behavior by defining your own Access Control functions as needed.

This means that adding a second Authentication-enabled collection does not automatically grant its users access to everything. Users from collections other than config.admin.user are denied by default unless you provide your own Access Control functions.

Here is the default Access Control that Payload provides:

1
const defaultPayloadAccess = ({ req: { payload, user } }) => {
2
// Return `true` only if a user is found
3
// and that user belongs to the admin user collection
4
return Boolean(user) && user.collection === payload.config.admin.user
5
}

Base Access Control

Use the top-level baseAccess config to apply an additional constraint to standard Collection and Global Access Control operations:

1
export default buildConfig({
2
baseAccess: {
3
collections: {
4
create: ({ req, slug }) =>
5
slug === 'public-posts' || req.user?.role === 'admin',
6
delete: ({ req, slug }) =>
7
slug === 'public-posts' || req.user?.role === 'admin',
8
update: ({ req, slug }) =>
9
slug === 'public-posts' || req.user?.role === 'admin',
10
},
11
globals: {
12
update: ({ req, slug }) =>
13
slug === 'public-settings' || req.user?.role === 'admin',
14
},
15
},
16
// ...
17
})

The collections and globals properties are typed as CollectionAccess and GlobalAccess. All Collection and Global Access Control callbacks, including normal document access, receive the document's slug.

Payload combines each configured base function with the corresponding document-specific function using AND semantics. Returning false denies the operation before the document-specific function runs. For operations that support query constraints, returning one combines it with a document-specific constraint using an and query. Collection create access only supports booleans, so returning a query constraint for that operation throws an error. Collection admin access also only supports booleans.

baseAccess applies only to Collection and Global Access Control. It does not apply to Field Access Control, custom endpoints, direct database adapter calls, job access, or other APIs with dedicated access configuration.

Like other Access Control, baseAccess is skipped when Local API operations use overrideAccess: true.

The Access Operation

The Admin Panel responds dynamically to your changes to Access Control. For example, if you restrict editing ExampleCollection to only users that feature an "admin" role, Payload will hide that Collection from the Admin Panel entirely. This is super powerful and allows you to control who can do what within your Admin Panel using the same functions that secure your APIs.

To accomplish this, Payload exposes the Access Operation. Upon login, Payload executes each Access Control function at the top level, across all Collections, Globals, and Fields, and returns a response that contains a reflection of what the currently authenticated user can do within your application.

If you use id, data, siblingData, blockData and doc within your access control functions, make sure to check that they are defined first. If they are not, then you can assume that your Access Control is being executed via the Access Operation to determine solely what the user can do within the Admin Panel.

Locale Specific Access Control

To implement locale-specific access control, you can use the req.locale argument in your access control functions. This argument allows you to evaluate the current locale of the request and determine access permissions accordingly.

Here is an example:

1
const access = ({ req }) => {
2
// Grant access if the locale is 'en'
3
if (req.locale === 'en') {
4
return true
5
}
6
7
// Deny access for all other locales
8
return false
9
}

Was this page helpful?

Next

Collection Access Control