[FEATURE]: Apply UI Authorization to Existing LiveViews #400

Closed
opened 2026-02-03 14:55:03 +01:00 by moritz · 0 comments
Owner

Description:

Update all existing LiveViews (Member, User, and where applicable CustomFieldValue, CustomField) to use authorization helpers for conditional rendering. Use the same pattern as Role and Group LiveViews (which already use can?/3 and can_access_page?/2).

Tasks:

  1. Member LiveViews:

    • Index: Hide "New Member" if user cannot create (can?(@current_user, :create, Mv.Membership.Member)).
    • Index: Hide "Edit" and "Delete" per row if user cannot update/destroy that record (can?(@current_user, :update, member) / can?(@current_user, :destroy, member)).
    • Show: Hide "Edit" button if user cannot update that member (can?(@current_user, :update, @member)).
    • Form: Access remains enforced by page permission plug only.
  2. User LiveViews:

    • Index: Page is admin-only (plug). Hide "New User", "Edit", and "Delete" using can? so UI matches permissions (defense in depth).
    • Show: Hide "Edit" if user cannot update that user (own profile: can?(@current_user, :update, @user); other users: only admin). Page access for own vs. other is already enforced by plug.
    • Edit (Form): Keep existing can? usage for member-linking section; ensure overall edit visibility is consistent with update permission.
  3. CustomFieldValue LiveViews:

    • Note: There are no dedicated /custom_field_values routes in the router yet (see docs/page-permission-route-coverage.md). When CustomFieldValue LiveViews or embedded CustomFieldValue UI exist: hide create/edit/delete based on permissions (same pattern as Member: can? for create, and per-record for update/destroy with scope :linked where applicable).
  4. CustomField LiveViews:

    • Note: No dedicated /custom_fields routes in the router yet. When CustomField LiveViews or embedded CustomField management UI exist: all users can view; only admin can create/edit/delete (can?(@current_user, :create|:update|:destroy, Mv.Membership.CustomField)).
  5. Sidebar (not Navbar):

    • The app uses a Sidebar (lib/mv_web/components/layouts/sidebar.ex), not a classic Navbar. Update it to use authorization helpers:
    • Show "Members" only if user can access the page (can_access_page?(@current_user, "/members")).
    • Show "Fee Types" (membership_fee_types) only if user can access the page (can_access_page?(@current_user, "/membership_fee_types")).
    • Show "Administration" group (and its items) only if user can access at least one admin page (e.g. can_access_page?(@current_user, "/admin/roles") or /users or /groups etc.). Alternatively: show each subitem (Users, Groups, Roles, Fee Settings, Settings) only when can_access_page?(@current_user, "<path>") for that path.
    • Always show "Profile" (already in user menu in sidebar footer).
  6. Test all updated views with all 5 role types (Mitglied, Vorstand, Kassenwart, Buchhaltung, Admin).

Acceptance Criteria:

  • All updated LiveViews use can?/3 (and where relevant can_access_page?/2) for conditional rendering.
  • Buttons/links are hidden when the user lacks the corresponding permission.
  • Sidebar shows only links the user is allowed to access (per page permission).
  • Behaviour is tested with all 5 roles (Mitglied, Vorstand, Kassenwart, Buchhaltung, Admin).
  • UI remains clean (no awkward empty spaces from hidden buttons).

Test Strategy (TDD):

Member Index – Mitglied (own_data):

  • Does not see "New Member" button.
  • Does not see list of all members (empty or filtered by policy).
  • Can only see own linked member when navigated directly (page plug + data policy).

Member Index – Vorstand (read_only):

  • Sees full member list.
  • Does not see "New Member" button.
  • Does not see "Edit" or "Delete" buttons.

Member Index – Kassenwart (normal_user):

  • Sees full member list.
  • Sees "New Member" button.
  • Sees "Edit" for all members.
  • Does not see "Delete" button (not in permission set).

