Hello! Maybe I am missing something, but I could not find anything related to access control of the 'unpublish' action. Is it possible?
@cerize Hi! You can use the beforeChange
hook to check the document's _status
. If it went from published
to draft
then you can throw an API error. Something like this (untested):
import APIError from "payload/dist/errors/APIError";
const beforeChangeHook: GlobalBeforeChangeHook = async ({
data, // incoming data to update or create with
req, // full express request
originalDoc, // original document
}) => {
if (originalDoc._status === 'published' && data._status !== 'published') throw new APIError('You cannot do this!');
return data; // Return data to update the document with
}
Here are the docs for this hook: https://payloadcms.com/docs/hooks/globals#beforechange
@jacobsfletch let me bug you one more time. Does a hook ever receive the _status 'changed'? It seems that if I publish a document, then make a random modification, the status goes back to 'draft' and I thought it would be 'changed': https://payloadcms.com/docs/versions/drafts#database-changes. My use case is 'Do not allow changing the field x if the document was ever published.
@jacobsfletch there is also another scenario that would make the status go from published to draft. It's when something is published as someone just 'save draft'. So that may not be enough to distinguish 'unpublish'?
@cerize I believe the changed
status is virtual and doesn't ever save to the db. This is because a single document is never changed
—they can only every be draft
or published
.
It's when something is published as someone just 'save draft'. So that may not be enough to distinguish 'unpublish'?
Ok so you need to prevent them from unpublishing documents, but allow them to save drafts. You're right this is tricky, it's not immediately clear to me how we'd handle these cases.
thanks for the clarification @jacobsfletch! Do you know if it's in the roadmap any change that would allow to target the 'unpublish' action?
You could add a hidden: true
field for new field named wasPublished
that you give a beforeChange
that conditionally sets the field true if (value || _status === 'published')
. Then in a custom validation logic function on the locked in fields you could compare the wasPublished
value.
Would that work for your scenario @cerize?
Thanks @DanRibbens and @jacobsfletch , I will try!