mitgliederverwaltung/docs/page-permission-route-coverage.md
Moritz f66cd2933a
docs: add page permission route and test coverage
- page-permission-route-coverage.md: route matrix, test coverage per role,
  reserved segments.
2026-01-30 00:00:33 +01:00

4.7 KiB
Raw Blame History

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
/members/:id/show/edit
/users
/users/new
/users/:id ✓ (own only)
/users/:id/edit
/users/:id/show/edit
/settings
/membership_fee_settings
/membership_fee_types
/membership_fee_types/new
/membership_fee_types/:id/edit
/groups
/groups/new
/groups/:slug
/groups/:slug/edit
/admin/roles
/admin/roles/new
/admin/roles/:id
/admin/roles/:id/edit

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.

Public Paths (no permission check)

  • /auth*, /register, /reset, /sign-in, /sign-out, /confirm*, /password-reset*, /set_locale

Test Coverage

File: test/mv_web/plugs/check_page_permission_test.exs

Unit tests (plug called directly with mock conn)

  • Static: own_data denied /members; read_only allowed /members; flash on denial.
  • Dynamic: read_only allowed /members/123; normal_user allowed /members/456/edit; read_only denied /members/123/edit.
  • read_only / normal_user: denied /admin/roles; read_only denied /members/new.
  • Wildcard: admin allowed /admin/roles, /members/999/edit.
  • Unauthenticated: nil user denied, redirect /sign-in.
  • Public: unauthenticated allowed /auth/sign-in, /register.
  • Error: no role, invalid permission_set_name → denied.

Integration tests (full router, Mitglied = own_data)

Denied (Mitglied gets 302 → /users/:id):

  • /members, /members/new, /users, /users/new, /settings, /membership_fee_settings, /membership_fee_types, /membership_fee_types/new, /groups, /groups/new, /admin/roles, /admin/roles/new
  • /members/:id/edit, /members/:id/show/edit, /users/:id (other user), /users/:id/edit (other), /users/:id/show/edit (other), /membership_fee_types/:id/edit, /groups/:slug, /admin/roles/:id, /admin/roles/:id/edit

Allowed (Mitglied gets 200):

  • /users/:id (own profile), /users/:id/edit, /users/:id/show/edit
  • /members/:id, /members/:id/edit, /members/:id/show/edit for linked member (plug unit tests; full-router tests for linked member skipped: session/LiveView constraints)

Root: GET / redirects Mitglied to profile (root not allowed for own_data).

All protected routes above are either covered by integration “denied” tests for Mitglied or by unit tests for the relevant permission set.

Integration tests (full router, read_only = Vorstand/Buchhaltung)

Allowed (200): /, /members, /members/:id, /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.

Integration tests (full router, normal_user = Kassenwart)

Allowed (200): /, /members, /members/new, /members/:id, /members/:id/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.

Integration tests (full router, admin)

Allowed (200): All protected routes (sample covered: /, /members, /users, /settings, /membership_fee_settings, /admin/roles, /members/:id, /admin/roles/:id, /groups/:slug).

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).