Skip to content

Commit f3333a7

Browse files
authored
docs: release v2.3.0 (#322)
* docs: release v2.3.0 * fix build * update * add notes * update
1 parent 1b3f099 commit f3333a7

File tree

6 files changed

+127
-4
lines changed

6 files changed

+127
-4
lines changed

docs/reference/server-adapters/nestjs.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,6 @@ interface ZenStackModuleOptions {
118118
/**
119119
* A callback for getting an enhanced `PrismaClient`.
120120
*/
121-
getEnhancedPrisma: () => unknown;
121+
getEnhancedPrisma: (model?: string | symbol) => unknown;
122122
}
123123
```

docs/reference/zmodel-language.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,64 @@ function future(): Any {}
914914

915915
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).
916916

917+
##### check()
918+
919+
```zmodel
920+
function check(field: FieldReference, operation String?): Boolean {}
921+
```
922+
923+
Checks if the current user can perform the given operation on the given field.
924+
925+
_Params_
926+
927+
- `field`: The field to check access for. Must be a relation field.
928+
- `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.
929+
930+
_Example_
931+
932+
```zmodel
933+
// delegating a single operation kind
934+
model Post {
935+
id Int @id
936+
author User @relation(fields: [authorId], references: [id])
937+
authorId Int
938+
939+
// delegate "read" check to the author, equivalent to
940+
// @@allow('read', check(author))
941+
@@allow('read', check(author, 'read'))
942+
}
943+
```
944+
945+
```zmodel
946+
// delegating all operations
947+
model Post {
948+
id Int @id
949+
author User @relation(fields: [authorId], references: [id])
950+
authorId Int
951+
952+
// delegate all access policies to the author, equivalent to:
953+
// @@allow('read', check(author))
954+
// @@allow('create', check(author))
955+
// @@allow('update', check(author))
956+
// @@allow('delete', check(author))
957+
@@allow('all', check(author))
958+
}
959+
```
960+
961+
```zmodel
962+
// delegating field access control
963+
model Post {
964+
id Int @id
965+
title String @allow('update', check(author))
966+
author User @relation(fields: [authorId], references: [id])
967+
authorId Int
968+
}
969+
```
970+
971+
:::info
972+
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.
973+
:::
974+
917975
##### contains()
918976

919977
```zmodel

docs/sample-catalog.md renamed to docs/samples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
sidebar_position: 7
3-
sidebar_label: Sample Catalog
3+
sidebar_label: Sample Projects
44
---
55

66
# A Catalog of Sample Projects

docs/the-complete-guide/part1/4-access-policy/4.1-model-level.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Each of the CRUD operation types governs a set of Prisma Client methods, as foll
6969

7070
- **read**
7171

72-
`findUnique`, `findUniqueOrThrow`, `findFirst`, `findFirstOrThrow`, `count`, `aggregate`, and `groupBy`.
72+
`findMany`, `findUnique`, `findUniqueOrThrow`, `findFirst`, `findFirstOrThrow`, `count`, `aggregate`, and `groupBy`.
7373

7474
The "read" operation also determines whether the value returned from `create`, `update` and `delete` method can be read.
7575

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
sidebar_label: 4.8 Keeping the Policies DRY
3+
slug: keep-policies-dry
4+
---
5+
6+
# Keeping the Policies DRY
7+
8+
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.
9+
10+
### Parent-Child Duplication
11+
12+
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:
13+
14+
```zmodel
15+
model List {
16+
...
17+
18+
// require login
19+
@@deny('all', auth() == null)
20+
21+
// can be read by space members if not private
22+
@@allow('read', owner == auth() || (space.members?[user == auth()] && !private))
23+
24+
// when create, owner must be set to current user, and user must be in the space
25+
@@allow('create,update', owner == auth() && space.members?[user == auth()])
26+
27+
...
28+
}
29+
30+
model Todo {
31+
...
32+
33+
// require login
34+
@@deny('all', auth() == null)
35+
36+
// owner has full access
37+
@@allow('all', list.owner == auth())
38+
39+
// space members have full access if the parent List is not private
40+
@@allow('all', list.space.members?[user == auth()] && !list.private)
41+
}
42+
```
43+
44+
Although not a 100% match, the rules of `Todo` closely resemble those of `List`. How can we avoid such duplication and stay DRY?
45+
46+
### Delegating Access Control to a Relation
47+
48+
If we carefully inspect the policies, we'll find the rules of `Todo` can summarized into a single statement:
49+
50+
> One has full access to a `Todo` entity if he can read its parent `List` entity.
51+
52+
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 🛠️:
53+
54+
```zmodel
55+
model Todo {
56+
...
57+
58+
// full access if the parent list is readable
59+
@@allow('all', check(list, 'read'))
60+
}
61+
```
62+
63+
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.
64+
65+
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.

docs/welcome.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ If you're the kind of inpatient developer who wants to get your hand dirty ASAP,
4343
## Other Resources
4444

4545
- [Recipes](./category/recipes/) - Mini guides for completing specific tasks using ZenStack
46-
- [Sample Catalog](./sample-catalog) - A catalog of sample projects using different frameworks
46+
- [Samples](./samples) - A catalog of sample projects using different frameworks
4747
- [Reference](./category/reference/) - Detailed documentation for the DSL, CLI, APIs, and plugins
4848
- [FAQ](./faq) - Frequently asked questions
4949

0 commit comments

Comments
 (0)