From 51ecd31312260f27fb246ea489ee6f558be962ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20K=C3=BCttner?= Date: Wed, 14 Aug 2024 14:11:51 +0200 Subject: [PATCH] Fix the order of preset application and payload validation (#23346) Co-authored-by: Pascal Jufer --- .changeset/warm-queens-drop.md | 5 ++++ .../process-payload/process-payload.test.ts | 24 +++++++++++++++++++ .../process-payload/process-payload.ts | 12 +++++----- 3 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 .changeset/warm-queens-drop.md diff --git a/.changeset/warm-queens-drop.md b/.changeset/warm-queens-drop.md new file mode 100644 index 0000000000..efdea7e162 --- /dev/null +++ b/.changeset/warm-queens-drop.md @@ -0,0 +1,5 @@ +--- +'@directus/api': patch +--- + +Ensured payload validation accounts for preset data diff --git a/api/src/permissions/modules/process-payload/process-payload.test.ts b/api/src/permissions/modules/process-payload/process-payload.test.ts index 92c6f1cc45..e56dce2eb8 100644 --- a/api/src/permissions/modules/process-payload/process-payload.test.ts +++ b/api/src/permissions/modules/process-payload/process-payload.test.ts @@ -288,3 +288,27 @@ test('Merges and applies defaults from presets', async () => { 'field-c': 2, }); }); + +test('Checks validation rules against payload with defaults', async () => { + const schema = { collections: { 'collection-a': { fields: {} } } } as unknown as SchemaOverview; + const acc = { admin: false } as unknown as Accountability; + + vi.mocked(fetchPermissions).mockResolvedValue([ + { fields: ['field-a'], validation: { 'field-a': { _eq: 2 } }, presets: { 'field-a': 1 } } as unknown as Permission, + { fields: [], validation: null, presets: { 'field-a': 2 } } as unknown as Permission, + ]); + + const payloadWithPresets = await processPayload( + { + accountability: acc, + action: 'read', + collection: 'collection-a', + payload: {}, + }, + { schema } as Context, + ); + + expect(payloadWithPresets).toEqual({ + 'field-a': 2, + }); +}); diff --git a/api/src/permissions/modules/process-payload/process-payload.ts b/api/src/permissions/modules/process-payload/process-payload.ts index ecceec11b3..0f77fa061b 100644 --- a/api/src/permissions/modules/process-payload/process-payload.ts +++ b/api/src/permissions/modules/process-payload/process-payload.ts @@ -84,6 +84,10 @@ export async function processPayload(options: ProcessPayloadOptions, context: Co fieldValidationRules.push(field.validation); } + const presets = (permissions ?? []).map((permission) => permission.presets); + + const payloadWithPresets = assign({}, ...presets, options.payload); + const validationRules = [...fieldValidationRules, ...permissionValidationRules].filter((rule): rule is Filter => { if (rule === null) return false; if (Object.keys(rule).length === 0) return false; @@ -94,7 +98,7 @@ export async function processPayload(options: ProcessPayloadOptions, context: Co const validationErrors: InstanceType[] = []; validationErrors.push( - ...validatePayload({ _and: validationRules }, options.payload) + ...validatePayload({ _and: validationRules }, payloadWithPresets) .map((error) => error.details.map((details) => new FailedValidationError(joiValidationErrorItemToErrorExtensions(details))), ) @@ -104,9 +108,5 @@ export async function processPayload(options: ProcessPayloadOptions, context: Co if (validationErrors.length > 0) throw validationErrors; } - if (!permissions) return options.payload; - - const presets = permissions.map((permission) => permission.presets); - - return assign({}, ...presets, options.payload); + return payloadWithPresets; }