Fix missing actor parameters and restore AshAuthentication bypass tests
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Moritz 2026-01-24 08:38:33 +01:00
parent 15a7c615d6
commit 71c13d0ac0
Signed by: moritz
GPG key ID: 1020A035E5DD0824
5 changed files with 50 additions and 48 deletions

View file

@ -81,7 +81,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :current_cycle_status) member = Ash.load!(member, :current_cycle_status, actor: actor)
assert member.current_cycle_status == :paid assert member.current_cycle_status == :paid
end end
@ -100,7 +100,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :current_cycle_status) member = Ash.load!(member, :current_cycle_status, actor: actor)
assert member.current_cycle_status == nil assert member.current_cycle_status == nil
end end
@ -108,7 +108,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
fee_type = create_fee_type(%{interval: :yearly}, actor) fee_type = create_fee_type(%{interval: :yearly}, actor)
member = create_member(%{membership_fee_type_id: fee_type.id}, actor) member = create_member(%{membership_fee_type_id: fee_type.id}, actor)
member = Ash.load!(member, :current_cycle_status) member = Ash.load!(member, :current_cycle_status, actor: actor)
assert member.current_cycle_status == nil assert member.current_cycle_status == nil
end end
@ -130,7 +130,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :current_cycle_status) member = Ash.load!(member, :current_cycle_status, actor: actor)
assert member.current_cycle_status == :unpaid assert member.current_cycle_status == :unpaid
end end
end end
@ -176,7 +176,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :last_cycle_status) member = Ash.load!(member, :last_cycle_status, actor: actor)
# Should return status of 2023 (last completed) # Should return status of 2023 (last completed)
assert member.last_cycle_status == :unpaid assert member.last_cycle_status == :unpaid
end end
@ -199,7 +199,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :last_cycle_status) member = Ash.load!(member, :last_cycle_status, actor: actor)
assert member.last_cycle_status == nil assert member.last_cycle_status == nil
end end
@ -207,7 +207,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
fee_type = create_fee_type(%{interval: :yearly}, actor) fee_type = create_fee_type(%{interval: :yearly}, actor)
member = create_member(%{membership_fee_type_id: fee_type.id}, actor) member = create_member(%{membership_fee_type_id: fee_type.id}, actor)
member = Ash.load!(member, :last_cycle_status) member = Ash.load!(member, :last_cycle_status, actor: actor)
assert member.last_cycle_status == nil assert member.last_cycle_status == nil
end end
@ -240,7 +240,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :last_cycle_status) member = Ash.load!(member, :last_cycle_status, actor: actor)
# Should return status of last month (last completed) # Should return status of last month (last completed)
assert member.last_cycle_status == :paid assert member.last_cycle_status == :paid
end end
@ -309,7 +309,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
) )
end end
member = Ash.load!(member, :overdue_count) member = Ash.load!(member, :overdue_count, actor: actor)
# Should only count 2022 (unpaid and ended) # Should only count 2022 (unpaid and ended)
assert member.overdue_count == 1 assert member.overdue_count == 1
end end
@ -329,7 +329,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :overdue_count) member = Ash.load!(member, :overdue_count, actor: actor)
assert member.overdue_count == 0 assert member.overdue_count == 0
end end
@ -337,7 +337,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
fee_type = create_fee_type(%{interval: :yearly}, actor) fee_type = create_fee_type(%{interval: :yearly}, actor)
member = create_member(%{membership_fee_type_id: fee_type.id}, actor) member = create_member(%{membership_fee_type_id: fee_type.id}, actor)
member = Ash.load!(member, :overdue_count) member = Ash.load!(member, :overdue_count, actor: actor)
assert member.overdue_count == 0 assert member.overdue_count == 0
end end
@ -384,7 +384,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :overdue_count) member = Ash.load!(member, :overdue_count, actor: actor)
# Should only count two_months_ago (unpaid and ended) # Should only count two_months_ago (unpaid and ended)
assert member.overdue_count == 1 assert member.overdue_count == 1
end end
@ -424,7 +424,7 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
actor actor
) )
member = Ash.load!(member, :overdue_count) member = Ash.load!(member, :overdue_count, actor: actor)
assert member.overdue_count == 3 assert member.overdue_count == 3
end end
end end
@ -470,7 +470,9 @@ defmodule Mv.Membership.MemberCycleCalculationsTest do
) )
member = member =
Ash.load!(member, [:current_cycle_status, :last_cycle_status, :overdue_count]) Ash.load!(member, [:current_cycle_status, :last_cycle_status, :overdue_count],
actor: actor
)
assert member.current_cycle_status == :unpaid assert member.current_cycle_status == :unpaid
assert member.last_cycle_status == :paid assert member.last_cycle_status == :paid

View file

