This commit is contained in:
parent
bc9ea818eb
commit
b41f005d9e
9 changed files with 110 additions and 92 deletions
|
|
@ -7,21 +7,20 @@ defmodule Mv.Membership.JoinRequestTest do
|
|||
"""
|
||||
use Mv.DataCase, async: false
|
||||
|
||||
alias Mv.Helpers.SystemActor
|
||||
alias Mv.Membership
|
||||
alias Mv.Membership.JoinRequest
|
||||
|
||||
require Ash.Query
|
||||
|
||||
# Minimal valid attributes for the public :confirm action (per concept §2.3.2)
|
||||
# Client-only attributes for :confirm (server sets status, submitted_at, source, schema_version)
|
||||
defp valid_confirm_attrs(opts \\ []) do
|
||||
token = Keyword.get(opts, :confirmation_token_hash, "hash_#{System.unique_integer([:positive])}")
|
||||
token =
|
||||
Keyword.get(opts, :confirmation_token_hash, "hash_#{System.unique_integer([:positive])}")
|
||||
|
||||
[
|
||||
email: "join_#{System.unique_integer([:positive])}@example.com",
|
||||
confirmation_token_hash: token,
|
||||
status: "submitted",
|
||||
submitted_at: DateTime.utc_now(),
|
||||
source: "public_join",
|
||||
schema_version: 1,
|
||||
payload: %{}
|
||||
]
|
||||
|> Enum.into(%{})
|
||||
|
|
@ -39,19 +38,36 @@ defmodule Mv.Membership.JoinRequestTest do
|
|||
assert request.source == "public_join"
|
||||
end
|
||||
|
||||
test "read with actor nil succeeds for created join request" do
|
||||
test "no public read: actor nil cannot read JoinRequest (by id or list)" do
|
||||
attrs = valid_confirm_attrs()
|
||||
{:ok, created} = Membership.confirm_join_request(attrs, actor: nil)
|
||||
|
||||
assert {:ok, %JoinRequest{} = read} =
|
||||
Ash.get(JoinRequest, created.id, actor: nil, domain: Mv.Membership)
|
||||
get_result = Ash.get(JoinRequest, created.id, actor: nil, domain: Mv.Membership)
|
||||
|
||||
assert read.id == created.id
|
||||
assert read.email == created.email
|
||||
assert match?({:error, %Ash.Error.Forbidden{}}, get_result) or
|
||||
match?(
|
||||
{:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{}]}},
|
||||
get_result
|
||||
)
|
||||
|
||||
list_result = JoinRequest |> Ash.read(actor: nil, domain: Mv.Membership)
|
||||
|
||||
assert match?({:error, %Ash.Error.Forbidden{}}, list_result) or
|
||||
match?({:error, %Ash.Error.Invalid{}}, list_result) or
|
||||
list_result == {:ok, []},
|
||||
"actor nil must not see any JoinRequests: got #{inspect(list_result)}"
|
||||
end
|
||||
|
||||
test "generic create with actor nil is forbidden" do
|
||||
attrs = valid_confirm_attrs()
|
||||
# Use full attrs required by :create so the only failure is policy, not validation
|
||||
attrs =
|
||||
valid_confirm_attrs()
|
||||
|> Map.merge(%{
|
||||
status: "submitted",
|
||||
submitted_at: DateTime.utc_now(),
|
||||
source: "public_join",
|
||||
schema_version: 1
|
||||
})
|
||||
|
||||
assert {:error, %Ash.Error.Forbidden{errors: [%Ash.Error.Forbidden.Policy{}]}} =
|
||||
JoinRequest
|
||||
|
|
@ -62,25 +78,23 @@ defmodule Mv.Membership.JoinRequestTest do
|
|||
|
||||
describe "Idempotency (confirmation_token_hash)" do
|
||||
test "second create with same confirmation_token_hash does not create duplicate" do
|
||||
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
||||
system_actor = SystemActor.get_system_actor()
|
||||
token = "idempotent_token_#{System.unique_integer([:positive])}"
|
||||
attrs1 = valid_confirm_attrs(confirmation_token_hash: token)
|
||||
attrs2 = valid_confirm_attrs(confirmation_token_hash: token)
|
||||
attrs2 = %{attrs2 | email: "other_#{System.unique_integer([:positive])}@example.com"}
|
||||
|
||||
assert {:ok, first} = Membership.confirm_join_request(attrs1, actor: nil)
|
||||
assert {:ok, _first} = Membership.confirm_join_request(attrs1, actor: nil)
|
||||
|
||||
# Second call with same token: idempotent return {:ok, existing} (concept §2.3.2)
|
||||
assert {:ok, second} = Membership.confirm_join_request(attrs2, actor: nil)
|
||||
assert second.id == first.id, "idempotent confirm must return the existing record"
|
||||
# Second call with same token: idempotent return {:ok, nil} (no public read)
|
||||
assert {:ok, nil} = Membership.confirm_join_request(attrs2, actor: nil)
|
||||
|
||||
count =
|
||||
JoinRequest
|
||||
|> Ash.Query.filter(confirmation_token_hash == ^token)
|
||||
|> Ash.read!(actor: system_actor, domain: Mv.Membership, authorize?: false)
|
||||
|> length()
|
||||
# Count via allowed admin read (no authorize?: false)
|
||||
assert {:ok, list} = Membership.list_join_requests(actor: system_actor)
|
||||
count = Enum.count(list, &(&1.confirmation_token_hash == token))
|
||||
|
||||
assert count == 1, "expected exactly one JoinRequest with this confirmation_token_hash, got #{count}"
|
||||
assert count == 1,
|
||||
"expected exactly one JoinRequest with this confirmation_token_hash, got #{count}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue