Member Email Validation for Linked Members closes #397 #399

Merged
moritz merged 7 commits from feature/397_emailsync_permission into main 2026-02-03 16:35:41 +01:00
2 changed files with 9 additions and 7 deletions
Showing only changes of commit 4e6b7305b6 - Show all commits

View file

@ -4,7 +4,7 @@
2. **DB constraints** - Prevent duplicates within same table (users.email, members.email)
3. **Custom validations** - Prevent cross-table conflicts only for linked entities
4. **Sync is bidirectional**: User ↔ Member (but User always wins on link)
5. **Linked member email change** - When a member is linked, only administrators or the linked user may change that member's email (Member resource validation `EmailChangePermission`). This keeps email sync under control and prevents non-admins from changing another user's linked member email.
5. **Linked member email change** - When a member is linked, only administrators or the linked user may change that member's email (Member resource validation `EmailChangePermission`). Because User.email wins on link and changes sync Member → User, allowing anyone to change a linked member's email would overwrite that user's account email; this rule keeps sync under control.
---

View file

@ -3,13 +3,15 @@ defmodule Mv.EmailSync.Loader do
Helper functions for loading linked records in email synchronization.
Centralizes the logic for retrieving related User/Member entities.
## Authorization
## Authorization-independent link checks
This module runs systemically and uses the system actor for all operations.
This ensures that email synchronization always works, regardless of user permissions.
All functions use `Mv.Helpers.SystemActor.get_system_actor/0` to bypass
user permission checks, as email sync is a mandatory side effect.
All functions use the **system actor** for the load. Link existence
(linked vs not linked) is therefore determined **independently of the
current request actor**. This is required so that validations (e.g.
`EmailChangePermission`, `EmailNotUsedByOtherUser`) can correctly decide
"member is linked" even when the current user would not have read permission
on the related User. Using the request actor would otherwise allow
treating a linked member as unlinked and bypass the permission rule.
"""
alias Mv.Helpers
alias Mv.Helpers.SystemActor