Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

In multi-tenant example...

default discord avatar
tejas_nirala12 months ago
4

I am able to hit the

localhost:300/api/users

api call successfully on browser. But on postman i am getting an error saying

"You are not allowed to perform this action."

. Any idea on this issue, how to fix it or what is the reason behind it.



please excuse me if this is simple issue, I am new to payload-cms

  • default discord avatar
    notchr12 months ago

    This is likely an access control / permission issue



    Can you share the Users access control config here?

  • default discord avatar
    tejas_nirala12 months ago

    Hi @notchris


    These are the access control I am using:


      access: {
        read: adminsAndSelf,
        create: anyone,
        update: adminsAndSelf,
        delete: adminsAndSelf,
        admin: isSuperOrTenantAdmin,
      },


    adminsAndSelf

    :


    export const adminsAndSelf: Access<any, User> = async ({ req: { user } }) => {
      if (user) {
        const isSuper = isSuperAdmin(user)
    
        // allow super-admins through only if they have not scoped their user via `lastLoggedInTenant`
        if (isSuper && !user?.lastLoggedInTenant) {
          return true
        }
    
        // allow users to read themselves and any users within the tenants they are admins of
        return {
          or: [
            {
              id: {
                equals: user.id,
              },
            },
            ...(isSuper
              ? [
                  {
                    'tenants.tenant': {
                      in: [
                        typeof user?.lastLoggedInTenant === 'string'
                          ? user?.lastLoggedInTenant
                          : user?.lastLoggedInTenant?.id,
                      ].filter(Boolean),
                    },
                  },
                ]
              : [
                  {
                    'tenants.tenant': {
                      in:
                        user?.tenants
                          ?.map(({ tenant, roles }) =>
                            roles.includes('admin')
                              ? typeof tenant === 'string'
                                ? tenant
                                : tenant.id
                              : null,
                          ) // eslint-disable-line function-paren-newline
                          .filter(Boolean) || [],
                    },
                  },
                ]),
          ],
        }
      }
    }


    .



    isSuperOrTenantAdmin

    :


    export const isSuperOrTenantAdmin = async (args: {
      req: PayloadRequest;
    }): Promise<boolean> => {
      const {
        req,
        req: { user, payload },
      } = args;
    
      // always allow super admins through
      if (isSuperAdmin(user)) {
        return true;
      }
    
      if (logs) {
        const msg = `Finding tenant with host: '${req.headers.host}'`;
        payload.logger.info({ msg });
      }
    
      // read `req.headers.host`, lookup the tenant by `domain` to ensure it exists, and check if the user is an admin of that tenant
      const foundTenants = await payload.find({
        collection: "tenants",
        where: {
          "domains.domain": {
            in: [req.headers.host],
          },
        },
        depth: 0,
        limit: 1,
        req,
      });
    
      // if this tenant does not exist, deny access
      if (foundTenants.totalDocs === 0) {
        if (logs) {
          const msg = `No tenant found for ${req.headers.host}`;
          payload.logger.info({ msg });
        }
    
        return false;
      }
    
      if (logs) {
        const msg = `Found tenant: '${foundTenants?.docs[0]?.orgName}', checking if user is an tenant admin`;
        payload.logger.info({ msg });
      }
    
      // finally check if the user is an admin of this tenant
      const tenantWithUser = user?.tenants?.find(
        ({ tenant: userTenant }) => userTenant?.id === foundTenants.docs[0].id
      );
    
      if (tenantWithUser?.roles?.some((role: any) => role.roleName === "Admin")) {
        if (logs) {
          const msg = `User is an admin of ${foundTenants?.docs[0]?.orgName}, allowing access`;
          payload.logger.info({ msg });
        }
    
        return true;
      }
    
      if (logs) {
        const msg = `User is not an admin of ${foundTenants?.docs[0]?.orgName}, denying access`;
        payload.logger.info({ msg });
      }
    
      return false;
    };
  • default discord avatar
    anders229212 months ago

    You are probably logged in with browser (and browser is sending cookie). And postman the request is anonymous and permission denied.

  • default discord avatar
    tejas_nirala12 months ago

    Thanks @anders. After logging in via postman (/api/users/login), I was succesfully able to fetch the details from collections.

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.