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?
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.
It's working, thanks
@415764121280184330!
Star
Discord
online
Get dedicated engineering support directly from the Payload team.