Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion docs/reference/server-adapters/nestjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,6 @@ interface ZenStackModuleOptions {
/**
* A callback for getting an enhanced `PrismaClient`.
*/
getEnhancedPrisma: () => unknown;
getEnhancedPrisma: (model?: string | symbol) => unknown;
}
```
58 changes: 58 additions & 0 deletions docs/reference/zmodel-language.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Copy link
Contributor

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.

- Only valid when used in a "update" access policy.
+ Only valid when used in an "update" access policy.
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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).
Gets the "post-update" state of an entity. Only valid when used in an "update" access policy. Read more about access policies [here](#access-policy).
Tools
LanguageTool

[misspelling] ~915-~915: Use “an” instead of ‘a’ if the following word starts with a vowel sound, e.g. ‘an article’, ‘an hour’.
Context: ...e of an entity. Only valid when used in a "update" access policy. Read more about...

(EN_A_VS_AN)


##### check()

```zmodel
function check(field: FieldReference, operation String?): Boolean {}
```

Checks if the current user can perform the given operation on the given field.

_Params_
Copy link
Contributor

Choose a reason for hiding this comment

The 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_
+ ### Params

Also applies to: 930-930

Tools
Markdownlint

925-925: null
Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


- `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.
Copy link
Contributor

Choose a reason for hiding this comment

The 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".

Committable suggestion was skipped due to low confidence.

Tools
LanguageTool

[uncategorized] ~928-~928: Loose punctuation mark.
Context: ...Must be a relation field. - operation: The operation to check access for. Can ...

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~928-~928: To form a complete sentence, be sure to include a subject.
Context: ...on`: The operation to check access for. Can be "read", "create", "update", or "dele...

(MISSING_IT_THERE)


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

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `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.
`operation`: The operation to check access for. The operation can be "read", "create", "update", or "delete". If the operation is not provided, it defaults the operation of the containing policy rule.
Tools
LanguageTool

[uncategorized] ~928-~928: Loose punctuation mark.
Context: ...Must be a relation field. - operation: The operation to check access for. Can ...

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~928-~928: To form a complete sentence, be sure to include a subject.
Context: ...on`: The operation to check access for. Can be "read", "create", "update", or "dele...

(MISSING_IT_THERE)


_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
Expand Down
2 changes: 1 addition & 1 deletion docs/sample-catalog.md → docs/samples.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
sidebar_position: 7
sidebar_label: Sample Catalog
sidebar_label: Sample Projects
---

# A Catalog of Sample Projects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Each of the CRUD operation types governs a set of Prisma Client methods, as foll

- **read**

`findUnique`, `findUniqueOrThrow`, `findFirst`, `findFirstOrThrow`, `count`, `aggregate`, and `groupBy`.
`findMany`, `findUnique`, `findUniqueOrThrow`, `findFirst`, `findFirstOrThrow`, `count`, `aggregate`, and `groupBy`.

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

Expand Down
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.
2 changes: 1 addition & 1 deletion docs/welcome.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ If you're the kind of inpatient developer who wants to get your hand dirty ASAP,
## Other Resources

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

Expand Down