diff --git a/docs/backend/forms.md b/docs/backend/forms.md index 10e910d..d12378b 100644 --- a/docs/backend/forms.md +++ b/docs/backend/forms.md @@ -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 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. +- 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. - 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. diff --git a/docs/backend/relation-manager.md b/docs/backend/relation-manager.md index 0933697..dae8703 100644 --- a/docs/backend/relation-manager.md +++ b/docs/backend/relation-manager.md @@ -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. - 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. +- 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. ## Relation managers