Docs: note User-Member Linking enforcement in code
Some checks reported errors
continuous-integration/drone/push Build was killed
continuous-integration/drone/promote/production Build is failing

- update_user restricted via ActorIsAdmin; Form gates Member-Linking UI
This commit is contained in:
Moritz 2026-01-30 11:13:41 +01:00
parent cf6bd4a6a1
commit 6e13a3aa34
Signed by: moritz
GPG key ID: 1020A035E5DD0824
3 changed files with 3 additions and 4 deletions

View file

@ -2002,6 +2002,8 @@ Users and Members are separate entities that can be linked. Special rules:
- A user cannot link themselves to an existing member - A user cannot link themselves to an existing member
- A user CAN create a new member and be directly linked to it (self-service) - A user CAN create a new member and be directly linked to it (self-service)
**Enforcement:** 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.
### Approach: Separate Ash Actions ### Approach: Separate Ash Actions
We use **different Ash actions** to enforce different policies: We use **different Ash actions** to enforce different policies:

View file

@ -120,7 +120,6 @@ defmodule Mv.Authorization.PermissionSets do
pages: [ pages: [
# No "/" - Mitglied must not see member index at root (same content as /members). # No "/" - Mitglied must not see member index at root (same content as /members).
# Own profile (sidebar links to /users/:id) and own user edit # Own profile (sidebar links to /users/:id) and own user edit
"/profile",
"/users/:id", "/users/:id",
"/users/:id/edit", "/users/:id/edit",
"/users/:id/show/edit", "/users/:id/show/edit",
@ -156,7 +155,6 @@ defmodule Mv.Authorization.PermissionSets do
pages: [ pages: [
"/", "/",
# Own profile (sidebar links to /users/:id; redirect target must be allowed) # Own profile (sidebar links to /users/:id; redirect target must be allowed)
"/profile",
"/users/:id", "/users/:id",
"/users/:id/edit", "/users/:id/edit",
"/users/:id/show/edit", "/users/:id/show/edit",
@ -206,7 +204,6 @@ defmodule Mv.Authorization.PermissionSets do
pages: [ pages: [
"/", "/",
# Own profile (sidebar links to /users/:id; redirect target must be allowed) # Own profile (sidebar links to /users/:id; redirect target must be allowed)
"/profile",
"/users/:id", "/users/:id",
"/users/:id/edit", "/users/:id/edit",
"/users/:id/show/edit", "/users/:id/show/edit",

View file

@ -95,7 +95,7 @@ defmodule MvWeb.UserLive.Form do
</ul> </ul>
</div> </div>
<%= if @user do %> <%= if @user && @can_manage_member_linking do %>
<div class="p-3 mt-3 border border-orange-200 rounded bg-orange-50"> <div class="p-3 mt-3 border border-orange-200 rounded bg-orange-50">
<p class="text-sm text-orange-800"> <p class="text-sm text-orange-800">
<strong>{gettext("Admin Note")}:</strong> {gettext( <strong>{gettext("Admin Note")}:</strong> {gettext(