From c035d0f141ecd26e77c462f2c3a7905b063b681d Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 4 Feb 2026 09:20:26 +0100 Subject: [PATCH] Docs: groups and roles/permissions architecture, Group moduledoc - groups-architecture: normal_user and admin can manage groups. - roles-and-permissions: matrix and MembershipFeeCycle :linked for own_data. - group_policies_test: update moduledoc. --- docs/groups-architecture.md | 8 ++++---- docs/roles-and-permissions-architecture.md | 15 ++++++++------- test/mv/membership/group_policies_test.exs | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/groups-architecture.md b/docs/groups-architecture.md index 344d582..735898c 100644 --- a/docs/groups-architecture.md +++ b/docs/groups-architecture.md @@ -420,9 +420,9 @@ lib/ **Actions:** - `read` - View groups (all permission sets) -- `create` - Create groups (admin only) -- `update` - Edit groups (admin only) -- `destroy` - Delete groups (admin only) +- `create` - Create groups (normal_user and admin) +- `update` - Edit groups (normal_user and admin) +- `destroy` - Delete groups (normal_user and admin) **Scopes:** - `:all` - All groups (for all permission sets that have read access) @@ -444,7 +444,7 @@ lib/ **Own Data Permission Set:** - `read` action on `Group` resource with `:all` scope - granted -**Note:** All permission sets use `:all` scope for groups. Groups are considered public information that all users with member read permission can view. Only admins can manage (create/update/destroy) groups. +**Note:** All permission sets use `:all` scope for groups. Groups are considered public information that all users with member read permission can view. normal_user and admin can manage (create/update/destroy) groups. ### Member-Group Association Permissions diff --git a/docs/roles-and-permissions-architecture.md b/docs/roles-and-permissions-architecture.md index 461f5ec..92ad3c5 100644 --- a/docs/roles-and-permissions-architecture.md +++ b/docs/roles-and-permissions-architecture.md @@ -97,10 +97,10 @@ Control CRUD operations on: - CustomFieldValue (custom field values) - CustomField (custom field definitions) - Role (role management) -- Group (group definitions; read all, create/update/destroy admin only) +- Group (group definitions; read all, create/update/destroy normal_user and admin) - MemberGroup (member–group associations; own_data read :linked, read_only read :all, normal_user/admin create/destroy) - MembershipFeeType (fee type definitions; all read, admin-only create/update/destroy) -- MembershipFeeCycle (fee cycles; all read, normal_user/admin read+create+update+destroy; manual "Regenerate Cycles" for normal_user and admin) +- MembershipFeeCycle (fee cycles; own_data read :linked, read_only read :all, normal_user/admin read+create+update+destroy; manual "Regenerate Cycles" for normal_user and admin) **4. Page-Level Permissions** @@ -691,11 +691,12 @@ Quick reference table showing what each permission set allows: | **CustomFieldValue** (all) | - | R | R, C, U, D | R, C, U, D | | **CustomField** (all) | R | R | R | R, C, U, D | | **Role** (all) | - | - | - | R, C, U, D | -| **Group** (all) | R | R | R | R, C, U, D | +| **Group** (all) | R | R | R, C, U, D | R, C, U, D | | **MemberGroup** (linked) | R | - | - | - | | **MemberGroup** (all) | - | R | R, C, D | R, C, D | | **MembershipFeeType** (all) | R | R | R | R, C, U, D | -| **MembershipFeeCycle** (all) | R | R | R, C, U, D | R, C, U, D | +| **MembershipFeeCycle** (linked) | R | - | - | - | +| **MembershipFeeCycle** (all) | - | R | R, C, U, D | R, C, U, D | **Legend:** R=Read, C=Create, U=Update, D=Destroy @@ -1217,13 +1218,13 @@ Only admins can change a user's role. The `update_user` action accepts `role_id` **Location:** `lib/membership/group.ex` -Policies use `HasPermission` for read/create/update/destroy. All permission sets can read; only admin can create, update, destroy. No bypass (scope :all only in PermissionSets). +Policies use `HasPermission` for read/create/update/destroy. All permission sets can read; normal_user and admin can create, update, destroy. No bypass (scope :all only in PermissionSets). ### MemberGroup Resource Policies **Location:** `lib/membership/member_group.ex` -Bypass for read with `expr(member_id == ^actor(:member_id))` (own_data list); HasPermission for read (read_only/normal_user/admin :all) and create/destroy (normal_user + admin only). HasPermission applies `:linked` scope for MemberGroup (see HasPermission apply_scope). +Bypass for read restricted to own_data (MemberGroupReadLinkedForOwnData check: own_data only, filter `member_id == actor.member_id`); HasPermission for read (read_only/normal_user/admin :all) and create/destroy (normal_user + admin only). Admin with member_id set still gets :all from HasPermission (bypass does not apply). ### MembershipFeeType Resource Policies @@ -1235,7 +1236,7 @@ Policies use `HasPermission` for read/create/update/destroy. All permission sets **Location:** `lib/membership_fees/membership_fee_cycle.ex` -Policies use `HasPermission` for read/create/update/destroy. All can read; read_only cannot update/create/destroy; normal_user and admin can read, create, update, and destroy (including mark_as_paid and manual "Regenerate Cycles" in the member detail view; UI button is shown when `can_create_cycle`). +Bypass for read restricted to own_data (MembershipFeeCycleReadLinkedForOwnData: own_data only, filter `member_id == actor.member_id`); HasPermission for read (read_only/normal_user/admin :all) and create/update/destroy. own_data can only read cycles of the linked member; read_only can read all; normal_user and admin can read, create, update, and destroy (including mark_as_paid and manual "Regenerate Cycles"; UI button when `can_create_cycle`). Regenerate-cycles handler enforces `can?(:create, MembershipFeeCycle)` server-side. --- diff --git a/test/mv/membership/group_policies_test.exs b/test/mv/membership/group_policies_test.exs index 4686524..27287ff 100644 --- a/test/mv/membership/group_policies_test.exs +++ b/test/mv/membership/group_policies_test.exs @@ -3,7 +3,7 @@ defmodule Mv.Membership.GroupPoliciesTest do Tests for Group resource authorization policies. Verifies that own_data, read_only, normal_user can read groups; - only admin can create, update, and destroy groups. + normal_user and admin can create, update, and destroy groups. """ use Mv.DataCase, async: false