@ -120,7 +120,7 @@ defmodule Mv.Membership.MemberTypeChangeIntegrationTest do
|> Ash.Query.filter(member_id == ^member.id and cycle_start == ^current_cycle_start) |> Ash.Query.filter(member_id == ^member.id and cycle_start == ^current_cycle_start)
|> Ash.read_one(actor: actor) do |> Ash.read_one(actor: actor) do
{:ok, existing_cycle} when not is_nil(existing_cycle) -> {:ok, existing_cycle} when not is_nil(existing_cycle) ->
Ash.destroy!(existing_cycle) Ash.destroy!(existing_cycle, actor: actor)
_ -> _ ->
:ok :ok
@ -313,7 +313,7 @@ defmodule Mv.Membership.MemberTypeChangeIntegrationTest do
|> Ash.Query.filter(member_id == ^member.id and cycle_start == ^past_cycle_start) |> Ash.Query.filter(member_id == ^member.id and cycle_start == ^past_cycle_start)
|> Ash.read_one(actor: actor) do |> Ash.read_one(actor: actor) do
{:ok, existing_cycle} when not is_nil(existing_cycle) -> {:ok, existing_cycle} when not is_nil(existing_cycle) ->
Ash.destroy!(existing_cycle) Ash.destroy!(existing_cycle, actor: actor)
_ -> _ ->
:ok :ok
@ -337,7 +337,7 @@ defmodule Mv.Membership.MemberTypeChangeIntegrationTest do
|> Ash.Query.filter(member_id == ^member.id and cycle_start == ^current_cycle_start) |> Ash.Query.filter(member_id == ^member.id and cycle_start == ^current_cycle_start)
|> Ash.read_one(actor: actor) do |> Ash.read_one(actor: actor) do
{:ok, existing_cycle} when not is_nil(existing_cycle) -> {:ok, existing_cycle} when not is_nil(existing_cycle) ->
Ash.destroy!(existing_cycle) Ash.destroy!(existing_cycle, actor: actor)
_ -> _ ->
:ok :ok
@ -426,7 +426,7 @@ defmodule Mv.Membership.MemberTypeChangeIntegrationTest do
Enum.each(existing_cycles, fn cycle -> Enum.each(existing_cycles, fn cycle ->
if cycle.cycle_start != current_cycle_start do if cycle.cycle_start != current_cycle_start do
Ash.destroy!(cycle) Ash.destroy!(cycle, actor: actor)
end end
end) end)

View file

@ -190,27 +190,27 @@ defmodule Mv.MembershipFees.MembershipFeeCycleTest do
# unpaid -> paid # unpaid -> paid
cycle1 = create_cycle(member, fee_type, %{status: :unpaid}, actor) cycle1 = create_cycle(member, fee_type, %{status: :unpaid}, actor)
assert {:ok, c1} = Ash.update(cycle1, %{}, action: :mark_as_paid) assert {:ok, c1} = Ash.update(cycle1, %{}, actor: actor, action: :mark_as_paid)
assert c1.status == :paid assert c1.status == :paid
# paid -> suspended # paid -> suspended
assert {:ok, c2} = Ash.update(c1, %{}, action: :mark_as_suspended) assert {:ok, c2} = Ash.update(c1, %{}, actor: actor, action: :mark_as_suspended)
assert c2.status == :suspended assert c2.status == :suspended
# suspended -> unpaid # suspended -> unpaid
assert {:ok, c3} = Ash.update(c2, %{}, action: :mark_as_unpaid) assert {:ok, c3} = Ash.update(c2, %{}, actor: actor, action: :mark_as_unpaid)
assert c3.status == :unpaid assert c3.status == :unpaid
# unpaid -> suspended # unpaid -> suspended
assert {:ok, c4} = Ash.update(c3, %{}, action: :mark_as_suspended) assert {:ok, c4} = Ash.update(c3, %{}, actor: actor, action: :mark_as_suspended)
assert c4.status == :suspended assert c4.status == :suspended
# suspended -> paid # suspended -> paid
assert {:ok, c5} = Ash.update(c4, %{}, action: :mark_as_paid) assert {:ok, c5} = Ash.update(c4, %{}, actor: actor, action: :mark_as_paid)
assert c5.status == :paid assert c5.status == :paid
# paid -> unpaid # paid -> unpaid
assert {:ok, c6} = Ash.update(c5, %{}, action: :mark_as_unpaid) assert {:ok, c6} = Ash.update(c5, %{}, actor: actor, action: :mark_as_unpaid)
assert c6.status == :unpaid assert c6.status == :unpaid
end end
end end

View file

