From e30be4c22817c4d1bf48e35308e2fe052c521186 Mon Sep 17 00:00:00 2001 From: Moritz Date: Sat, 24 Jan 2026 19:13:04 +0100 Subject: [PATCH] Add Role helper function and create_role_with_system_flag action - Add get_mitglied_role/0 helper to avoid code duplication - Add create_role_with_system_flag action for seeds/migrations - Allows setting is_system_role flag (required for 'Mitglied' role) --- lib/mv/authorization/role.ex | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/lib/mv/authorization/role.ex b/lib/mv/authorization/role.ex index da43510..9c33e2d 100644 --- a/lib/mv/authorization/role.ex +++ b/lib/mv/authorization/role.ex @@ -67,6 +67,11 @@ defmodule Mv.Authorization.Role do # Custom validations will still work end + create :create_role_with_system_flag do + description "Internal action to create roles, allowing `is_system_role` to be set. Used by seeds and migrations." + accept [:name, :description, :permission_set_name, :is_system_role] + end + update :update_role do primary? true # is_system_role is intentionally excluded - should only be set via seeds/internal actions @@ -139,4 +144,33 @@ defmodule Mv.Authorization.Role do identities do identity :unique_name, [:name] end + + @doc """ + Loads the "Mitglied" role without authorization (for bootstrap operations). + + This is a helper function to avoid code duplication when loading the default + role in changes, migrations, and test setup. + + ## Returns + + - `{:ok, %Mv.Authorization.Role{}}` - The "Mitglied" role + - `{:ok, nil}` - Role doesn't exist + - `{:error, term()}` - Error during lookup + + ## Examples + + {:ok, mitglied_role} = Mv.Authorization.Role.get_mitglied_role() + # => {:ok, %Mv.Authorization.Role{name: "Mitglied", ...}} + + {:ok, nil} = Mv.Authorization.Role.get_mitglied_role() + # => Role doesn't exist (e.g., in test environment before seeds run) + """ + @spec get_mitglied_role() :: {:ok, t() | nil} | {:error, term()} + def get_mitglied_role do + require Ash.Query + + __MODULE__ + |> Ash.Query.filter(name == "Mitglied") + |> Ash.read_one(authorize?: false, domain: Mv.Authorization) + end end