From this doc I can read that field level access control accepts user, data, doc, siblingData and id.
When I pass doc or data to the function, it's always undefined.
What is more, is that value reactive i.e. will the access control update when the editReason changes.
access: {
update: ({ req: { user }, doc }) => { if(doc) return doc.editReason === "impairment"; else return true }
}
What I wish to achieve is a dynamic field readOnly status. As the admin field readOnly doesn't accept a function, I am attempting to use the access controls for this.
Hey @KasparTr , there are certain instances where access control is executed without reference to the document. More detail in our docs here under the Argument Availability section:
https://payloadcms.com/docs/access-control/overview#access-controlIn this case, it is impossible to build document based access control logic via access operators?
User can only update documents they have created. This is a basic requirement in almost all systems but in PayloadCMS, it would not be possible to do as access operators don't pass document data?
I'm getting data undefined in all access.update functions.
Example:
export const isEditorOrCreatedBy: Access = ({req: { user },id,data }) => {
const isCreatedBy = {
createdBy: {
equals: user.id,
},
}
console.log("isCreatedBy: ", isCreatedBy) // json object
console.log("data: ", data) // undefined
console.log("id: ", id) // defined
...
};
Just watched this video again.
It's really unclear how these queries are made without any variable declaration. Also they don't work in practice. Not sure why this item is market as answered as there are clearly issues in reality.
In order to achieve your use-case, there would need to be some sort of reference to the user stored on the document. Would the solution in this post work for your use-case?
https://payloadcms.com/blog/build-your-own-rbac?
The gist is to store some sort of value on the document itself, such as user id, role, or team. Then your access control would reference this value in the query constraint that is returned.
Not sure why this item is market as answered as there are clearly issues in reality.
We try our best to answer all inquiries. Since the last post on here was 2 months ago, and the last link was pointing to helpful information - the assumption is that the issue was resolved.
@KasparTr to do what you are looking to do, which is very common, you need to return the query constraint. You won’t have access to the variables you are talking about but the db query will constrain results based on the query you return in the access control functions
Found some code that explained how this works but not as in the video or in docs.
Also, most collections don't have "createdBy" field added in DB so not sure how this query should magically work.
Here is the code if anyone is trubleshooting this.
export const canUpdateItem = (fieldToCheck: string = '<COLLECTION_FIELD_NAME>'): Access => ({ req: { user } }) => {
return {
or: [
{
[fieldToCheck]: {
in: user.id
}
}
]
}
};
Using this in a collection:
access: {
create: () => true,
read: () => true,
update: canUpdateItem('collaborators'),
delete: () => false
},
I also have a usecase for accessing data to access control functions, as I described here:
https://discord.com/channels/967097582721572934/1100757519376339004I agree that the query construction is a bit vague sometimes.
@KasparTr it's not magic. In the post @denolfe shared under the
Set the createdBy Attribute Using a Hook
section, it explains exactly what is being done to achieve this.
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.