This is, in my opinion, Payload's most underrated feature.
An access function can return true/false — or it can return a Where object that Payload stitches into every query at the database level. That's row-level security, for free:
export const canReadPage: Access<Page> = ({ req: { user } }) => {
if (user) return true
// A guest only sees public documents — the filter goes to the DB, not to JS
return {
isPublic: { equals: true },
}
}
You don't fetch everything and then filter in memory — this Where becomes part of the WHERE clause in SQL (or $match in Mongo). And it works identically for read, update, and delete.
Once it clicks that access control is a constraint, not a gate, a whole class of "filter the user's own records" problems just disappears.
Top comments (0)