Add actor parameter to all tests requiring authorization
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit adds actor: system_actor to all Ash operations in tests that require authorization.
This commit is contained in:
parent
4c846f8bba
commit
a6cdeaa18d
75 changed files with 4649 additions and 2865 deletions
|
|
@ -8,9 +8,15 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
use MvWeb.ConnCase, async: true
|
||||
require Ash.Query
|
||||
|
||||
setup do
|
||||
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
||||
%{actor: system_actor}
|
||||
end
|
||||
|
||||
describe "OIDC login with existing email (no oidc_id) - Email Collision" do
|
||||
@tag :test_proposal
|
||||
test "OIDC register with existing password user email fails with PasswordVerificationRequired" do
|
||||
test "OIDC register with existing password user email fails with PasswordVerificationRequired",
|
||||
%{actor: actor} do
|
||||
# Create password-only user
|
||||
existing_user =
|
||||
create_test_user(%{
|
||||
|
|
@ -26,10 +32,13 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
}
|
||||
|
||||
result =
|
||||
Mv.Accounts.create_register_with_rauthy(%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
})
|
||||
Mv.Accounts.create_register_with_rauthy(
|
||||
%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
},
|
||||
actor: actor
|
||||
)
|
||||
|
||||
# Should fail with PasswordVerificationRequired error
|
||||
assert {:error, %Ash.Error.Invalid{errors: errors}} = result
|
||||
|
|
@ -47,7 +56,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end
|
||||
|
||||
@tag :test_proposal
|
||||
test "PasswordVerificationRequired error contains necessary context" do
|
||||
test "PasswordVerificationRequired error contains necessary context", %{actor: actor} do
|
||||
existing_user =
|
||||
create_test_user(%{
|
||||
email: "test@example.com",
|
||||
|
|
@ -61,10 +70,13 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
}
|
||||
|
||||
{:error, %Ash.Error.Invalid{errors: errors}} =
|
||||
Mv.Accounts.create_register_with_rauthy(%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
})
|
||||
Mv.Accounts.create_register_with_rauthy(
|
||||
%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
},
|
||||
actor: actor
|
||||
)
|
||||
|
||||
password_error =
|
||||
Enum.find(errors, fn err ->
|
||||
|
|
@ -78,7 +90,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end
|
||||
|
||||
@tag :test_proposal
|
||||
test "after successful password verification, oidc_id can be set" do
|
||||
test "after successful password verification, oidc_id can be set", %{actor: actor} do
|
||||
# Create password user
|
||||
user =
|
||||
create_test_user(%{
|
||||
|
|
@ -97,12 +109,12 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
{:ok, updated_user} =
|
||||
Mv.Accounts.User
|
||||
|> Ash.Query.filter(id == ^user.id)
|
||||
|> Ash.read_one!()
|
||||
|> Ash.read_one!(actor: actor)
|
||||
|> Ash.Changeset.for_update(:link_oidc_id, %{
|
||||
oidc_id: user_info["sub"],
|
||||
oidc_user_info: user_info
|
||||
})
|
||||
|> Ash.update()
|
||||
|> Ash.update(actor: actor)
|
||||
|
||||
assert updated_user.id == user.id
|
||||
assert updated_user.oidc_id == "linked_oidc_555"
|
||||
|
|
@ -112,7 +124,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end
|
||||
|
||||
@tag :test_proposal
|
||||
test "password verification with wrong password keeps oidc_id as nil" do
|
||||
test "password verification with wrong password keeps oidc_id as nil", %{actor: actor} do
|
||||
# This test verifies that if password verification fails,
|
||||
# the oidc_id should NOT be set
|
||||
|
||||
|
|
@ -131,7 +143,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
# before link_oidc_id is called, so here we just verify the user state
|
||||
|
||||
# User should still have no oidc_id (no linking happened)
|
||||
{:ok, unchanged_user} = Ash.get(Mv.Accounts.User, user.id)
|
||||
{:ok, unchanged_user} = Ash.get(Mv.Accounts.User, user.id, actor: actor)
|
||||
assert is_nil(unchanged_user.oidc_id)
|
||||
assert unchanged_user.hashed_password == user.hashed_password
|
||||
end
|
||||
|
|
@ -139,7 +151,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
|
||||
describe "OIDC login with email of user having different oidc_id - Account Conflict" do
|
||||
@tag :test_proposal
|
||||
test "OIDC register with email of user having different oidc_id fails" do
|
||||
test "OIDC register with email of user having different oidc_id fails", %{actor: actor} do
|
||||
# User already linked to OIDC provider A
|
||||
_existing_user =
|
||||
create_test_user(%{
|
||||
|
|
@ -155,10 +167,13 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
}
|
||||
|
||||
result =
|
||||
Mv.Accounts.create_register_with_rauthy(%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
})
|
||||
Mv.Accounts.create_register_with_rauthy(
|
||||
%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
},
|
||||
actor: actor
|
||||
)
|
||||
|
||||
# Should fail - cannot link different OIDC account to same email
|
||||
assert {:error, %Ash.Error.Invalid{errors: errors}} = result
|
||||
|
|
@ -171,7 +186,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end
|
||||
|
||||
@tag :test_proposal
|
||||
test "existing OIDC user email remains unchanged when oidc_id matches" do
|
||||
test "existing OIDC user email remains unchanged when oidc_id matches", %{actor: actor} do
|
||||
user =
|
||||
create_test_user(%{
|
||||
email: "oidc@example.com",
|
||||
|
|
@ -186,10 +201,13 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
|
||||
# This should work via upsert
|
||||
{:ok, updated_user} =
|
||||
Mv.Accounts.create_register_with_rauthy(%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
})
|
||||
Mv.Accounts.create_register_with_rauthy(
|
||||
%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
},
|
||||
actor: actor
|
||||
)
|
||||
|
||||
assert updated_user.id == user.id
|
||||
assert updated_user.oidc_id == "oidc_stable_789"
|
||||
|
|
@ -199,7 +217,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
|
||||
describe "Email update during OIDC linking" do
|
||||
@tag :test_proposal
|
||||
test "linking OIDC to password account updates email if different in OIDC" do
|
||||
test "linking OIDC to password account updates email if different in OIDC", %{actor: actor} do
|
||||
# Password user with old email
|
||||
user =
|
||||
create_test_user(%{
|
||||
|
|
@ -218,19 +236,19 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
{:ok, updated_user} =
|
||||
Mv.Accounts.User
|
||||
|> Ash.Query.filter(id == ^user.id)
|
||||
|> Ash.read_one!()
|
||||
|> Ash.read_one!(actor: actor)
|
||||
|> Ash.Changeset.for_update(:link_oidc_id, %{
|
||||
oidc_id: user_info["sub"],
|
||||
oidc_user_info: user_info
|
||||
})
|
||||
|> Ash.update()
|
||||
|> Ash.update(actor: actor)
|
||||
|
||||
assert updated_user.oidc_id == "oidc_link_999"
|
||||
assert to_string(updated_user.email) == "newemail@example.com"
|
||||
end
|
||||
|
||||
@tag :test_proposal
|
||||
test "email change during linking triggers member email sync" do
|
||||
test "email change during linking triggers member email sync", %{actor: actor} do
|
||||
# Create member
|
||||
member =
|
||||
Ash.Seed.seed!(Mv.Membership.Member, %{
|
||||
|
|
@ -257,25 +275,25 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
{:ok, updated_user} =
|
||||
Mv.Accounts.User
|
||||
|> Ash.Query.filter(id == ^user.id)
|
||||
|> Ash.read_one!()
|
||||
|> Ash.read_one!(actor: actor)
|
||||
|> Ash.Changeset.for_update(:link_oidc_id, %{
|
||||
oidc_id: user_info["sub"],
|
||||
oidc_user_info: user_info
|
||||
})
|
||||
|> Ash.update()
|
||||
|> Ash.update(actor: actor)
|
||||
|
||||
# Verify user email changed
|
||||
assert to_string(updated_user.email) == "newemail@example.com"
|
||||
|
||||
# Verify member email was synced
|
||||
{:ok, updated_member} = Ash.get(Mv.Membership.Member, member.id)
|
||||
{:ok, updated_member} = Ash.get(Mv.Membership.Member, member.id, actor: actor)
|
||||
assert to_string(updated_member.email) == "newemail@example.com"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Edge cases" do
|
||||
@tag :test_proposal
|
||||
test "user with empty string oidc_id is treated as password-only user" do
|
||||
test "user with empty string oidc_id is treated as password-only user", %{actor: actor} do
|
||||
_user =
|
||||
create_test_user(%{
|
||||
email: "empty@example.com",
|
||||
|
|
@ -290,10 +308,13 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
}
|
||||
|
||||
result =
|
||||
Mv.Accounts.create_register_with_rauthy(%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
})
|
||||
Mv.Accounts.create_register_with_rauthy(
|
||||
%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{}
|
||||
},
|
||||
actor: actor
|
||||
)
|
||||
|
||||
# Should trigger PasswordVerificationRequired (empty string = no OIDC)
|
||||
assert {:error, %Ash.Error.Invalid{errors: errors}} = result
|
||||
|
|
@ -307,7 +328,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end
|
||||
|
||||
@tag :test_proposal
|
||||
test "cannot link same oidc_id to multiple users" do
|
||||
test "cannot link same oidc_id to multiple users", %{actor: actor} do
|
||||
# User 1 with OIDC
|
||||
_user1 =
|
||||
create_test_user(%{
|
||||
|
|
@ -323,7 +344,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
email: "user2@example.com"
|
||||
})
|
||||
|> Ash.Changeset.force_change_attribute(:oidc_id, "shared_oidc_333")
|
||||
|> Ash.create()
|
||||
|> Ash.create(actor: actor)
|
||||
|
||||
# Should fail due to unique constraint on oidc_id
|
||||
assert match?({:error, %Ash.Error.Invalid{}}, result)
|
||||
|
|
@ -337,14 +358,16 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end
|
||||
|
||||
describe "OIDC login with passwordless user - Requires Linking Flow" do
|
||||
test "user without password and without oidc_id triggers PasswordVerificationRequired" do
|
||||
test "user without password and without oidc_id triggers PasswordVerificationRequired", %{
|
||||
actor: actor
|
||||
} do
|
||||
# Create user without password (e.g., invited user)
|
||||
{:ok, existing_user} =
|
||||
Mv.Accounts.User
|
||||
|> Ash.Changeset.for_create(:create_user, %{
|
||||
email: "invited@example.com"
|
||||
})
|
||||
|> Ash.create()
|
||||
|> Ash.create(actor: actor)
|
||||
|
||||
# Verify user has no password and no oidc_id
|
||||
assert is_nil(existing_user.hashed_password)
|
||||
|
|
@ -372,14 +395,14 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end)
|
||||
end
|
||||
|
||||
test "user without password but WITH password later requires verification" do
|
||||
test "user without password but WITH password later requires verification", %{actor: actor} do
|
||||
# Create user without password first
|
||||
{:ok, user} =
|
||||
Mv.Accounts.User
|
||||
|> Ash.Changeset.for_create(:create_user, %{
|
||||
email: "added-password@example.com"
|
||||
})
|
||||
|> Ash.create()
|
||||
|> Ash.create(actor: actor)
|
||||
|
||||
# User sets password later (using admin action)
|
||||
{:ok, user_with_password} =
|
||||
|
|
@ -387,7 +410,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
|> Ash.Changeset.for_update(:admin_set_password, %{
|
||||
password: "newpassword123"
|
||||
})
|
||||
|> Ash.update()
|
||||
|> Ash.update(actor: actor)
|
||||
|
||||
assert not is_nil(user_with_password.hashed_password)
|
||||
|
||||
|
|
@ -398,10 +421,13 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
}
|
||||
|
||||
result =
|
||||
Mv.Accounts.create_register_with_rauthy(%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{"access_token" => "test_token"}
|
||||
})
|
||||
Mv.Accounts.create_register_with_rauthy(
|
||||
%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{"access_token" => "test_token"}
|
||||
},
|
||||
actor: actor
|
||||
)
|
||||
|
||||
# Should fail with PasswordVerificationRequired
|
||||
assert {:error, %Ash.Error.Invalid{}} = result
|
||||
|
|
@ -414,7 +440,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end
|
||||
|
||||
describe "OIDC login with different oidc_id - Hard Error" do
|
||||
test "user with different oidc_id cannot be linked (hard error)" do
|
||||
test "user with different oidc_id cannot be linked (hard error)", %{actor: actor} do
|
||||
# Create user with existing OIDC ID
|
||||
{:ok, existing_user} =
|
||||
Mv.Accounts.User
|
||||
|
|
@ -422,7 +448,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
email: "already-linked@example.com"
|
||||
})
|
||||
|> Ash.Changeset.force_change_attribute(:oidc_id, "original_oidc_999")
|
||||
|> Ash.create()
|
||||
|> Ash.create(actor: actor)
|
||||
|
||||
assert existing_user.oidc_id == "original_oidc_999"
|
||||
|
||||
|
|
@ -433,10 +459,13 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
}
|
||||
|
||||
result =
|
||||
Mv.Accounts.create_register_with_rauthy(%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{"access_token" => "test_token"}
|
||||
})
|
||||
Mv.Accounts.create_register_with_rauthy(
|
||||
%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{"access_token" => "test_token"}
|
||||
},
|
||||
actor: actor
|
||||
)
|
||||
|
||||
# Should fail with hard error (not PasswordVerificationRequired)
|
||||
assert {:error, %Ash.Error.Invalid{}} = result
|
||||
|
|
@ -459,7 +488,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
end)
|
||||
end
|
||||
|
||||
test "cannot link different oidc_id even with password verification" do
|
||||
test "cannot link different oidc_id even with password verification", %{actor: actor} do
|
||||
# Create user with password AND existing OIDC ID
|
||||
existing_user =
|
||||
create_test_user(%{
|
||||
|
|
@ -478,10 +507,13 @@ defmodule MvWeb.OidcPasswordLinkingTest do
|
|||
}
|
||||
|
||||
result =
|
||||
Mv.Accounts.create_register_with_rauthy(%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{"access_token" => "test_token"}
|
||||
})
|
||||
Mv.Accounts.create_register_with_rauthy(
|
||||
%{
|
||||
user_info: user_info,
|
||||
oauth_tokens: %{"access_token" => "test_token"}
|
||||
},
|
||||
actor: actor
|
||||
)
|
||||
|
||||
# Should fail - cannot link different OIDC ID
|
||||
assert {:error, %Ash.Error.Invalid{}} = result
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue