fix: respects boolean query preset constraints (#12124)

Returning a boolean value from a constraint-level access control
function does nothing. For example:

```ts
{
  label: 'Noone',
  value: 'noone',
  access: () => false,
},
```

This is because we were only handling query objects, disregarding any
boolean values. The fix is to check if the query is a boolean, and if
so, format a query object to return.
This commit is contained in:
Jacob Fletcher
2025-04-16 09:16:43 -04:00
committed by GitHub
parent e79b20363e
commit a675c04c99
8 changed files with 89 additions and 23 deletions

View File

@@ -24,9 +24,9 @@ export default buildConfigWithDefaults({
// },
access: {
read: ({ req: { user } }) =>
user ? !user?.roles?.some((role) => role === 'anonymous') : false,
user ? user && !user?.roles?.some((role) => role === 'anonymous') : false,
update: ({ req: { user } }) =>
user ? !user?.roles?.some((role) => role === 'anonymous') : false,
user ? user && !user?.roles?.some((role) => role === 'anonymous') : false,
},
constraints: {
read: [
@@ -40,6 +40,11 @@ export default buildConfigWithDefaults({
},
}),
},
{
label: 'Noone',
value: 'noone',
access: () => false,
},
],
update: [
{

View File

@@ -503,6 +503,42 @@ describe('Query Presets', () => {
expect((error as Error).message).toBe('You are not allowed to perform this action.')
}
})
it('should respect boolean access control results', async () => {
// create a preset with the read constraint set to "noone"
const presetForNoone = await payload.create({
collection: queryPresetsCollectionSlug,
user,
data: {
relatedCollection: 'pages',
title: 'Noone',
where: {
text: {
equals: 'example page',
},
},
access: {
read: {
constraint: 'noone',
},
},
},
})
try {
const foundPresetWithUser1 = await payload.findByID({
collection: queryPresetsCollectionSlug,
depth: 0,
user,
overrideAccess: false,
id: presetForNoone.id,
})
expect(foundPresetWithUser1).toBeFalsy()
} catch (error: unknown) {
expect((error as Error).message).toBe('Not Found')
}
})
})
it.skip('should disable query presets when "enabledQueryPresets" is not true on the collection', async () => {

View File

@@ -86,7 +86,7 @@ export interface Config {
'payload-query-presets': PayloadQueryPresetsSelect<false> | PayloadQueryPresetsSelect<true>;
};
db: {
defaultIDType: number;
defaultIDType: string;
};
globals: {};
globalsSelect: {};
@@ -122,7 +122,7 @@ export interface UserAuthOperations {
* via the `definition` "pages".
*/
export interface Page {
id: number;
id: string;
text?: string | null;
updatedAt: string;
createdAt: string;
@@ -133,7 +133,7 @@ export interface Page {
* via the `definition` "users".
*/
export interface User {
id: number;
id: string;
name?: string | null;
roles?: ('admin' | 'user' | 'anonymous')[] | null;
updatedAt: string;
@@ -152,7 +152,7 @@ export interface User {
* via the `definition` "posts".
*/
export interface Post {
id: number;
id: string;
text?: string | null;
updatedAt: string;
createdAt: string;
@@ -163,24 +163,24 @@ export interface Post {
* via the `definition` "payload-locked-documents".
*/
export interface PayloadLockedDocument {
id: number;
id: string;
document?:
| ({
relationTo: 'pages';
value: number | Page;
value: string | Page;
} | null)
| ({
relationTo: 'users';
value: number | User;
value: string | User;
} | null)
| ({
relationTo: 'posts';
value: number | Post;
value: string | Post;
} | null);
globalSlug?: string | null;
user: {
relationTo: 'users';
value: number | User;
value: string | User;
};
updatedAt: string;
createdAt: string;
@@ -190,10 +190,10 @@ export interface PayloadLockedDocument {
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: number;
id: string;
user: {
relationTo: 'users';
value: number | User;
value: string | User;
};
key?: string | null;
value?:
@@ -213,7 +213,7 @@ export interface PayloadPreference {
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: number;
id: string;
name?: string | null;
batch?: number | null;
updatedAt: string;
@@ -224,23 +224,23 @@ export interface PayloadMigration {
* via the `definition` "payload-query-presets".
*/
export interface PayloadQueryPreset {
id: number;
id: string;
title: string;
isShared?: boolean | null;
access?: {
read?: {
constraint?: ('everyone' | 'onlyMe' | 'specificUsers' | 'specificRoles') | null;
users?: (number | User)[] | null;
constraint?: ('everyone' | 'onlyMe' | 'specificUsers' | 'specificRoles' | 'noone') | null;
users?: (string | User)[] | null;
roles?: ('admin' | 'user' | 'anonymous')[] | null;
};
update?: {
constraint?: ('everyone' | 'onlyMe' | 'specificUsers' | 'specificRoles') | null;
users?: (number | User)[] | null;
users?: (string | User)[] | null;
roles?: ('admin' | 'user' | 'anonymous')[] | null;
};
delete?: {
constraint?: ('everyone' | 'onlyMe' | 'specificUsers') | null;
users?: (number | User)[] | null;
users?: (string | User)[] | null;
};
};
where?:

View File

@@ -167,6 +167,21 @@ export const seed = async (_payload: Payload) => {
overrideAccess: false,
data: seedData.onlyMe,
}),
() =>
_payload.create({
collection: 'payload-query-presets',
user: devUser,
overrideAccess: false,
data: {
relatedCollection: 'pages',
title: 'Noone',
access: {
read: {
constraint: 'noone',
},
},
},
}),
],
false,
)