Skip to content

Commit 9327f55

Browse files
authored
Merge pull request #33 from mnfst/ownership
Ownership-based access
2 parents 5696395 + 859a7fc commit 9327f55

File tree

4 files changed

+71
-22
lines changed

4 files changed

+71
-22
lines changed

access-policies.md

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ id: access
66

77
Access Policies ensure that we provide specific access to resources for users. You may want to open publicly the **read** access for an entity while limiting **creation** to logged in users for example.
88

9-
Acces policies are a way to implement **Authorization** following the RBAC (Role-Based Access Control) method. Indeed it is possible to create different entities (ex: User, Manager...) with different access to resources.
9+
Access policies are a way to implement **Authorization** following the RBAC (Role-Based Access Control) method. Indeed it is possible to create different entities (ex: User, Manager...) with different access to resources. You also can limit access to a user own's records using [ownership-based access](#ownership-based-access).
1010

11-
Policies can be added to [entities](./entities.md) or [endpoints](./endpoints.md).
11+
Policies can be added to [entities](./entities.md) and [endpoints](./endpoints.md).
12+
13+
:::info
14+
By default, all CRUD rules access are set to **admin** and thus only available for logged-in admins. Custom endpoints are **public** by default.
15+
:::
1216

1317
## Syntax
1418

