Complete Permissions for Groups, Membership Fees, and User Role Assignment closes #404 #405

Merged
moritz merged 26 commits from feature/404_permission_completeness into main 2026-02-04 11:47:19 +01:00
Showing only changes of commit e799f0271c - Show all commits

View file

@ -58,10 +58,19 @@ defmodule Mv.Authorization.PermissionSets do
pages: [String.t()] pages: [String.t()]
} }
# DRY helpers for shared resource permission lists (used in own_data, read_only, normal_user) # DRY helpers for shared resource permission lists (used in own_data, read_only, normal_user, admin)
defp perm(resource, action, scope), defp perm(resource, action, scope),
do: %{resource: resource, action: action, scope: scope, granted: true} do: %{resource: resource, action: action, scope: scope, granted: true}
# All four CRUD actions for a resource with scope :all (used for admin)
defp perm_all(resource),
do: [
perm(resource, :read, :all),
perm(resource, :create, :all),
perm(resource, :update, :all),
perm(resource, :destroy, :all)
]
# User: read/update own credentials only (all non-admin sets allow password changes) # User: read/update own credentials only (all non-admin sets allow password changes)
defp user_own_credentials, do: [perm("User", :read, :own), perm("User", :update, :own)] defp user_own_credentials, do: [perm("User", :read, :own), perm("User", :update, :own)]
@ -234,61 +243,24 @@ defmodule Mv.Authorization.PermissionSets do
end end
def get_permissions(:admin) do def get_permissions(:admin) do
# MemberGroup has no :update action in the domain; use read/create/destroy only
member_group_perms = [
perm("MemberGroup", :read, :all),
perm("MemberGroup", :create, :all),
perm("MemberGroup", :destroy, :all)
]
%{ %{
resources: [ resources:
# User: Full management including other users perm_all("User") ++
%{resource: "User", action: :read, scope: :all, granted: true}, perm_all("Member") ++
%{resource: "User", action: :create, scope: :all, granted: true}, perm_all("CustomFieldValue") ++
%{resource: "User", action: :update, scope: :all, granted: true}, perm_all("CustomField") ++
%{resource: "User", action: :destroy, scope: :all, granted: true}, perm_all("Role") ++
perm_all("Group") ++
# Member: Full CRUD member_group_perms ++
%{resource: "Member", action: :read, scope: :all, granted: true}, perm_all("MembershipFeeType") ++
%{resource: "Member", action: :create, scope: :all, granted: true}, perm_all("MembershipFeeCycle"),
%{resource: "Member", action: :update, scope: :all, granted: true},
%{resource: "Member", action: :destroy, scope: :all, granted: true},
# CustomFieldValue: Full CRUD
%{resource: "CustomFieldValue", action: :read, scope: :all, granted: true},
%{resource: "CustomFieldValue", action: :create, scope: :all, granted: true},
%{resource: "CustomFieldValue", action: :update, scope: :all, granted: true},
%{resource: "CustomFieldValue", action: :destroy, scope: :all, granted: true},
# CustomField: Full CRUD (admin manages custom field definitions)
%{resource: "CustomField", action: :read, scope: :all, granted: true},
%{resource: "CustomField", action: :create, scope: :all, granted: true},
%{resource: "CustomField", action: :update, scope: :all, granted: true},
%{resource: "CustomField", action: :destroy, scope: :all, granted: true},
# Role: Full CRUD (admin manages roles)
%{resource: "Role", action: :read, scope: :all, granted: true},
%{resource: "Role", action: :create, scope: :all, granted: true},
%{resource: "Role", action: :update, scope: :all, granted: true},
%{resource: "Role", action: :destroy, scope: :all, granted: true},
# Group: Full CRUD (admin manages groups)
%{resource: "Group", action: :read, scope: :all, granted: true},
%{resource: "Group", action: :create, scope: :all, granted: true},
%{resource: "Group", action: :update, scope: :all, granted: true},
%{resource: "Group", action: :destroy, scope: :all, granted: true},
# MemberGroup: Full CRUD
%{resource: "MemberGroup", action: :read, scope: :all, granted: true},
%{resource: "MemberGroup", action: :create, scope: :all, granted: true},
%{resource: "MemberGroup", action: :destroy, scope: :all, granted: true},
# MembershipFeeType: Full CRUD (admin manages fee types)
%{resource: "MembershipFeeType", action: :read, scope: :all, granted: true},
%{resource: "MembershipFeeType", action: :create, scope: :all, granted: true},
%{resource: "MembershipFeeType", action: :update, scope: :all, granted: true},
%{resource: "MembershipFeeType", action: :destroy, scope: :all, granted: true},
# MembershipFeeCycle: Full CRUD
%{resource: "MembershipFeeCycle", action: :read, scope: :all, granted: true},
%{resource: "MembershipFeeCycle", action: :create, scope: :all, granted: true},
%{resource: "MembershipFeeCycle", action: :update, scope: :all, granted: true},
%{resource: "MembershipFeeCycle", action: :destroy, scope: :all, granted: true}
],
pages: [ pages: [
# Explicit admin-only pages (for clarity and future restrictions) # Explicit admin-only pages (for clarity and future restrictions)
"/settings", "/settings",