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.

Help About Access Control

default discord avatar
kisut_8 months ago
2

Hi, guys



I'm new at Payload and I'm using v3. I'm trying to make admin panel with 2 role, User and Admin with this repo reference

https://github.com/payloadcms/access-control-demo

. But there was a problem and I was at a loss to solve it.



I have a Media collection and have access control:


read: isAdminOrSelf,
update: isAdminOrSelf,
delete: isAdminOrSelf,


However, when the user wants to upload new media, the user is not redirected to the edit page and instead to the Not Found page. When looking at the collection, the media that has just been uploaded does not exist. But when accessed through the Admin role, the media exists. I've also tried to create a createdBy column in the database and it still doesn't seem to work.



Here is the access file of isAdminOrSelf:


import { Access } from "payload/config";

export const isAdminOrSelf: Access = ({ req: { user } }) => {
  // Need to be logged in
  if (user) {
    // If user has role of 'admin'
    if (user.roles?.includes('admin')) {
      return true;
    }

    // If any other type of user, only provide access to themselves
    return {
      id: {
        equals: user.id,
      }
    }
  }

  // Reject everyone else
  return false;
}


Can someone help me?

  • default discord avatar
    hristo60048 months ago

    This

    isAdminOrSelf

    access hook is meant for the Users collection, anywhere else it won't work, because it's checking whether the

    id

    of the document matches the

    id

    of the user.



    The media doesn't appear to exist for the user that has uploaded it, because the rights are not set up correctly (hence 404 after uploading).



    To fix this, you'll need a way to check whether the current user has created the media document. This can be done with additional field, like

    createdBy

    .



    1) You need to create a

    createdBy

    field in your media collection


    2) Then when you create a new media document, this field needs to be automatically populated with the current user's

    id

    , this will be useful for the access hook later to check whether the user's

    id

    matches with the

    id

    saved in

    createdBy

    .



    After you have your

    createdBy

    field, add the following hook:



    import type { CollectionBeforeChangeHook } from 'payload'
    
    export const populateCreatedBy: CollectionBeforeChangeHook = ({
      data,
      req: { user },
      operation,
    }) => {
      if (operation === 'create') {
        if (user) {
          data.createdBy = user.id
    
          return data
        }
      }
    
      return data
    }


    Import it in your media collection and set it as a

    beforeChange

    hook:



    hooks: {
      beforeChange: [populateCreatedBy],
    }


    Then for your read access, you can do something like this:



    import { Access } from "payload/config";
    
    export const isAdminOrSelf: Access = ({ req: { user } }) => {
      // Need to be logged in
      if (user) {
        // If user has role of 'admin'
        if (user.roles?.includes('admin')) {
          return true;
        }
    
        // If any other type of user, only provide access to themselves
        return {
          createdBy: {
            equals: user.id,
          }
        }
      }
    
      // Reject everyone else
      return false;
    }


    There might be some modifications here and there, but hopefully this helps.

  • default discord avatar
    kisut_8 months ago

    It's working, thanks

    @415764121280184330

    !

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.