@@ -33,8 +37,6 @@ entities:
3337
3438
In this case, everyone can see the **Invoice** items, only logged-in **Users** can create new ones. Updating an Invoice is restricted to [Admins](./auth.md#admins) only and no one can delete them (not even Admins).
3539
36-
By default, all rules access are set to **admin** and thus only visible by logged-in **Admins**.
37-
3840
| Prop | Description | Type |
3941
| ---------- | ------------------------------------------------------------------------- | ------------------ |
4042
| **access** | The type of access: **public**, **restricted**, **admin**, **forbidden** | AccessType |
@@ -44,12 +46,12 @@ By default, all rules access are set to **admin** and thus only visible by logge
4446
4547
There are 4 possible access types:
4648
47-
| Access | Description | Short version (emoji) |
48-
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
49-
| **public** | Everyone has access | 🌐 |
50-
| **restricted** | Only logged-in users have access to it. If _allow_ key specifies one or several entities, users logged in as other entities will not have access. Admins always have access to restricted rules | 🔒 |
51-
| **admin** | Only [admins](./auth.md#admins) have access | 👨🏻‍💻 |
52-
| **forbidden** | No one has access, not even admins | 🚫 |
49+
| Access | Description | Short version (emoji) |
50+
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
51+
| **public** | Everyone has access | 🌐 |
52+
| **restricted** | Only logged-in users have access to it. If _allow_ key specifies one or several entities, users logged in as other entities will not have access. If _condition_ is set to `self`, it limits access to the item owner. Admins always have access to restricted rules | 🔒 |
53+
| **admin** | Only [admins](./auth.md#admins) have access | 👨🏻‍💻 |
54+
| **forbidden** | No one has access, not even admins | 🚫 |
5355

5456
### Entity rules
5557

@@ -63,18 +65,65 @@ Each entity has **5 rules** where one or several access policies can be applied:
6365

6466
By default, all rules have the [admin access type](#access-types)
6567

68+
## Ownership-based access
69+
70+
Above rules are based on predefined roles, but you many want to grant user access only to their own records. For example, a platform like _Craiglist_ allows its users to create and manage classified ads only for them, not letting users edit others' content.
71+
72+
In Manifest, this is done simply by adding the `{condition: 'self'}` to a restricted policy:
73+
74+
```yaml
75+
User:
76+
properties:
77+
- name
78+
authenticable: true
79+
80+
Project:
81+
properties:
82+
- name
83+
belongsTo:
84+
- User # Should belong to an authenticable entity.
85+
policies:
86+
create:
87+
- { access: restricted, allow: User, condition: self }
88+
```
89+
90+
See ? Just adding the `self` condition prevent creating projects for other users than themselves.
91+
92+
Even if it looks very simple, it has slighlty different impact based on rule where it is added. See the following example:
93+
94+
```yaml
95+
policies:
96+
create:
97+
- { access: restricted, allow: User, condition: self }
98+
read:
99+
- { access: restricted, allow: User, condition: self }
100+
update:
101+
- { access: restricted, allow: User, condition: self }
102+
delete:
103+
- { access: restricted, allow: User, condition: self }
104+
```
105+
106+
This means:
107+
108+
- Create: Record creation is authorized only if owner is the logged in user
109+
- Read: You can only fetch your own record: it forces a filter
110+
- Update: You only can update your own records and cannot change the ownership of them
111+
- Delete: You only can delete your own records
112+
66113
## Additional examples
67114

68115
```yaml
69116
entities:
70117
Project 🗂️:
71118
properties:
72119
- name
120+
belongsTo:
121+
- Manager
73122
policies:
74123
read:
75124
- { access: restricted, allow: [Contributor, Manager] } # Only some entities (and admins).
76125
create:
77-
- { access: restricted, allow: Manager } # Only managers (and admins).
126+
- { access: restricted, allow: Manager, condition: self } # Only managers for themselves (and admins).
78127
update:
79128
- access: 👨🏻‍💻 # Only admin.
80129
delete:

auth.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@ entities:
4747
- name
4848
```
4949
50-
Authenticable entities have 2 extra properties that are used as credentials to log in: `email` and `password`. You do not need to specify them.
51-
52-
The passwords are automatically hashed using _bcryt_ with 10 salt rounds.
50+
Authenticable entities have 2 extra properties that are used as credentials to log in: `email` and `password`. You do not need to specify them.The `email` property expects a unique valid emails and the `password` property is automatically hashed using _bcryt_ with 10 salt rounds.
5351

5452
## Actions
5553

@@ -187,7 +185,7 @@ Logout removes the token from future request headers.
187185
</TabItem>
188186
<TabItem value="sdk" label="JS SDK" default>
189187
```js
190-
// All future calls will lose the "Authorization" header.
188+
// Resets the "Authorization" header for all future calls.
191189
await manifest.logout()
192190
```
193191

crud.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ This operation will create a new item and store it in the database. The newly cr
261261

262262
```json title="Example HTTP Response"
263263
{
264-
"id": '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
264+
"id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
265265
"name": "Pikachu",
266266
"type": "electric",
267267
"level": 3,
@@ -280,7 +280,7 @@ This operation will create a new item and store it in the database. The newly cr
280280

281281
console.log(newPokemon);
282282
// Output: {
283-
// id: '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
283+
// id: "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
284284
// name: "Pikachu",
285285
// type: "electric",
286286
// level: 3
@@ -314,7 +314,7 @@ Unlike [partial updates](#patch-an-item), this operation will replace the whole
314314

315315
```json title="Example HTTP Response"
316316
{
317-
"id": '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
317+
"id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
318318
"name": "Raichu",
319319
"type": "electric",
320320
"level": 8
@@ -333,7 +333,7 @@ Unlike [partial updates](#patch-an-item), this operation will replace the whole
333333

334334
console.log(newPokemon);
335335
// Output: {
336-
// id: 'a1b2c3d4-e5f6-4789-abcd-ef0123456789',
336+
// id: "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
337337
// name: "Raichu",
338338
// type: "electric",
339339
// level: 8
@@ -363,7 +363,7 @@ Unlike [fully replacement](#update-an-item), this operation will only modify the
363363

364364
```json title="Example HTTP Response"
365365
{
366-
"id": 'a1b2c3d4-e5f6-4789-abcd-ef0123456789',
366+
"id": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
367367
"name": "Pikachu",
368368
"type": "electric",
369369
"level": 5
@@ -380,7 +380,7 @@ Unlike [fully replacement](#update-an-item), this operation will only modify the
380380

381381
console.log(newPokemon);
382382
// Output: {
383-
// id: 'a1b2c3d4-e5f6-4789-abcd-ef0123456789',
383+
// id: "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
384384
// name: "Pikachu",
385385
// type: "electric",
386386
// level: 5

entities.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ Timestamp field (ISO 8601 Format)
246246
```
247247

248248
#### Email
249+
You can create one-to-many relationships or many-to-many relationships. Defining relationships in your entities allows you to load relations when you query them and also filter by relations.
250+
249251

250252
```yaml
251253
- { name: email, type: email }
@@ -341,7 +343,7 @@ The location type consists in a object with `lat` and `lng` coordinates.
341343

342344
## Relations
343345

344-
You can create **one-to-many** relationships or **many-to-many** relationships.
346+
You can create **one-to-many** relationships or **many-to-many** relationships. Defining relationships in your entities allows you to [load relations](./crud.md#load-relations) when you query them and also [filter your query by relations](./crud.md#filter-by-relation).
345347

346348
### Syntax
347349

0 commit comments

Comments
 (0)