I'm trying to understand how to use attribute-based multitenancy with AshGraphql
1. The documentation says to set up a
multitenancy
block in your resource module, and add a strategy
and attribute
. Check:
2. The documentation says to pass the tenant to the conn
by calling Ash.PlugHelpers.set_tenant/2
. Check:
Also, I inspected the above call to ensure it's being called correctly in my test.
So now in my test, I call the "create" mutation for my resource, and it returns the error "GF.Ash.WebComponent changesets require a tenant to be specified"
What am I missing?28 Replies
In the Multitenancy Topic (https://ash-hq.org/docs/guides/ash/latest/topics/multitenancy), it says:
Setting the tenant when using the code API is done via Ash.Query.set_tenant/2 and Ash.Changeset.set_tenant/2 . If you are using an extension, such as AshJsonApi or AshGraphql the method of setting tenant context is explained in that extension’s documentation.The words
AshJsonApi
and AshGraphql
are linked. AshJsonApi
goes to a "We couldn't find that page.". AshGraphql
goes to the API doc for the AshGraphql
module, with no information about setting the tenant context as claimed in the paragraph above.Yikes.
If you don't mind creating an issue in Ash for those links being broken that would be great
Well, just the one link.
Anyway, this ought to be documented in the multitenancy guide, but what you need to do is use
Ash.PlugHelpers.set_tenant(conn, "tenant_string")
in a plug
So the idea is that tenancy is something that can be derived from something like a subdomain or a header or something like that.
oh
I should have read your message more
🤔 the set_tenant
should be all you need
How are you calling the mutation in your test?In
Ash.PlugHelpers.set_tenant(conn, "tenant_string")
, what is "tenant_string"
? Is that the tenant ID?WIth tenancy in Ash a tenant is just a string
For attribute multitenancy, it is the value that the attribute must equal
I'm not sure I follow. My tenant is an
Org
record. It has a primary key. Other tables in the database have org_id
foreign keys to the orgs
table.
What is "tenant_string"
for me?If you are using attribute multitenancy, and the attribute is
org_id
, then the tenant string would be the organisation idYes, I"m using attribute base multitenancy
attribute multitenancy ultimately boils down to
filter(org_id == ^tenant_string)
Okay, great.
I've been passing the
Org
struct to Ash.PlugHelpers.set_tenant/2
, so that's my problem.
Hmm, the problem still remains.
I added an IO.inspect to AshGraphql.Graphql.Resolver.mutate/3
, and the tenant is nil. I don't know why.So what does your test code look like?
oh, are you getting the error from the actual post_gql call or just your call to
for_create
?
In the resp_body of the GraphQL call
what does
post_gql
doIt calls
post()
, but it also passes the org_id to the request first.
In my plug, it does this:
I added an IO.inspect there, and it's executing correctly there.Okay...maybe there is a bug there? Does it work in real life?
like if you load up the playground?
I haven't tried it outside of tests. I'll try...
Same thing in Graphiql. In the server output, I see my debug statements:
The first one is from my plug that calls
set_tenant/2
. The second one is from inside of AshGraphql.Graphql.Resolver.mutate/3
Here's the call/2
function from the plug:
That plug is used inside a pipeline:
Then that pipeline is used in the graphql endpoints:
Somehow, the set_tenant()
call isn't getting the tenant value to the context inside of AshGraphql.Graphql.Resolver.mutate/3
lemme take a look at that code in a bit, I'll see if I can figure out what is going wrong
hopefully I haven't just been telling you a lie
We did a change over from how it used to get the tenant to supporting getting it from plug helpers at some point, and maybe no one has set up a new multitenant graphql since then to spot the issue
I also tried commenting out the line
|> Absinthe.Plug.put_options(context: context)
, and it didn't make any difference. I thought maybe that might be interfering with things, but no.Actually...try setting tenant and actor keys in the context there
that was the old way
I think I figured it out. My test is passing:
I realized that there was nothing passing the tenant from the conn to the Absinthe context.
...is that in our guides? I completely forgot about that plug, sorry 😦
No, it's not
woof
okay, well, an issue for that would be great. I'll fix it in the morning, sorry about that 😢
oh wait, there it is
Hmm...yeah we should just put taht in the initial set up guide
even if you aren't using users or tenants, it won't hurt to have it, and then you don't end up in this position
Yeah, good idea