Skip to content
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
413de25
Add first draft of custom conditions for RBAC
pwizla Mar 9, 2021
ea4094d
Improve RBAC dev doc to follow the dev journey
pwizla Mar 9, 2021
ad97023
Move unstable warning at top of section
pwizla Mar 11, 2021
c9edbe2
Improve introduction of RBAC in dev docs
pwizla Mar 11, 2021
0555f7c
Add all 3 badges to RBAC section title
pwizla Mar 11, 2021
091422c
Improve property descriptions for RBAC custom conditions
pwizla Mar 11, 2021
3ebf959
Reword parts of RBAC dev docs for a more neutral style
pwizla Mar 11, 2021
ca8b323
Remove useless parenthesis in RBAC dev intro
pwizla Mar 11, 2021
96dd467
Merge branch 'main' into developer/rbac
pwizla Mar 12, 2021
3402f67
Fix grammar mistake in RBAC dev docs 🤦
pwizla Mar 12, 2021
8c258d2
Clarify the plugin property in RBAC conditions
pwizla Mar 12, 2021
bff0d7f
Update true/false examples for RBAC condition handler
pwizla Mar 12, 2021
f2ce2c5
Add tip about `name` being a unique id in RBAC conditions
pwizla Mar 13, 2021
457eef1
Reframe RBAC intro about default roles & custom conditions
pwizla Mar 13, 2021
63225bc
Improve RBAC devs doc intro
pwizla Mar 15, 2021
9c18431
Extend RBAC `handler` dev doc
pwizla Mar 15, 2021
d78bcfb
Simplify and harmonize naming in RBAC dev docs
pwizla Mar 15, 2021
a8dc784
Fix typo in async handler example for RBAC dev docs
pwizla Mar 15, 2021
6e4d42f
Fix link to bootstrap.js in RBAC dev docs
pwizla Mar 15, 2021
8c40c5b
Extend RBAC dev docs on register() vs. registerMany()
pwizla Mar 15, 2021
52307f4
Simplify sentences & uniformize style further in RBAC dev docs
pwizla Mar 15, 2021
6064ad2
Fix link to bootstrap.js doc entry in RBAC dev docs
pwizla Mar 15, 2021
afdca50
Add link to codebase for `name` RBAC condition property
pwizla Mar 15, 2021
9a6d3fb
Document `category` property in RBAC conditions
pwizla Mar 18, 2021
dec88f6
Rewrite `handler` documentation in RBAC conditions
pwizla Mar 18, 2021
4213e76
Give examples for both `register` & `registerMany` in RBAC conditions
pwizla Mar 18, 2021
0afa7ca
Add link to user guide for condition categories in RBAC dev docs
pwizla Mar 18, 2021
61cfac3
Clarify the use of query objects in RBAC `handler`
pwizla Mar 19, 2021
43d9856
Merge branch 'main' into developer/rbac
pwizla Mar 20, 2021
915fa87
Add "publish" to query objects definition in RBAC dev docs
pwizla Mar 23, 2021
d203163
Merge branch 'main' into developer/rbac
pwizla Mar 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions docs/developer-docs/latest/setup-deployment-guides/configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -1575,3 +1575,131 @@ module.exports = () => ({
},
});
```

### Role-Based Access Control <BronzeBadge link="https://strapi.io/pricing"/> <SilverBadge link="https://strapi.io/pricing"/> <GoldBadge link="https://strapi.io/pricing" withLinkIcon/>

::: warning 🚧 This API is considered unstable for now.
<br>
:::

Role-Based Access Control (RBAC) is an approach to restricting access to some users. In a Strapi application, users of the admin panel are administrators. Their roles and permissions are [configured in the admin panel](/user-docs/latest/users-roles-permissions/configuring-administrator-roles.md). The Community Edition of Strapi offers 3 default roles (Author, Editor, and Super Admin). To go further, creating custom conditions for any type of permission is also possible. This requires an Enterprise Edition with at minimum a Bronze licence plan.

#### Declaring new conditions

Declare a single condition as an object, and multiple conditions as an array of objects. Each condition object can have 5 possible properties:

- `displayName` (string): the condition name as shown in the admin panel,
- `name` (string): the condition name, kebab-cased,
- `category` (string, _optional_): conditions can be grouped into categories available [in the admin panel](/user-docs/latest/users-roles-permissions/configuring-administrator-roles.md#setting-custom-conditions-for-permissions); if undefined, the condition will appear under the "Default" category,
- `plugin` (string, _optional_): if the condition is created by a plugin, should be the plugin's name, kebab-cased (e.g `content-manager`),
- `handler`: a query object or a function used to verify the condition (see [using the condition handler](#using-the-condition-handler))

Declare and register conditions in your [`./config/functions/bootstrap.js`](/developer-docs/latest/setup-deployment-guides/configurations.md#bootstrap) file (see [Registering conditions](#registering-conditions)).

:::tip NOTE
The condition `name` property acts as a [unique id](https://github.com/strapi/strapi/blob/master/packages/strapi-admin/services/permission/condition-provider.js#L22) within its namespace, that is either the plugin if the `plugin` property is defined, or the root namespace.
:::

#### Using the condition handler

A condition can be applied to any permission, and the condition `handler` is used to verify the condition. The `handler` can be a query object or a function.

Query objects are useful to verify conditions on the entities you read, create, update, delete or publish. They use the [sift.js](https://github.com/crcn/sift.js) library, but only with the following supported operators:

- `$or`
- `$eq`
- `$ne`
- `$in`
- `$nin`
- `$lt`
- `$lte`
- `$gt`
- `$gte`
- `$exists`
- `$elemMatch`

For instance, this `handler` uses a query object to match entities with an `amount` lower than 10,000:

```js
handler: { amount: { $lt: 10000 } }
```

The condition `handler` can also be a synchronous or asynchronous function that:

* receives the authenticated user making the request,
* and returns `true`, `false`, or a query object.

Returning `true` or `false` is useful to verify an external condition or a condition on the authenticated user.
For instance, a condition that allows access to a page in the admin panel only if server time is 5pm could use this handler:

```js
handler: () => new Date().getHours() === 17
```

The `handler` function receives the authenticated user, so it can verify conditions on the user:

```js
const condition = {
displayName: "Email address from strapi.io",
name: "email-strapi-dot-io",
async handler(user) {
return user.email.includes('@strapi.io');
},
};
```

For more granular control, the `handler` function can also return a query object:

```js
const condition = {
displayName: "price greater than 50",
name: "price-gt-50",
async handler(user) {
return { price: { $gt: 50 } };
},
};
```


#### Registering conditions

To be available in the admin panel, conditions should be declared and registered in the [`./config/functions/bootstrap.js`](/developer-docs/latest/setup-deployment-guides/configurations.md#bootstrap) file. Register a single condition with the `conditionProvider.register()` method:

```js
module.exports = () => {
strapi.admin.services.permission.conditionProvider.register({
displayName: 'Billing amount under 10K',
name: 'billing-amount-under-10k',
plugin: 'admin',
handler: { amount: { $lt: 10000 }},
});
};
```

To register multiple conditions, defined as an array of [condition objects](#declaring-new-conditions), use `conditionProvider.registerMany()`:

```js
const conditions = [
{
displayName: "Entity has same name as user",
name: "same-name-as-user",
plugin: "name of a plugin if created in a plugin"
handler: (user) => {
return { name: user.name };
},
},
{
displayName: "Email address from strapi.io",
name: "email-strapi-dot-io",
async handler(user) {
return user.email.includes('@strapi.io');
},
}
];

module.exports = () => {
// do your boostrap

strapi.admin.services.permission.conditionProvider.registerMany(conditions);
};
```