-
-
Notifications
You must be signed in to change notification settings - Fork 38
docs: release v2.3.0 #322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs: release v2.3.0 #322
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -914,6 +914,64 @@ function future(): Any {} | |||||
|
|
||||||
| Gets the "post-update" state of an entity. Only valid when used in a "update" access policy. Read more about access policies [here](#access-policy). | ||||||
|
|
||||||
| ##### check() | ||||||
|
|
||||||
| ```zmodel | ||||||
| function check(field: FieldReference, operation String?): Boolean {} | ||||||
| ``` | ||||||
|
|
||||||
| Checks if the current user can perform the given operation on the given field. | ||||||
|
|
||||||
| _Params_ | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix emphasis used instead of a heading. Emphasis used instead of a heading. - _Params_
+ ### ParamsAlso applies to: 930-930 ToolsMarkdownlint
|
||||||
|
|
||||||
| - `field`: The field to check access for. Must be a relation field. | ||||||
| - `operation`: The operation to check access for. Can be "read", "create", "update", or "delete". If the operation is not provided, it defaults the operation of the containing policy rule. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix punctuation for readability. A punctuation mark might be missing here. - - `operation`: The operation to check access for. Can be "read", "create", "update", or "delete".
+ - `operation`: The operation to check access for. Can be "read", "create", "update", or "delete".
ToolsLanguageTool
Fix incomplete sentence. To form a complete sentence, be sure to include a subject. - Can be "read", "create", "update", or "delete".
+ The operation can be "read", "create", "update", or "delete".Committable suggestion
Suggested change
ToolsLanguageTool
|
||||||
|
|
||||||
| _Example_ | ||||||
|
|
||||||
| ```zmodel | ||||||
| // delegating a single operation kind | ||||||
| model Post { | ||||||
| id Int @id | ||||||
| author User @relation(fields: [authorId], references: [id]) | ||||||
| authorId Int | ||||||
|
|
||||||
| // delegate "read" check to the author, equivalent to | ||||||
| // @@allow('read', check(author)) | ||||||
| @@allow('read', check(author, 'read')) | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ```zmodel | ||||||
| // delegating all operations | ||||||
| model Post { | ||||||
| id Int @id | ||||||
| author User @relation(fields: [authorId], references: [id]) | ||||||
| authorId Int | ||||||
|
|
||||||
| // delegate all access policies to the author, equivalent to: | ||||||
| // @@allow('read', check(author)) | ||||||
| // @@allow('create', check(author)) | ||||||
| // @@allow('update', check(author)) | ||||||
| // @@allow('delete', check(author)) | ||||||
| @@allow('all', check(author)) | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| ```zmodel | ||||||
| // delegating field access control | ||||||
| model Post { | ||||||
| id Int @id | ||||||
| title String @allow('update', check(author)) | ||||||
| author User @relation(fields: [authorId], references: [id]) | ||||||
| authorId Int | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| :::info | ||||||
| The `check()` function only supports singular relation fields and cannot be used with "to-many" relations. We may add support for it in the future. | ||||||
| ::: | ||||||
|
|
||||||
| ##### contains() | ||||||
|
|
||||||
| ```zmodel | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| --- | ||
| sidebar_label: 4.8 Keeping the Policies DRY | ||
| slug: keep-policies-dry | ||
| --- | ||
|
|
||
| # Keeping the Policies DRY | ||
|
|
||
| ZenStack's access policies provide you with a powerful tool to model authorization in a intuitive and declarative way. However, as your application grows, you may find yourself repeating the same access policy patterns across multiple models. In this section, we'll review a typical type of duplication and show you how to avoid it by delegating to related models. | ||
|
|
||
| ### Parent-Child Duplication | ||
|
|
||
| If your application has a hierarchy of models, you'll quite often notice that the child models repeat the access policies of their parent. This can be found in our Todo schema, where `List` and `Todo` models have a parent-child relationship: | ||
|
|
||
| ```zmodel | ||
| model List { | ||
| ... | ||
|
|
||
| // require login | ||
| @@deny('all', auth() == null) | ||
|
|
||
| // can be read by space members if not private | ||
| @@allow('read', owner == auth() || (space.members?[user == auth()] && !private)) | ||
|
|
||
| // when create, owner must be set to current user, and user must be in the space | ||
| @@allow('create,update', owner == auth() && space.members?[user == auth()]) | ||
|
|
||
| ... | ||
| } | ||
|
|
||
| model Todo { | ||
| ... | ||
|
|
||
| // require login | ||
| @@deny('all', auth() == null) | ||
|
|
||
| // owner has full access | ||
| @@allow('all', list.owner == auth()) | ||
|
|
||
| // space members have full access if the parent List is not private | ||
| @@allow('all', list.space.members?[user == auth()] && !list.private) | ||
| } | ||
| ``` | ||
|
|
||
| Although not a 100% match, the rules of `Todo` closely resemble those of `List`. How can we avoid such duplication and stay DRY? | ||
|
|
||
| ### Delegating Access Control to a Relation | ||
|
|
||
| If we carefully inspect the policies, we'll find the rules of `Todo` can summarized into a single statement: | ||
|
|
||
| > One has full access to a `Todo` entity if he can read its parent `List` entity. | ||
|
|
||
| ZenStack provides a `check()` attribute function for you to delegate access control of the current model to a relation. Let's refactor the `Todo` model to use this feature 🛠️: | ||
|
|
||
| ```zmodel | ||
| model Todo { | ||
| ... | ||
|
|
||
| // full access if the parent list is readable | ||
| @@allow('all', check(list, 'read')) | ||
| } | ||
| ``` | ||
|
|
||
| When authorizing an operation on a `Todo` (e.g., "update"), ZenStack will make the decision based on if the related `List` entity is readable. If you adjust the rules on `List` in the future, the `Todo` model automatically follows without needing any changes. | ||
|
|
||
| The `check()` API can be used in both model-level and field-level policies. See the [API Reference](../../../reference/zmodel-language#check) for more details. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix grammatical error: Use "an" instead of "a".
Use “an” instead of ‘a’ if the following word starts with a vowel sound.
Committable suggestion
Tools
LanguageTool