69 lines
5 KiB
Markdown
69 lines
5 KiB
Markdown
# Page Permission – Route and Test Coverage
|
||
|
||
This document lists all protected routes, which permission set may access them, and how they are covered by tests.
|
||
|
||
## Protected Routes (Router scope with CheckPagePermission in :browser)
|
||
|
||
| Route | own_data | read_only | normal_user | admin |
|
||
|-------|----------|-----------|-------------|-------|
|
||
| `/` | ✗ | ✓ | ✓ | ✓ |
|
||
| `/members` | ✗ | ✓ | ✓ | ✓ |
|
||
| `/members/new` | ✗ | ✗ | ✓ | ✓ |
|
||
| `/members/:id` | ✓ (linked only) | ✓ | ✓ | ✓ |
|
||
| `/members/:id/edit` | ✓ (linked only) | ✗ | ✓ | ✓ |
|
||
| `/members/:id/show/edit` | ✓ (linked only) | ✗ | ✓ | ✓ |
|
||
| `/users` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/users/new` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/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_settings/new_fee_type` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/membership_fee_settings/:id/edit_fee_type` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/groups` | ✗ | ✓ | ✓ | ✓ |
|
||
| `/groups/new` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/groups/:slug` | ✗ | ✓ | ✓ | ✓ |
|
||
| `/groups/:slug/edit` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/statistics` | ✗ | ✓ | ✓ | ✓ |
|
||
| `/admin/roles` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/admin/roles/new` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/admin/roles/:id` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/admin/roles/:id/edit` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/join_requests` | ✗ | ✗ | ✓ | ✓ |
|
||
| `/join_requests/:id` | ✗ | ✗ | ✓ | ✓ |
|
||
| `/admin/datafields` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/admin/import` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/admin/import/template/en` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/admin/import/template/de` | ✗ | ✗ | ✗ | ✓ |
|
||
| `/members/export.csv` | ✗ | ✓ | ✓ | ✓ |
|
||
| `/members/export.pdf` | ✗ | ✗ | ✗ | ✓ |
|
||
|
||
**Note:** Permission sets define `/custom_field_values` and related paths, but there are no such routes in the router; those entries are for future use. The Approval UI routes `/join_requests` and `/join_requests/:id` are implemented and routed: `normal_user` lists them explicitly in its permission set, and `admin` reaches them through the `*` wildcard.
|
||
|
||
**Note on admin-only routes:** `/admin/datafields`, `/admin/import`, `/admin/import/template/en`, `/admin/import/template/de`, and `/members/export.pdf` are not listed explicitly in any permission set; only `admin` can reach them, via the `*` wildcard. `/members/export.csv` is additionally granted explicitly to `read_only` and `normal_user`.
|
||
|
||
## Public Paths (no permission check)
|
||
|
||
- `/auth*`, `/register`, `/reset`, `/sign-in`, `/sign-out`, `/confirm*`, `/password-reset*`, `/set_locale`, **`/join`**
|
||
|
||
The public join page `GET /join` is explicitly public (Subtask 4); unauthenticated access returns 200 when join form is enabled, 404 when disabled. Unit test: `test/mv_web/plugs/check_page_permission_test.exs` (plug allows /join); integration: `test/mv_web/live/join_live_test.exs`.
|
||
|
||
The join confirmation route `GET /confirm_join/:token` is public (matched by `/confirm*`). Unit tests: `test/mv_web/controllers/join_confirm_controller_test.exs` (stubbed callback, no integration).
|
||
|
||
## Test Coverage
|
||
|
||
**File:** `test/mv_web/plugs/check_page_permission_test.exs` covers both unit tests (plug called directly with a mock conn) and full-router integration tests. The route→permission-set matrix above is the source of truth; each permission set (own_data/Mitglied, read_only, normal_user/Kassenwart, admin) is exercised there. Allowed routes return 200; denied routes return 302 → `/users/:id`. `GET /` redirects own_data to its profile. Unauthenticated access is denied and redirected to `/sign-in`; public paths (`/auth/sign-in`, `/register`) are allowed. Error cases (no role, invalid permission_set_name) deny.
|
||
|
||
Two coverage notes:
|
||
|
||
- **Linked-member routes** (`/members/:id*` for own_data) are covered by plug unit tests; full-router integration tests for the linked member are skipped due to session/LiveView constraints.
|
||
- **Join requests:** normal_user and admin are allowed `/join_requests` and `/join_requests/:id` (normal_user via its explicit permission-set pages, admin via the `*` wildcard); read_only and own_data are denied.
|
||
|
||
## 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.
|