From c41e0b7b7455bb7e9169cbc6fbd82a3d0ff9db73 Mon Sep 17 00:00:00 2001 From: wtrocki Date: Thu, 6 Mar 2025 13:52:58 +0100 Subject: [PATCH] CLOUDP-271997: request no body --- .../deleteMethodNoRequestBody.test.js | 71 +++++++++++++++++++ tools/spectral/ipa/rulesets/IPA-108.yaml | 9 +++ tools/spectral/ipa/rulesets/README.md | 1 + .../functions/deleteMethod204Response.js | 2 +- .../functions/deleteMethod404Response.js | 2 +- .../functions/deleteMethodNoRequestBody.js | 25 +++++++ 6 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 tools/spectral/ipa/__tests__/deleteMethodNoRequestBody.test.js create mode 100644 tools/spectral/ipa/rulesets/functions/deleteMethodNoRequestBody.js diff --git a/tools/spectral/ipa/__tests__/deleteMethodNoRequestBody.test.js b/tools/spectral/ipa/__tests__/deleteMethodNoRequestBody.test.js new file mode 100644 index 0000000000..8a3ea84fb5 --- /dev/null +++ b/tools/spectral/ipa/__tests__/deleteMethodNoRequestBody.test.js @@ -0,0 +1,71 @@ +import testRule from './__helpers__/testRule'; +import { DiagnosticSeverity } from '@stoplight/types'; + +testRule('xgen-IPA-108-delete-request-no-body', [ + { + name: 'valid DELETE without body', + document: { + paths: { + '/resource/{id}': { + delete: { + responses: { + 204: {}, + }, + }, + }, + }, + }, + errors: [], + }, + { + name: 'invalid DELETE with body', + document: { + paths: { + '/resource/{id}': { + delete: { + requestBody: { + content: { + 'application/vnd.atlas.2024-08-05+json': { + schema: { type: 'object' }, + }, + }, + }, + responses: { + 204: {}, + }, + }, + }, + }, + }, + errors: [ + { + code: 'xgen-IPA-108-delete-request-no-body', + message: 'DELETE method should not have a request body. http://go/ipa/108', + path: ['paths', '/resource/{id}', 'delete'], + severity: DiagnosticSeverity.Warning, + }, + ], + }, + { + name: 'valid with exception', + document: { + paths: { + '/resource/{id}': { + delete: { + 'x-xgen-IPA-exception': { + 'xgen-IPA-108-delete-request-no-body': 'Bulk delete operation', + }, + requestBody: { + content: { + 'application/json': { + schema: { type: 'object' }, + }, + }, + }, + }, + }, + }, + }, + errors: [], + }, +]); diff --git a/tools/spectral/ipa/rulesets/IPA-108.yaml b/tools/spectral/ipa/rulesets/IPA-108.yaml index e5bd2cd233..989ef51b14 100644 --- a/tools/spectral/ipa/rulesets/IPA-108.yaml +++ b/tools/spectral/ipa/rulesets/IPA-108.yaml @@ -26,7 +26,16 @@ rules: then: function: deleteMethod404Response + xgen-IPA-108-delete-request-no-body: + description: DELETE method must not have request body. http://go/ipa/108 + message: '{{error}} http://go/ipa/108' + severity: warn + given: $.paths[*].delete + then: + function: deleteMethodNoRequestBody + functions: - deleteMethodResponseShouldNotHaveSchema - deleteMethod204Response + - deleteMethodNoRequestBody - deleteMethod404Response diff --git a/tools/spectral/ipa/rulesets/README.md b/tools/spectral/ipa/rulesets/README.md index a7e120957c..e0139de793 100644 --- a/tools/spectral/ipa/rulesets/README.md +++ b/tools/spectral/ipa/rulesets/README.md @@ -55,6 +55,7 @@ For rule definitions, see [IPA-108.yaml](https://github.com/mongodb/openapi/blob | xgen-IPA-108-delete-response-should-be-empty | Delete method response should not have schema reference to object. http://go/ipa/108 | warn | | xgen-IPA-108-delete-method-return-204-response | DELETE method must return 204 No Content. http://go/ipa/108 | warn | | xgen-IPA-108-delete-include-404-response | DELETE method must include 404 response and return it when resource not found. http://go/ipa/108 | warn | +| xgen-IPA-108-delete-request-no-body | DELETE method must not have request body. http://go/ipa/108 | warn | ### IPA-109 diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethod204Response.js b/tools/spectral/ipa/rulesets/functions/deleteMethod204Response.js index c907589bc5..2c947ba5f2 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethod204Response.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethod204Response.js @@ -12,12 +12,12 @@ const ERROR_MESSAGE = 'DELETE method should return 204 No Content status code.'; * @param {object} context - The context object containing the path */ export default (input, _, { path }) => { - const responses = input.responses; if (hasException(input, RULE_NAME)) { collectException(input, RULE_NAME, path); return; } + const responses = input.responses; if (!responses || !responses['204']) { return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE); } diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethod404Response.js b/tools/spectral/ipa/rulesets/functions/deleteMethod404Response.js index 8cbc3ca180..2a8b700d99 100644 --- a/tools/spectral/ipa/rulesets/functions/deleteMethod404Response.js +++ b/tools/spectral/ipa/rulesets/functions/deleteMethod404Response.js @@ -12,12 +12,12 @@ const ERROR_MESSAGE = 'DELETE method should include 404 status code for not foun * @param {object} context - The context object containing the path */ export default (input, _, { path }) => { - const responses = input.responses; if (hasException(input, RULE_NAME)) { collectException(input, RULE_NAME, path); return; } + const responses = input.responses; if (!responses || !responses['404']) { return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE); } diff --git a/tools/spectral/ipa/rulesets/functions/deleteMethodNoRequestBody.js b/tools/spectral/ipa/rulesets/functions/deleteMethodNoRequestBody.js new file mode 100644 index 0000000000..4e54ae1fb0 --- /dev/null +++ b/tools/spectral/ipa/rulesets/functions/deleteMethodNoRequestBody.js @@ -0,0 +1,25 @@ +import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js'; +import { hasException } from './utils/exceptions.js'; + +const RULE_NAME = 'xgen-IPA-108-delete-request-no-body'; +const ERROR_MESSAGE = 'DELETE method should not have a request body.'; + +/** + * Delete method should not have a request body + * + * @param {object} input - The delete operation object + * @param {object} _ - Unused + * @param {object} context - The context object containing the path + */ +export default (input, _, { path }) => { + if (hasException(input, RULE_NAME)) { + collectException(input, RULE_NAME, path); + return; + } + + const requestBody = input.requestBody; + if (requestBody) { + return collectAndReturnViolation(path, RULE_NAME, ERROR_MESSAGE); + } + return collectAdoption(path, RULE_NAME); +};