Seed Data - Roles and Default Assignment closes #365 #368

Merged
moritz merged 16 commits from feature/365_seed_roles into main 2026-01-25 17:21:04 +01:00
2 changed files with 84 additions and 0 deletions
Showing only changes of commit 3b5b5044fb - Show all commits

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).