Member Index – Admin:

  • Sees everything (New, Edit, Delete).

User Index / Show:

  • Admin sees User list, New User, Edit, Delete.
  • Non-admin does not reach User index (redirected by plug); if reached, buttons hidden via can?.
  • Show: only own profile or admin sees other users (plug); Edit button only when can?(@current_user, :update, @user).

Sidebar (all roles):

  • Mitglied: Only links they may access (e.g. Profile via user menu; no /members if own_data has no /members in permission set – see page-permission doc).
  • Vorstand: Members (read), Fee Types if in permission set, Profile; no Administration if no admin pages allowed.
  • Kassenwart: Members, Fee Types, Profile; Administration items only if allowed (e.g. no /users, no /admin/roles).
  • Buchhaltung: Same idea as Vorstand (read-only members, Profile, no admin actions).
  • Admin: All sidebar links (Members, Fee Types, Administration with Users, Groups, Roles, Fee Settings, Settings), Profile.

Note: Exact sidebar entries depend on current router and permission sets (e.g. no "Properties" in current sidebar; add/align names if routes change).

CustomFieldValue / CustomField (when UI exists):

  • When dedicated or embedded CustomFieldValue/CustomField UI is present: same pattern – create/edit/delete only when can? allows; view when read is allowed.

Test Files:

  • test/mv_web/live/member_live_authorization_test.exs
  • test/mv_web/live/user_live_authorization_test.exs
  • test/mv_web/live/custom_field_value_live_authorization_test.exs (when CustomFieldValue LiveViews/routes exist)
  • test/mv_web/live/custom_field_live_authorization_test.exs (when CustomField LiveViews/routes exist)
  • test/mv_web/components/sidebar_authorization_test.exs (Sidebar, not Navbar)
