Fetching from multi-tenant collection returns empty

default discord avatar
ingrid741
2 weeks ago

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-key

That 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).

    Open the post
    Continue the discussion in Discord
    Like what we're doing?
    Star us on GitHub!

    Star

    Connect with the Payload Community on Discord

    Discord

    online

    Can't find what you're looking for?

    Get help straight from the Payload team with an Enterprise License.