Add test support for default role assignment

This commit is contained in:
Moritz 2026-01-24 19:13:15 +01:00 committed by Simon
parent cea68638e6
commit d77eb4d55e
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2
2 changed files with 84 additions and 0 deletions

View file

@ -16,6 +16,8 @@ defmodule Mv.DataCase do
use ExUnit.CaseTemplate
require Ash.Query
using do
quote do
alias Mv.Repo
@ -29,6 +31,8 @@ defmodule Mv.DataCase do
setup tags do
Mv.DataCase.setup_sandbox(tags)
# Ensure "Mitglied" role exists for AssignDefaultRole to work in tests
Mv.DataCase.ensure_default_role()
:ok
end
@ -42,6 +46,36 @@ defmodule Mv.DataCase do
pid
end
@doc """
Ensures the default "Mitglied" role exists in the test database.
This is necessary because AssignDefaultRole expects this role to exist.
Tests run in sandbox mode, so the role needs to be created for each test.
"""
def ensure_default_role do
# Check if "Mitglied" role already exists
case Mv.Authorization.Role.get_mitglied_role() do
{:ok, nil} ->
# Create the role if it doesn't exist
Mv.Authorization.Role
|> Ash.Changeset.for_create(:create_role_with_system_flag, %{
name: "Mitglied",
description: "Default member role with access to own data only",
permission_set_name: "own_data",
is_system_role: true
})
|> Ash.create!(authorize?: false, domain: Mv.Authorization)
{:ok, _role} ->
# Role already exists, do nothing
:ok
{:error, _error} ->
# Ignore errors (e.g., in tests that don't need roles)
:ok
end
end
@doc """
A helper that transforms changeset errors into a map of messages.

View file

@ -182,6 +182,56 @@ defmodule Mv.Fixtures do
user_with_role
end
@doc """
Creates a user with password authentication and a specific role.
This is useful for tests that need to use password-based registration
but also require the user to have a role for authorization.
## Parameters
- `email` - User email (defaults to unique generated email)
- `password` - User password (defaults to "testpassword123")
- `permission_set_name` - The permission set name (defaults to "own_data")
## Returns
- User struct with role preloaded
## Examples
iex> user = password_user_with_role_fixture()
iex> user.role.permission_set_name
"own_data"
"""
def password_user_with_role_fixture(opts \\ %{}) do
email = Map.get(opts, :email, "user#{System.unique_integer([:positive])}@example.com")
password = Map.get(opts, :password, "testpassword123")
permission_set_name = Map.get(opts, :permission_set_name, "own_data")
# Create role with permission set
role = role_fixture(permission_set_name)
# Create user with password (without password_confirmation as it's optional)
{:ok, user} =
Mv.Accounts.User
|> Ash.Changeset.for_create(:register_with_password, %{
email: email,
password: password
})
|> Ash.create()
# Assign role to user
{:ok, user} =
user
|> Ash.Changeset.for_update(:update, %{})
|> Ash.Changeset.manage_relationship(:role, role, type: :append_and_remove)
|> Ash.update()
# Reload user with role preloaded
{:ok, user_with_role} = Ash.load(user, :role, domain: Mv.Accounts)
user_with_role
end
@doc """
Creates a member with an actor (for use in tests with policies).