You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/reference/zmodel-language.md
+15-1Lines changed: 15 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1518,7 +1518,21 @@ A field can also contain an arbitrary number of policy rules. The logic of combi
1518
1518
1519
1519
Please note the difference between model-level and field-level rules. Model-level access are by-default denied, while field-level access are by-default allowed.
1520
1520
1521
-
### Pre-update vs. post-update
1521
+
### "Create" rules
1522
+
1523
+
The "create" policy rules should be understood as: **if an entity were to be created, would it satisfy the rules**. Or, in other words, the rules are checked "post create".
1524
+
1525
+
An entity creating process works like the following:
1526
+
1527
+
1. Initiate a transaction and create the entity.
1528
+
2. In the same transaction, try to read the created entity with the "create" rules as filter, and see if it succeeds.
1529
+
3. If the read fails, the transaction is rolled back; otherwise it's committed.
1530
+
1531
+
The "post-create check" semantic allows the rules to access relations of the entity being created since they are only accessible after the create happens. For simple cases, ZenStack may apply optimizations to reject a create request without initiating a transaction, but generally speaking the "post-create check" semantic is the correct way to think about it.
1532
+
1533
+
We may introduce a "pre-create" policy type in the future.
1534
+
1535
+
### "Pre-update" vs." post-update" rules
1522
1536
1523
1537
When an access policy rule is applied to a mutate operation, the entities under operation have a "pre" and "post" state. For a "create" rule, its "pre" state is empty, so the rule implicitly refers to the "post" state. For a "delete" rule, its "post" state is empty, so the rule implicitly refers to the "pre" state.
We queried with user Joey and now can get the `List` created by Rachel because Joey is a member of the same space.
172
+
173
+
:::info A note about "create" rules
174
+
175
+
You might have noticed we have two "create" rules in the `SpaceUser` model.
176
+
177
+
```zmodel
178
+
// space owner can add any one
179
+
@@allow('create', space.owner == auth())
180
+
181
+
// space admin can add anyone but not himself
182
+
@@allow('create', auth() != user
183
+
&& space.members?[user == auth() && role == 'ADMIN'])
184
+
```
185
+
186
+
One might be tempting to use one simple rule like the following to allow space admins to create new memberships.
187
+
188
+
```zmodel
189
+
@@allow('create', space.members?[user == auth() && role == 'ADMIN'])
190
+
```
191
+
192
+
However, it'll be problematic due to "create" rule's semantic - **if an entity were to be created, would it satisfy the rules**? Or, in more details, a create process works like the following:
193
+
194
+
1. Initiate a transaction and create the entity.
195
+
2. In the same transaction, try to read the created entity with the "create" rules as filter, and see if it succeeds.
196
+
3. If the read fails, the transaction is rolled back; otherwise it's committed.
197
+
198
+
The "post-create check" semantic allows the rules to access relations of the entity being created. For simple cases, ZenStack may apply optimizations to reject a create request without initiating a transaction, but generally speaking the "post-create check" semantic is the correct way to think about it. We may introduce a "pre-create" policy type in the future.
199
+
200
+
With these in mind, if we were to use the simple rule, a user can add himself to any space as "ADMIN", because after the create happens, the new membership would satisfy the rule. By splitting the rule into two, we can prevent this from happening:
201
+
202
+
- Space owner can add anyone (including himself) into the space.
0 commit comments