-
Notifications
You must be signed in to change notification settings - Fork 170
docs: document cds.drafts.enforceReadonly and the @readonly bypass hint #2790
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
base: main
Are you sure you want to change the base?
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 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -116,6 +116,32 @@ public void validateOrderItem(CdsCreateEventContext context, OrderItems orderIte | |||||||||
| During activation the draft data is deleted from the database. This happens before the active entity is created or updated within the same transaction. | ||||||||||
| In case the create or update operation raises an error, the transaction is rolled back and the draft data is restored. | ||||||||||
|
|
||||||||||
| ## Read-Only Fields in Drafts { #readonly-in-drafts } | ||||||||||
|
|
||||||||||
| By default, `@readonly` and `@Core.Computed` fields are only enforced when a draft is activated, that means during the `CREATE` or `UPDATE` event on the active entity. Until then, such fields can still be changed on the draft, for example through an OData `PATCH` request. | ||||||||||
|
|
||||||||||
| To enforce these annotations on the draft already, during the `DRAFT_NEW` and `DRAFT_PATCH` events, set the [`cds.drafts.enforceReadonly`](./developing-applications/properties#cds-drafts-enforcereadonly) property (default `false`): | ||||||||||
|
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.
Suggested change
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. Maybe it doesn't even need the "even" :)
Suggested change
|
||||||||||
|
|
||||||||||
| ```yaml | ||||||||||
| cds.drafts.enforceReadonly: true | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| With this property enabled, values sent for `@readonly` or `@Core.Computed` fields are ignored when a draft is created or patched, so these fields can no longer be modified through OData requests on the draft. | ||||||||||
|
|
||||||||||
| ### Writing Read-Only Fields from Custom Code { #readonly-hint } | ||||||||||
|
|
||||||||||
| When `cds.drafts.enforceReadonly` is enabled, the read-only enforcement also applies to `Update` or `Insert` statements that your own event handlers run against the draft entity, for example in a determination. As a result, values for `@readonly` and `@Core.Computed` fields are removed from these statements as well. | ||||||||||
|
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. We should mention here explicitly that this applies to statements run via the DraftService. |
||||||||||
|
|
||||||||||
| To intentionally write such fields from trusted custom code, add the `@readonly` hint with value `false` to the statement. This disables the read-only enforcement for that single statement: | ||||||||||
|
|
||||||||||
| ```java | ||||||||||
| Update.entity(Books_.class).data(book).hint("@readonly", false); | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| ::: warning Use the hint only for trusted data | ||||||||||
| The `@readonly` hint disables the read-only field protection for the affected statement. Only use it in server-side code where the values are computed or validated by your application, never with unvalidated client input. Managed fields (`@cds.on.insert`, `@cds.on.update`) and `@Core.Immutable` fields are always enforced and are not affected by this hint. | ||||||||||
| ::: | ||||||||||
|
|
||||||||||
| ## Working with Draft-Enabled Entities | ||||||||||
|
|
||||||||||
| When deleting active entities that have a draft, the draft is deleted as well. In this case, a `DELETE` and `DRAFT_CANCEL` event are triggered. | ||||||||||
|
|
||||||||||
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.
We should also explain the effects for readonly elements calculated in code (determinations). In the default scenario determinations need to happen during draft activation on CREATE or UPDATE. They can optionally happen at draft edit time as well (to show the determined field on the UI already in that mode). If the determination is not fully deterministic (e.g. creating a random UUID) there is no guarantee that values created in draft mode and during activation are the same.
This can be solved by setting the
enforceReadonlyflag tofalseas well, as on that mode@readonlyis no longer evaluated during activation, thus elements calculated in draft mode are taken over with the exact same value.