Skip to content

Commit 5164f64

Browse files
authored
test: Reproduce (KeyError) key :to_tenant not found in: nil (#309)
1 parent 70c266d commit 5164f64

File tree

9 files changed

+433
-0
lines changed

9 files changed

+433
-0
lines changed

test/gf_test.exs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
defmodule GF.Test do
2+
use ExUnit.Case
3+
4+
test "basic" do
5+
group =
6+
GF.Group
7+
|> Ash.Changeset.for_create(:create, %{abbreviation: "TG", name: "Test Group"})
8+
|> Ash.create!(authorize?: false)
9+
10+
Ash.DataLayer.Simple.set_data(GF.Group, [group])
11+
12+
event =
13+
GF.Event
14+
|> Ash.Changeset.for_create(:create, %{title: "Test Event"}, tenant: group.id)
15+
|> Ash.create!(authorize?: false)
16+
17+
assert event.id
18+
19+
Ash.DataLayer.Simple.set_data(GF.Event, [event])
20+
21+
assert Ash.get!(GF.Event, event.id, authorize?: false)
22+
23+
member =
24+
GF.Member
25+
|> Ash.Changeset.for_create(
26+
:create,
27+
%{email: "test@example.com", name: "Test Member", status: :active},
28+
tenant: group.id
29+
)
30+
|> Ash.create!(authorize?: false)
31+
32+
actor =
33+
GF.Member
34+
|> Ash.Changeset.for_create(
35+
:create,
36+
%{email: "actor@example.com", name: "Actor Member", status: :inactive},
37+
tenant: group.id
38+
)
39+
|> Ash.create!(authorize?: false)
40+
41+
Ash.DataLayer.Simple.set_data(GF.Member, [member, actor])
42+
43+
attendee =
44+
GF.Attendee
45+
|> Ash.Changeset.for_create(:create, %{event_id: event.id, member_id: member.id})
46+
|> Ash.create!(authorize?: false)
47+
48+
Ash.DataLayer.Simple.set_data(GF.Attendee, [attendee])
49+
50+
assert attendee.id
51+
52+
{:ok, %{data: data}} =
53+
"""
54+
query GetEvent($id: ID!) {
55+
getEvent(id: $id) {
56+
id
57+
title
58+
attendees(filter: {member: {status: {eq: ACTIVE}}}) {
59+
id
60+
member {
61+
id
62+
name
63+
}
64+
}
65+
}
66+
}
67+
"""
68+
|> Absinthe.run(GF.AshGraphqlSchema,
69+
variables: %{"id" => event.id},
70+
context: %{actor: actor}
71+
)
72+
73+
assert data["getEvent"]
74+
end
75+
end
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
defmodule GF.ActiveMemberPolicy do
2+
use Ash.Policy.SimpleCheck
3+
4+
# This is used when logging a breakdown of how a policy is applied - see Logging below.
5+
def describe(_) do
6+
"Member is active and has given role"
7+
end
8+
9+
def match?(%_{} = member, %{resource: _resource} = _context, opts) do
10+
active? =
11+
case member do
12+
%{status: :active} -> true
13+
_other -> false
14+
end
15+
16+
cond do
17+
opts[:role] ->
18+
GF.Member.can_take_role_action?(member, opts[:role])
19+
20+
true ->
21+
active?
22+
end
23+
end
24+
25+
def match?(_actor, _context, _opts) do
26+
false
27+
end
28+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
defmodule GF.AshGraphqlSchema do
2+
@moduledoc false
3+
4+
use Absinthe.Schema
5+
6+
@domains [GF.Domain]
7+
8+
use AshGraphql, domains: @domains, generate_sdl_file: "priv/gf_schema.graphql"
9+
10+
query do
11+
end
12+
13+
mutation do
14+
end
15+
end

test/support/gf/attendee.ex

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
defmodule GF.Attendee do
2+
@moduledoc """
3+
An attendee record for ane event.
4+
"""
5+
6+
use Ash.Resource,
7+
domain: GF.Domain,
8+
data_layer: Ash.DataLayer.Ets,
9+
extensions: [AshGraphql.Resource],
10+
authorizers: [Ash.Policy.Authorizer]
11+
12+
require Ash.Query
13+
require Ash.Sort
14+
15+
alias GF.Member
16+
17+
actions do
18+
default_accept(:*)
19+
defaults([:create, :update, :read, :destroy])
20+
end
21+
22+
attributes do
23+
uuid_primary_key(:id)
24+
25+
attribute(:event_id, :uuid, public?: true)
26+
attribute(:member_id, :uuid, public?: true)
27+
28+
create_timestamp(:inserted_at)
29+
update_timestamp(:updated_at)
30+
end
31+
32+
relationships do
33+
belongs_to(:member, Member, public?: true)
34+
end
35+
36+
policies do
37+
policy action(:read) do
38+
authorize_if(actor_present())
39+
end
40+
end
41+
42+
graphql do
43+
type :gf_attendee
44+
end
45+
46+
code_interface do
47+
define(:get_by_id, action: :read, get_by: :id, not_found_error?: false)
48+
define(:create, action: :create)
49+
define(:update, action: :update)
50+
end
51+
end

test/support/gf/domain.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
defmodule GF.Domain do
2+
use Ash.Domain
3+
4+
resources do
5+
resource(GF.Event)
6+
resource(GF.Attendee)
7+
resource(GF.Group)
8+
resource(GF.Member)
9+
end
10+
end

test/support/gf/event.ex

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
defmodule GF.Event do
2+
@moduledoc """
3+
Event Ash resource.
4+
"""
5+
6+
use Ash.Resource,
7+
domain: GF.Domain,
8+
data_layer: Ash.DataLayer.Ets,
9+
extensions: [AshGraphql.Resource]
10+
11+
require Ash.Query
12+
13+
alias GF.Attendee
14+
15+
attributes do
16+
uuid_primary_key(:id)
17+
18+
attribute(:description, :string, public?: true)
19+
attribute(:group_id, :uuid, public?: false)
20+
21+
attribute(:start_at, :utc_datetime, public?: true)
22+
attribute(:title, :string, public?: true)
23+
24+
create_timestamp(:inserted_at, public?: true)
25+
update_timestamp(:updated_at, public?: true)
26+
end
27+
28+
multitenancy do
29+
strategy(:attribute)
30+
attribute(:group_id)
31+
global?(true)
32+
end
33+
34+
actions do
35+
default_accept(:*)
36+
defaults([:create, :read, :update, :destroy])
37+
end
38+
39+
relationships do
40+
has_many(:attendees, Attendee, public?: true)
41+
end
42+
43+
graphql do
44+
type :gf_event
45+
46+
queries do
47+
get :get_event, :read
48+
end
49+
end
50+
51+
code_interface do
52+
define(:get_by_id, action: :read, get_by: :id, not_found_error?: false)
53+
define(:create, action: :create)
54+
end
55+
end

test/support/gf/group.ex

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
defmodule GF.Group do
2+
@moduledoc "An Ash-managed GroupFlow Group (customer)"
3+
4+
use Ash.Resource,
5+
domain: GF.Domain,
6+
data_layer: Ash.DataLayer.Ets,
7+
extensions: [AshGraphql.Resource]
8+
9+
@type t :: %__MODULE__{}
10+
11+
# Attributes are the simple pieces of data that exist on your resource
12+
attributes do
13+
uuid_primary_key(:id)
14+
15+
attribute(:abbreviation, :string, public?: true)
16+
attribute(:name, :string, public?: true)
17+
18+
create_timestamp(:inserted_at, public?: true)
19+
update_timestamp(:updated_at, public?: true)
20+
end
21+
22+
actions do
23+
default_accept(:*)
24+
# Add a set of simple actions. You'll customize these later.
25+
defaults([:create, :read, :update, :destroy])
26+
end
27+
28+
graphql do
29+
type :group2
30+
end
31+
32+
code_interface do
33+
define(:create, action: :create)
34+
end
35+
end

0 commit comments

Comments
 (0)