docs(12.1-05): state the limits of relation locks and locked permission codes

- a relation lock covers the form field only; a relation manager on the same relation does not ask the provider
- a locked permission code must be stored with a value its mode can send
This commit is contained in:
Jakub Zych
2026-10-05 16:01:10 +02:00
parent 3190b1ce59
commit 83feeef9fa
2 changed files with 2 additions and 0 deletions

View File

@@ -314,6 +314,7 @@ func (MembersController) AdminSetPermissionValues(_ context.Context, field strin
- A save checks the submitted object inside its transaction, after the Form before-hooks and before the row is written. A value that is not an object of integers, a code the controller does not offer, or a value outside the mode's set is a 422 on the field; a `0` means "no value". The checked set is then handed to `AdminSetPermissionValues`, which decides how it is stored. - A save checks the submitted object inside its transaction, after the Form before-hooks and before the row is written. A value that is not an object of integers, a code the controller does not offer, or a value outside the mode's set is a 422 on the field; a `0` means "no value". The checked set is then handed to `AdminSetPermissionValues`, which decides how it is stored.
- A stored code that is not among the options is kept as it is: an offered code that is left out loses its value, a code that is not offered is never touched and can never be submitted. - A stored code that is not among the options is kept as it is: an offered code that is left out loses its value, a code that is not offered is never touched and can never be submitted.
- An option with `Locked` set is shown with a disabled control. The server enforces it: a save in which a locked code's value differs from the stored one is answered 403 `forbidden` with a message on the field, and nothing is written. - An option with `Locked` set is shown with a disabled control. The server enforces it: a save in which a locked code's value differs from the stored one is answered 403 `forbidden` with a message on the field, and nothing is written.
- A locked code must be stored with a value its mode can send: 1, -1 or no value in radio mode, 1 or no value in checkbox mode. The admin sends only those values, so a locked code stored with anything else never matches, and every save of that record from the admin form is refused for that administrator. Normalize stored values before locking a code.
- A save that does not send the field leaves the stored permissions alone, and the field's `context` applies as for any field. - A save that does not send the field leaves the stored permissions alone, and the field's `context` applies as for any field.
- The keys `options`, `default`, `nameFrom`, `emptyOption`, `relation` and `preset` are refused on the type. A field without `mode`, or on a controller that does not implement the provider, stops the start-up. The type is not available on settings forms or relation forms. - The keys `options`, `default`, `nameFrom`, `emptyOption`, `relation` and `preset` are refused on the type. A field without `mode`, or on a controller that does not implement the provider, stops the start-up. The type is not available on settings forms or relation forms.

View File

@@ -78,6 +78,7 @@ func (c MembersController) AdminRelationLocks(ctx context.Context, field string)
- The server enforces the lock; the flag is only a display aid. A create or update is checked inside its transaction, after the scope check and before any row is written. For a belongsToMany field the locked ids among the record's current links and among the submitted ids must be the same set, so a locked record can be neither added nor removed while other links change freely. For a belongsTo field a change is refused when the current or the submitted record is locked. - The server enforces the lock; the flag is only a display aid. A create or update is checked inside its transaction, after the scope check and before any row is written. For a belongsToMany field the locked ids among the record's current links and among the submitted ids must be the same set, so a locked record can be neither added nor removed while other links change freely. For a belongsTo field a change is refused when the current or the submitted record is locked.
- A refused save is answered 403 `forbidden` with the lock's `Message` (a translation key or text), also as a message on the field, and nothing is written. With an empty `Message` the admin shows its own text. - A refused save is answered 403 `forbidden` with the lock's `Message` (a translation key or text), also as a message on the field, and nothing is written. With an empty `Message` the admin shows its own text.
- A save that does not send the field is not checked: it changes nothing. A controller without the provider behaves as before. - A save that does not send the field is not checked: it changes nothing. A controller without the provider behaves as before.
- The lock covers the form field only. A relation manager declared for the same relation does not ask the provider: its link and unlink routes change the links whatever the lock says. Give a relation whose links carry privilege one writer, the form field, and declare no relation manager for it.
- The provider is asked with the request context: `bouncer.User(ctx)` is the administrator, and inside a save `cabana.TxFromContext(ctx)` is the transaction. - The provider is asked with the request context: `bouncer.User(ctx)` is the administrator, and inside a save `cabana.TxFromContext(ctx)` is the transaction.
## Relation managers ## Relation managers