Fix unlink-by-omission: on_missing :ignore, test, doc, string-key
Some checks failed
continuous-integration/drone/push Build is failing

- Member update_member: on_missing :unrelate → :ignore (no unlink when :user omitted)
- Test: normal_user update linked member without :user keeps link
- Doc: unlink only explicit (user: nil), admin-only; Actor.admin?(nil) note
- Check: defense-in-depth for "user" string key
This commit is contained in:
Moritz 2026-02-04 14:06:36 +01:00
parent 543fded102
commit 5194b20b5c
Signed by: moritz
GPG key ID: 1020A035E5DD0824
4 changed files with 46 additions and 19 deletions

View file

@ -2052,7 +2052,7 @@ Users and Members are separate entities that can be linked. Special rules:
**Enforcement:**
- **User side:** The User resource restricts the `update_user` action (which accepts the `member` argument for link/unlink) to admins only via `Mv.Authorization.Checks.ActorIsAdmin`. The UserLive.Form shows the Member-Linking UI and runs member link/unlink on save only when the current user is admin; non-admins use the `:update` action (email only) for profile edit.
- **Member side:** Only admins may set or change the usermember link on **Member** create or update. When creating or updating a member, the `:user` argument (which links the member to a user account) is forbidden for non-admins. This is enforced by `Mv.Authorization.Checks.ForbidMemberUserLinkUnlessAdmin` in the Member resource policies (`forbid_if` before `authorize_if HasPermission`). Non-admins (e.g. normal_user / Kassenwart) can still create and update members as long as they do not pass the `:user` argument.
- **Member side:** Only admins may set or change the usermember link on **Member** create or update. When creating or updating a member, the `:user` argument (which links the member to a user account) is forbidden for non-admins. This is enforced by `Mv.Authorization.Checks.ForbidMemberUserLinkUnlessAdmin` in the Member resource policies (`forbid_if` before `authorize_if HasPermission`). Non-admins can still create and update members as long as they do **not** pass the `:user` argument. The Member resource uses **`on_missing: :ignore`** for the `:user` relationship on update_member, so **omitting** `:user` from params does **not** change the link (no "unlink by omission"); unlink is only possible by explicitly passing `:user` (e.g. `user: nil`), which is admin-only.
### Approach: Separate Ash Actions