From e3135cf6d46f23fd1802452470d3738e25f1d20b Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 11 Mar 2025 09:22:34 +0000 Subject: [PATCH 1/2] CLOUDP-271992: Add rule xgen-IPA-105-list-method-response-code-is-200 --- .../listResponseCodeShouldBe200OK.test.js | 163 ++++++++++++++++++ tools/spectral/ipa/ipa-spectral.yaml | 7 +- tools/spectral/ipa/rulesets/IPA-105.yaml | 14 ++ .../listResponseCodeShouldBe200OK.js | 51 ++++++ 4 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 tools/spectral/ipa/__tests__/listResponseCodeShouldBe200OK.test.js create mode 100644 tools/spectral/ipa/rulesets/IPA-105.yaml create mode 100644 tools/spectral/ipa/rulesets/functions/listResponseCodeShouldBe200OK.js diff --git a/tools/spectral/ipa/__tests__/listResponseCodeShouldBe200OK.test.js b/tools/spectral/ipa/__tests__/listResponseCodeShouldBe200OK.test.js new file mode 100644 index 0000000000..87f50cd737 --- /dev/null +++ b/tools/spectral/ipa/__tests__/listResponseCodeShouldBe200OK.test.js @@ -0,0 +1,163 @@ +import testRule from './__helpers__/testRule'; +import { DiagnosticSeverity } from '@stoplight/types'; + +testRule('xgen-IPA-105-list-method-response-code-is-200', [ + { + name: 'valid methods', + document: { + paths: { + '/resource': { + get: { + responses: { + 200: {}, + 400: {}, + 500: {}, + }, + }, + }, + '/resource/{id}': { + get: { + responses: { + 400: {}, + 500: {}, + }, + }, + }, + '/resource/{id}:customMethod': { + get: { + responses: { + 400: {}, + 500: {}, + }, + }, + }, + '/resource/{id}/singleton': { + get: { + responses: { + 400: {}, + 500: {}, + }, + }, + }, + }, + }, + errors: [], + }, + { + name: 'invalid methods', + document: { + paths: { + '/resourceOne': { get: { responses: {} } }, + '/resourceTwo': { + get: { + responses: { + 201: {}, + 400: {}, + 500: {}, + }, + }, + }, + '/resourceThree': { + get: { + responses: { + 400: {}, + 500: {}, + }, + }, + }, + '/resourceFour': { + get: { + responses: { + 200: {}, + 201: {}, + 400: {}, + 500: {}, + }, + }, + }, + }, + }, + errors: [ + { + code: 'xgen-IPA-105-list-method-response-code-is-200', + message: + 'The List method must return a 200 OK response. This method either lacks a 200 OK response or defines a different 2xx status code. http://go/ipa/105', + path: ['paths', '/resourceOne', 'get'], + severity: DiagnosticSeverity.Warning, + }, + { + code: 'xgen-IPA-105-list-method-response-code-is-200', + message: + 'The List method must return a 200 OK response. This method either lacks a 200 OK response or defines a different 2xx status code. http://go/ipa/105', + path: ['paths', '/resourceTwo', 'get'], + severity: DiagnosticSeverity.Warning, + }, + { + code: 'xgen-IPA-105-list-method-response-code-is-200', + message: + 'The List method must return a 200 OK response. This method either lacks a 200 OK response or defines a different 2xx status code. http://go/ipa/105', + path: ['paths', '/resourceThree', 'get'], + severity: DiagnosticSeverity.Warning, + }, + { + code: 'xgen-IPA-105-list-method-response-code-is-200', + message: + 'The List method must return a 200 OK response. This method either lacks a 200 OK response or defines a different 2xx status code. http://go/ipa/105', + path: ['paths', '/resourceFour', 'get'], + severity: DiagnosticSeverity.Warning, + }, + ], + }, + { + name: 'invalid method with exception', + document: { + paths: { + '/resourceOne': { + get: { + 'x-xgen-IPA-exception': { + 'xgen-IPA-105-list-method-response-code-is-200': 'reason', + }, + responses: {}, + }, + }, + '/resourceTwo': { + get: { + 'x-xgen-IPA-exception': { + 'xgen-IPA-105-list-method-response-code-is-200': 'reason', + }, + responses: { + 201: {}, + 400: {}, + 500: {}, + }, + }, + }, + '/resourceThree': { + get: { + 'x-xgen-IPA-exception': { + 'xgen-IPA-105-list-method-response-code-is-200': 'reason', + }, + responses: { + 400: {}, + 500: {}, + }, + }, + }, + '/resourceFour': { + get: { + 'x-xgen-IPA-exception': { + 'xgen-IPA-105-list-method-response-code-is-200': 'reason', + }, + responses: { + 200: {}, + 201: {}, + 400: {}, + 500: {}, + }, + }, + }, + }, + }, + errors: [], + }, +]); diff --git a/tools/spectral/ipa/ipa-spectral.yaml b/tools/spectral/ipa/ipa-spectral.yaml index 0693a5a88e..03bbbbe660 100644 --- a/tools/spectral/ipa/ipa-spectral.yaml +++ b/tools/spectral/ipa/ipa-spectral.yaml @@ -1,12 +1,13 @@ extends: + - ./rulesets/IPA-005.yaml - ./rulesets/IPA-102.yaml - ./rulesets/IPA-104.yaml - - ./rulesets/IPA-005.yaml + - ./rulesets/IPA-105.yaml + - ./rulesets/IPA-106.yaml + - ./rulesets/IPA-108.yaml - ./rulesets/IPA-109.yaml - ./rulesets/IPA-113.yaml - ./rulesets/IPA-123.yaml - - ./rulesets/IPA-106.yaml - - ./rulesets/IPA-108.yaml overrides: - files: diff --git a/tools/spectral/ipa/rulesets/IPA-105.yaml b/tools/spectral/ipa/rulesets/IPA-105.yaml new file mode 100644 index 0000000000..1669c1eb60 --- /dev/null +++ b/tools/spectral/ipa/rulesets/IPA-105.yaml @@ -0,0 +1,14 @@ +# IPA-105: List +# http://go/ipa/105 + +functions: + - listResponseCodeShouldBe200OK + +rules: + xgen-IPA-105-list-method-response-code-is-200: + description: 'The List method must return a 200 OK response. http://go/ipa/105' + message: '{{error}} http://go/ipa/105' + severity: warn + given: '$.paths[*].get' + then: + function: 'listResponseCodeShouldBe200OK' diff --git a/tools/spectral/ipa/rulesets/functions/listResponseCodeShouldBe200OK.js b/tools/spectral/ipa/rulesets/functions/listResponseCodeShouldBe200OK.js new file mode 100644 index 0000000000..1cc3b52c48 --- /dev/null +++ b/tools/spectral/ipa/rulesets/functions/listResponseCodeShouldBe200OK.js @@ -0,0 +1,51 @@ +import { hasException } from './utils/exceptions.js'; +import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js'; +import { + getResourcePathItems, + isResourceCollectionIdentifier, + isSingletonResource, +} from './utils/resourceEvaluation.js'; + +const RULE_NAME = 'xgen-IPA-105-list-method-response-code-is-200'; +const ERROR_MESSAGE = + 'The List method must return a 200 OK response. This method either lacks a 200 OK response or defines a different 2xx status code.'; + +export default (input, _, { path, documentInventory }) => { + const resourcePath = path[1]; + const oas = documentInventory.resolved; + + if ( + !isResourceCollectionIdentifier(resourcePath) || + (isResourceCollectionIdentifier(resourcePath) && isSingletonResource(getResourcePathItems(resourcePath, oas.paths))) + ) { + return; + } + if (hasException(input, RULE_NAME)) { + collectException(input, RULE_NAME, path); + return; + } + + const errors = checkViolationsAndReturnErrors(input, path); + + if (errors.length !== 0) { + return collectAndReturnViolation(path, RULE_NAME, errors); + } + return collectAdoption(path, RULE_NAME); +}; + +function checkViolationsAndReturnErrors(input, path) { + if (input['responses']) { + const responses = input['responses']; + + // If there is no 200 response, return a violation + if (!responses['200']) { + return [{ path, message: ERROR_MESSAGE }]; + } + + // If there are other 2xx responses that are not 200, return a violation + if (Object.keys(responses).some((key) => key.startsWith('2') && key !== '200')) { + return [{ path, message: ERROR_MESSAGE }]; + } + } + return []; +} From aa5df6ac9c614d222f0fb5d5c0ccfa0cc5d68b2c Mon Sep 17 00:00:00 2001 From: Lovisa Berggren Date: Tue, 11 Mar 2025 09:45:30 +0000 Subject: [PATCH 2/2] CLOUDP-271992: Docs --- tools/spectral/ipa/rulesets/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/spectral/ipa/rulesets/README.md b/tools/spectral/ipa/rulesets/README.md index 080158f265..4062afb0cd 100644 --- a/tools/spectral/ipa/rulesets/README.md +++ b/tools/spectral/ipa/rulesets/README.md @@ -37,6 +37,14 @@ For rule definitions, see [IPA-104.yaml](https://github.com/mongodb/openapi/blob | xgen-IPA-104-get-method-response-has-no-input-fields | The Get method response object must not include writeOnly properties (fields that should be used only on creation or update, ie output fields). http://go/ipa/104 | warn | | xgen-IPA-104-get-method-no-request-body | The Get method request must not include a body. http://go/ipa/104 | warn | +### IPA-105 + +For rule definitions, see [IPA-105.yaml](https://github.com/mongodb/openapi/blob/main/tools/spectral/ipa/rulesets/IPA-105.yaml). + +| Rule Name | Description | Severity | +| --------------------------------------------- | ---------------------------------------------------------------- | -------- | +| xgen-IPA-105-list-method-response-code-is-200 | The List method must return a 200 OK response. http://go/ipa/105 | warn | + ### IPA-106 For rule definitions, see [IPA-106.yaml](https://github.com/mongodb/openapi/blob/main/tools/spectral/ipa/rulesets/IPA-106.yaml).