@ -343,29 +343,24 @@ defmodule Mv.Accounts.UserPoliciesTest do
end end
describe "AshAuthentication bypass" do describe "AshAuthentication bypass" do
test "register_with_password works with system actor" do test "register_with_password works without actor via AshAuthentication bypass" do
# Registration should work (AshAuthentication bypass in production) # Test that AshAuthentication bypass allows registration without actor
# Note: When directly calling Ash actions in tests, the AshAuthentication bypass # This tests the actual bypass mechanism, not admin permissions
# may not be active, so we use system_actor to test the functionality changeset =
system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, user} =
Accounts.User Accounts.User
|> Ash.Changeset.for_create(:register_with_password, %{ |> Ash.Changeset.for_create(:register_with_password, %{
email: "register#{System.unique_integer([:positive])}@example.com", email: "register#{System.unique_integer([:positive])}@example.com",
password: "testpassword123" password: "testpassword123"
}) })
|> Ash.create(actor: system_actor) |> Ash.Changeset.set_context(%{private: %{ash_authentication?: true}})
{:ok, user} = Ash.create(changeset)
assert user.email assert user.email
end end
test "register_with_rauthy works with OIDC user_info" do test "register_with_rauthy works without actor via AshAuthentication bypass" do
# OIDC registration should work (AshAuthentication bypass in production) # Test that AshAuthentication bypass allows OIDC registration without actor
# Note: When directly calling Ash actions in tests, the AshAuthentication bypass
# may not be active, so we use system_actor to test the functionality
system_actor = Mv.Helpers.SystemActor.get_system_actor()
user_info = %{ user_info = %{
"sub" => "oidc_sub_#{System.unique_integer([:positive])}", "sub" => "oidc_sub_#{System.unique_integer([:positive])}",
"email" => "oidc#{System.unique_integer([:positive])}@example.com" "email" => "oidc#{System.unique_integer([:positive])}@example.com"
@ -373,20 +368,24 @@ defmodule Mv.Accounts.UserPoliciesTest do
oauth_tokens = %{access_token: "token", refresh_token: "refresh"} oauth_tokens = %{access_token: "token", refresh_token: "refresh"}
{:ok, user} = changeset =
Accounts.User Accounts.User
|> Ash.Changeset.for_create(:register_with_rauthy, %{ |> Ash.Changeset.for_create(:register_with_rauthy, %{
user_info: user_info, user_info: user_info,
oauth_tokens: oauth_tokens oauth_tokens: oauth_tokens
}) })
|> Ash.create(actor: system_actor) |> Ash.Changeset.set_context(%{private: %{ash_authentication?: true}})
{:ok, user} = Ash.create(changeset)
assert user.email assert user.email
assert user.oidc_id == user_info["sub"] assert user.oidc_id == user_info["sub"]
end end
test "sign_in_with_rauthy works with OIDC user_info" do test "sign_in_with_rauthy works without actor via AshAuthentication bypass" do
# First create a user with OIDC ID # First create a user with OIDC ID (using system_actor for setup)
system_actor = Mv.Helpers.SystemActor.get_system_actor()
user_info_create = %{ user_info_create = %{
"sub" => "oidc_sub_#{System.unique_integer([:positive])}", "sub" => "oidc_sub_#{System.unique_integer([:positive])}",
"email" => "oidc#{System.unique_integer([:positive])}@example.com" "email" => "oidc#{System.unique_integer([:positive])}@example.com"
@ -394,8 +393,6 @@ defmodule Mv.Accounts.UserPoliciesTest do
oauth_tokens = %{access_token: "token", refresh_token: "refresh"} oauth_tokens = %{access_token: "token", refresh_token: "refresh"}
system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, user} = {:ok, user} =
Accounts.User Accounts.User
|> Ash.Changeset.for_create(:register_with_rauthy, %{ |> Ash.Changeset.for_create(:register_with_rauthy, %{
@ -404,14 +401,16 @@ defmodule Mv.Accounts.UserPoliciesTest do
}) })
|> Ash.create(actor: system_actor) |> Ash.create(actor: system_actor)
# Now test sign_in_with_rauthy (should work via AshAuthentication bypass) # Now test sign_in_with_rauthy without actor (should work via AshAuthentication bypass)
{:ok, signed_in_user} = query =
Accounts.User Accounts.User
|> Ash.Query.for_read(:sign_in_with_rauthy, %{ |> Ash.Query.for_read(:sign_in_with_rauthy, %{
user_info: user_info_create, user_info: user_info_create,
oauth_tokens: oauth_tokens oauth_tokens: oauth_tokens
}) })
|> Ash.read_one(actor: system_actor) |> Ash.Query.set_context(%{private: %{ash_authentication?: true}})
{:ok, signed_in_user} = Ash.read_one(query)
assert signed_in_user.id == user.id assert signed_in_user.id == user.id
end end

View file

@ -1323,7 +1323,8 @@ defmodule MvWeb.MemberLive.IndexTest do
}) })
|> Ash.create(actor: system_actor) |> Ash.create(actor: system_actor)
member_without_value = member_without_value |> Ash.load!(:custom_field_values) member_without_value =
member_without_value |> Ash.load!(:custom_field_values, actor: system_actor)
members = [member_with_true, member_with_false, member_without_value] members = [member_with_true, member_with_false, member_without_value]
filters = %{to_string(boolean_field.id) => true} filters = %{to_string(boolean_field.id) => true}