Hey! I'm making a PoC with Payload as multi-tenant CMS for some Next frontends. My query for tenant-specific data returns an empty list, and so I'd just like to check that my thinking and setup is correct. I'm on localhost with my Payload backend (clone of multi-tenant example) and two Next frontends running on each their own port:
- The collection I'm querying is set up with a
tenant
field. I can logon as tenant admin and see other tenants' data filtered out.
- My tenants are set up with a
slug
field, and their
domains
field is set up with a test domain that is mocked in Windows hosts file. I'm querying the data like so:
http://tenant-mock.localhost/cms/api/courses?where[tenant][slug][equals]=tenant-slug
- I have Payload config set up with
routes { api: "/cms/api" }
to let the Next apps use that route. Then I have nginx configured for each host domain to redirect
/
to the Next frontend and
/admin
and
/cms
to my Payload backend.
I'm accessing the frontends in my browser and trying to intercept the GET using Postman Interceptor. I don't know if it's the interceptor but the request doesn't show up. It catches everything on reload page, navigating in admin, etc.
I'm console logging the return value
data.docs
though and it does return an empty list.
Any ideas welcome, thanks!
Update:
- Make sure the collection config
access: { read: anyone }
to make it publicly queryable
- Adding
depth: 2
to the query made it return data, finally.
However data from other tenants are returned as well so I keep looking.
Any ideas why tenant should not be respected in a query of thi?
const query = {
tenant: {
slug: {
equals: 'hjertets-tempel'
}
}
}
const stringified = qs.stringify(
{
depth: 2,
where: query
},
{
addQueryPrefix: true
}
)
const url = http://hjertets-tempel.localhost/cms/api/courses${stringified}
Solved: The query is fine. It doesn't need
depth
specified (not sure why it returned
[]
before without it).
You can query collections publicly (without
Authorization
headers identifying what
user
you are querying as), as long as your collection's
access: read
config resolves to
true
. In that case the query will return everything.
If you want to return only one tenant's data using the query pattern specified in the multi-tenant example,
/api/pages?where[tenant][slug][equals]=abc
, you have to authorize the query for Payload to be able to differentiate between tenant data.
Make sure the collection has a
tenant
field, and that each tenant has a
slug
field.
So you can authorize your app's requests and basically log in using the request headers, but a better way is using API keys, thanks August for letting me know:
- Add
auth: { useAPIKey: true }
to your
user
collection,
- Log in to your admin dashboard and enable API keys on the appropriate tenant admin user, copy the API key,
- Query the data from your app with the key as specified here:
https://payloadcms.com/docs/authentication/config#authenticating-via-api-keyThat way you can let your apps interact with your backend as tenant admin users thru their API key.
Turns out the API key filters the tenant data already. I haven't been able to make the filter by query params work. Edit: I'm guessing it's meant to be used when you authorize the request normally (without API key).
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.