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
tenantfield. I can logon as tenant admin and see other tenants' data filtered out.
- My tenants are set up with a
slugfield, and their
domainsfield 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
/adminand
/cmsto 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.docsthough 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: 2to 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
depthspecified (not sure why it returned
[]before without it).
You can query collections publicly (without
Authorizationheaders identifying what
useryou are querying as), as long as your collection's
access: readconfig 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
tenantfield, and that each tenant has a
slugfield.
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
usercollection,
- 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 dedicated engineering support directly from the Payload team.