**Description:** Update all existing LiveViews (Member, User, and where applicable CustomFieldValue, CustomField) to use authorization helpers for conditional rendering. Use the same pattern as Role and Group LiveViews (which already use `can?/3` and `can_access_page?/2`). **Tasks:** 1. **Member LiveViews:** - Index: Hide "New Member" if user cannot create (`can?(@current_user, :create, Mv.Membership.Member)`). - Index: Hide "Edit" and "Delete" per row if user cannot update/destroy that record (`can?(@current_user, :update, member)` / `can?(@current_user, :destroy, member)`). - Show: Hide "Edit" button if user cannot update that member (`can?(@current_user, :update, @member)`). - Form: Access remains enforced by page permission plug only. 2. **User LiveViews:** - Index: Page is admin-only (plug). Hide "New User", "Edit", and "Delete" using `can?` so UI matches permissions (defense in depth). - Show: Hide "Edit" if user cannot update that user (own profile: `can?(@current_user, :update, @user)`; other users: only admin). Page access for own vs. other is already enforced by plug. - Edit (Form): Keep existing `can?` usage for member-linking section; ensure overall edit visibility is consistent with update permission. 3. **CustomFieldValue LiveViews:** - *Note: There are no dedicated `/custom_field_values` routes in the router yet (see `docs/page-permission-route-coverage.md`).* When CustomFieldValue LiveViews or embedded CustomFieldValue UI exist: hide create/edit/delete based on permissions (same pattern as Member: `can?` for create, and per-record for update/destroy with scope :linked where applicable). 4. **CustomField LiveViews:** - *Note: No dedicated `/custom_fields` routes in the router yet.* When CustomField LiveViews or embedded CustomField management UI exist: all users can view; only admin can create/edit/delete (`can?(@current_user, :create|:update|:destroy, Mv.Membership.CustomField)`). 5. **Sidebar (not Navbar):** - The app uses a Sidebar (`lib/mv_web/components/layouts/sidebar.ex`), not a classic Navbar. Update it to use authorization helpers: - Show "Members" only if user can access the page (`can_access_page?(@current_user, "/members")`). - Show "Fee Types" (membership_fee_types) only if user can access the page (`can_access_page?(@current_user, "/membership_fee_types")`). - Show "Administration" group (and its items) only if user can access at least one admin page (e.g. `can_access_page?(@current_user, "/admin/roles")` or `/users` or `/groups` etc.). Alternatively: show each subitem (Users, Groups, Roles, Fee Settings, Settings) only when `can_access_page?(@current_user, "<path>")` for that path. - Always show "Profile" (already in user menu in sidebar footer). 6. Test all updated views with all 5 role types (Mitglied, Vorstand, Kassenwart, Buchhaltung, Admin). **Acceptance Criteria:** - [ ] All updated LiveViews use `can?/3` (and where relevant `can_access_page?/2`) for conditional rendering. - [ ] Buttons/links are hidden when the user lacks the corresponding permission. - [ ] Sidebar shows only links the user is allowed to access (per page permission). - [ ] Behaviour is tested with all 5 roles (Mitglied, Vorstand, Kassenwart, Buchhaltung, Admin). - [ ] UI remains clean (no awkward empty spaces from hidden buttons). **Test Strategy (TDD):** **Member Index – Mitglied (own_data):** - Does not see "New Member" button. - Does not see list of all members (empty or filtered by policy). - Can only see own linked member when navigated directly (page plug + data policy). **Member Index – Vorstand (read_only):** - Sees full member list. - Does not see "New Member" button. - Does not see "Edit" or "Delete" buttons. **Member Index – Kassenwart (normal_user):** - Sees full member list. - Sees "New Member" button. - Sees "Edit" for all members. - Does not see "Delete" button (not in permission set). **Member Index – Admin:** - Sees everything (New, Edit, Delete). **User Index / Show:** - Admin sees User list, New User, Edit, Delete. - Non-admin does not reach User index (redirected by plug); if reached, buttons hidden via `can?`. - Show: only own profile or admin sees other users (plug); Edit button only when `can?(@current_user, :update, @user)`. **Sidebar (all roles):** - Mitglied: Only links they may access (e.g. Profile via user menu; no /members if own_data has no /members in permission set – see page-permission doc). - Vorstand: Members (read), Fee Types if in permission set, Profile; no Administration if no admin pages allowed. - Kassenwart: Members, Fee Types, Profile; Administration items only if allowed (e.g. no /users, no /admin/roles). - Buchhaltung: Same idea as Vorstand (read-only members, Profile, no admin actions). - Admin: All sidebar links (Members, Fee Types, Administration with Users, Groups, Roles, Fee Settings, Settings), Profile. *Note: Exact sidebar entries depend on current router and permission sets (e.g. no "Properties" in current sidebar; add/align names if routes change).* **CustomFieldValue / CustomField (when UI exists):** - When dedicated or embedded CustomFieldValue/CustomField UI is present: same pattern – create/edit/delete only when `can?` allows; view when read is allowed. **Test Files:** - `test/mv_web/live/member_live_authorization_test.exs` - `test/mv_web/live/user_live_authorization_test.exs` - `test/mv_web/live/custom_field_value_live_authorization_test.exs` (when CustomFieldValue LiveViews/routes exist) - `test/mv_web/live/custom_field_live_authorization_test.exs` (when CustomField LiveViews/routes exist) - `test/mv_web/components/sidebar_authorization_test.exs` (Sidebar, not Navbar)
moritz added this to the Accounts & Logins milestone 2026-02-03 14:55:03 +01:00
moritz self-assigned this 2026-02-03 14:55:03 +01:00
moritz added this to the Sprint 12: 29.01.- 19.02 project 2026-02-03 14:55:03 +01:00
moritz modified the milestone from Accounts & Logins to We have different roles and permissions 2026-02-03 16:38:20 +01:00
Sign in to join this conversation.
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: local-it/mitgliederverwaltung#400
No description provided.