Automatically filtering collections by site (multisite setup)

default discord avatar
falko100
8 months ago
1 1

Hey guys!

I've been working a feature for a client that wants to use 1 payload instance for all his sites.
So far I added a sites collection and every collection (such as pages) has a site relation.

I've added a Context for setting your currently active site:

import React, {
    useState, createContext, useContext, useEffect,
} from 'react';

const Context = createContext({
    currentSite: null,
    setCurrentSite: () => {},
} as SiteContext);

export const SiteProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
    const [currentSite, setCurrentSite] = useState<string | null>();

    useEffect(() => {
        const site = localStorage.getItem('currentSite');

        if (site) {
            setCurrentSite(site);
        }
    });

    const setSite = (site: string | null) => {
        localStorage.setItem('currentSite', site);
        setCurrentSite(site);
    }

    return (
        <Context.Provider value={{
            currentSite,
            setCurrentSite: setSite,
        }}>
            {children}
        </Context.Provider>
    );
};

class SiteContext {
    currentSite: string | null;
    setCurrentSite: (string) => void;
}

type UseSite = () => SiteContext;

export const useSite: UseSite = () => useContext(Context);

And added a simple dropdown below the logo to pick one of the sites.

Now I want to enable the "collection.filters.where.site = currentSite" filter by default on some of the collections, but I have trouble finding where to do this. Any tips?

  • discord user avatar
    jmikrut
    Payload Team
    8 months ago

    Hey @falko100 — that type of "filter" would be referred to as a query constraint, and that is generally accomplished via some backend logic in either a field hook or an access control operation.

    There are lots of ways to do this - but I think how I'd do it is persist something to the user when you switch the selected site - like... a select field on the user or similar.

    And then write all your access control to look at which site the user has selected, and return your query constraint based on that. Does that make sense?

    1 reply
  • default discord avatar
    falko100
    8 months ago

    Ahh perfect. I was close but got confused.
    I finally put it here:

    const Pages: CollectionConfig = {
      slug: 'pages',
      access: {
        read: ({ req: { user }}) => {
          if (user) {
            return {
              site: {
                equals: user.currentSite.id,
              }
            }
          }
    
          return true;
        },
        ...
      },

    My problem was that I was trying to do this all in the frontend.

Open the post
Continue the discussion in GitHub
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.