diff --git a/lib/accounts/user.ex b/lib/accounts/user.ex index bc64e39..58cdfde 100644 --- a/lib/accounts/user.ex +++ b/lib/accounts/user.ex @@ -60,14 +60,33 @@ defmodule Mv.Accounts.User do end actions do + # Default actions kept for framework/tooling integration: + # - :create -> Used by AshAdmin's generated "Create" UI and by generic + # AshPhoenix helpers that assume a default create action. + # It does NOT manage the :member relationship. For admin + # flows that may link an existing member, use :create_user. + # - :read -> Standard read used across the app and by admin tooling. + # - :destroy-> Standard delete used by admin tooling and maintenance tasks. defaults [:read, :create, :destroy] + # Primary generic update action: + # - Selected by AshAdmin's generated "Edit" UI and generic AshPhoenix + # helpers that assume a default update action. + # - Intended for simple attribute updates (e.g., :email) and scenarios + # that do NOT need to manage the :member relationship. + # - For linking/unlinking a member (and the related validations), prefer + # the specialized :update_user action below. update :update do primary? true + + # Required because custom validation functions (email validation, member relationship validation) + # cannot be executed atomically. These validations need to query the database and perform + # complex checks that are not supported in atomic operations. require_atomic? false end create :create_user do + description "Creates a new user with optional member relationship. The member relationship is managed through the :member argument." # Only accept email directly - member_id is NOT in accept list # This prevents direct foreign key manipulation, forcing use of manage_relationship accept [:email] @@ -89,12 +108,16 @@ defmodule Mv.Accounts.User do end update :update_user do + description "Updates a user and manages the optional member relationship. To change an existing member link, first remove it (set member to nil), then add the new one." # Only accept email directly - member_id is NOT in accept list # This prevents direct foreign key manipulation, forcing use of manage_relationship accept [:email] # Allow member to be passed as argument for relationship management argument :member, :map, allow_nil?: true - # Required because custom validation function cannot be done atomically + + # Required because custom validation functions (email validation, member relationship validation) + # cannot be executed atomically. These validations need to query the database and perform + # complex checks that are not supported in atomic operations. require_atomic? false # Manage the member relationship during user update diff --git a/lib/mv_web/components/layouts/navbar.ex b/lib/mv_web/components/layouts/navbar.ex index 91caa8e..9fec3f4 100644 --- a/lib/mv_web/components/layouts/navbar.ex +++ b/lib/mv_web/components/layouts/navbar.ex @@ -16,9 +16,8 @@ defmodule MvWeb.Layouts.Navbar do
Mitgliederverwaltung
diff --git a/priv/repo/migrations/20250926164519_member_relation.exs b/priv/repo/migrations/20250926164519_member_relation.exs index daaa24c..1f63f73 100644 --- a/priv/repo/migrations/20250926164519_member_relation.exs +++ b/priv/repo/migrations/20250926164519_member_relation.exs @@ -8,6 +8,8 @@ defmodule Mv.Repo.Migrations.MemberRelation do use Ecto.Migration def up do + # Ensure 1:1 relationship - one user can only be linked to one member + # This prevents multiple users from sharing the same member account create unique_index(:users, [:member_id], name: "users_unique_member_index") end diff --git a/priv/repo/migrations/20250926180341_add_unique_email_to_members.exs b/priv/repo/migrations/20250926180341_add_unique_email_to_members.exs index 51b874f..a33ce2f 100644 --- a/priv/repo/migrations/20250926180341_add_unique_email_to_members.exs +++ b/priv/repo/migrations/20250926180341_add_unique_email_to_members.exs @@ -8,6 +8,8 @@ defmodule Mv.Repo.Migrations.AddUniqueEmailToMembers do use Ecto.Migration def up do + # Ensure email uniqueness across all members + # This supports upsert operations and prevents duplicate member accounts create unique_index(:members, [:email], name: "members_unique_email_index") end diff --git a/test/accounts/user_member_relationship_test.exs b/test/accounts/user_member_relationship_test.exs index 19cbe62..b64f5ec 100644 --- a/test/accounts/user_member_relationship_test.exs +++ b/test/accounts/user_member_relationship_test.exs @@ -1,5 +1,7 @@ defmodule Mv.Accounts.UserMemberRelationshipTest do - use Mv.DataCase, async: false + # Using async: true for faster test execution + # This is safe because all database operations are sandboxed per test + use Mv.DataCase, async: true alias Mv.Accounts alias Mv.Membership