diff --git a/docs/page-permission-route-coverage.md b/docs/page-permission-route-coverage.md index 7eb9a6d..9151a44 100644 --- a/docs/page-permission-route-coverage.md +++ b/docs/page-permission-route-coverage.md @@ -10,13 +10,13 @@ This document lists all protected routes, which permission set may access them, | `/members` | ✗ | ✓ | ✓ | ✓ | | `/members/new` | ✗ | ✗ | ✓ | ✓ | | `/members/:id` | ✓ (linked only) | ✓ | ✓ | ✓ | -| `/members/:id/edit` | ✗ | ✗ | ✓ | ✓ | -| `/members/:id/show/edit` | ✗ | ✗ | ✓ | ✓ | +| `/members/:id/edit` | ✓ (linked only) | ✗ | ✓ | ✓ | +| `/members/:id/show/edit` | ✓ (linked only) | ✗ | ✓ | ✓ | | `/users` | ✗ | ✗ | ✗ | ✓ | | `/users/new` | ✗ | ✗ | ✗ | ✓ | -| `/users/:id` | ✓ (own only) | ✗ | ✗ | ✓ | -| `/users/:id/edit` | ✗ | ✗ | ✗ | ✓ | -| `/users/:id/show/edit` | ✗ | ✗ | ✗ | ✓ | +| `/users/:id` | ✓ (own only) | ✓ (own only) | ✓ (own only) | ✓ | +| `/users/:id/edit` | ✓ (own only) | ✓ (own only) | ✓ (own only) | ✓ | +| `/users/:id/show/edit` | ✓ (own only) | ✓ (own only) | ✓ (own only) | ✓ | | `/settings` | ✗ | ✗ | ✗ | ✓ | | `/membership_fee_settings` | ✗ | ✗ | ✗ | ✓ | | `/membership_fee_types` | ✗ | ✗ | ✗ | ✓ | @@ -69,13 +69,13 @@ All protected routes above are either covered by integration “denied” tests ### Integration tests (full router, read_only = Vorstand/Buchhaltung) -**Allowed (200):** `/`, `/members`, `/members/:id`, `/groups`, `/groups/:slug`. +**Allowed (200):** `/`, `/members`, `/members/:id`, `/users/:id` (own profile), `/users/:id/edit`, `/users/:id/show/edit`, `/groups`, `/groups/:slug`. -**Denied (302 → `/users/:id`):** `/members/new`, `/members/:id/edit`, `/users`, `/users/new`, `/settings`, `/membership_fee_settings`, `/membership_fee_types`, `/groups/new`, `/groups/:slug/edit`, `/admin/roles`, `/admin/roles/:id`. +**Denied (302 → `/users/:id`):** `/members/new`, `/members/:id/edit`, `/members/:id/show/edit`, `/users`, `/users/new`, `/users/:id` (other user), `/settings`, `/membership_fee_settings`, `/membership_fee_types`, `/groups/new`, `/groups/:slug/edit`, `/admin/roles`, `/admin/roles/:id`. ### Integration tests (full router, normal_user = Kassenwart) -**Allowed (200):** `/`, `/members`, `/members/new`, `/members/:id`, `/members/:id/edit`, `/groups`, `/groups/:slug`. +**Allowed (200):** `/`, `/members`, `/members/new`, `/members/:id`, `/members/:id/edit`, `/members/:id/show/edit`, `/users/:id` (own profile), `/users/:id/edit`, `/users/:id/show/edit`, `/groups`, `/groups/:slug`. **Denied (302 → `/users/:id`):** `/users`, `/users/new`, `/users/:id` (other user), `/settings`, `/membership_fee_settings`, `/membership_fee_types`, `/groups/new`, `/groups/:slug/edit`, `/admin/roles`, `/admin/roles/:id`. @@ -86,3 +86,7 @@ All protected routes above are either covered by integration “denied” tests ## Plug behaviour: reserved segments The plug treats `"new"` as a reserved path segment so that patterns like `/members/:id` and `/groups/:slug` do not match `/members/new` or `/groups/new`. Thus `/groups/new` is only allowed when the permission set explicitly lists `/groups/new` (currently only admin). + +## Role and member_id loading + +The plug may reload the user's role (and optionally `member_id`) before checking page permission. Session/`load_from_session` can leave the role unloaded; the plug uses `Mv.Authorization.Actor.ensure_loaded/1` (and, when needed, loads `member_id`) so that permission checks always have the required data. No change to session loading is required; this is documented for clarity.