Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import testRule from './__helpers__/testRule';
import { DiagnosticSeverity } from '@stoplight/types';

testRule('xgen-IPA-106-create-method-response-code-is-201', [
{
name: 'valid methods',
document: {
paths: {
'/resource': {
post: {
responses: {
201: {},
400: {},
500: {},
},
},
},
'/resource/{id}/subresource': {
post: {
responses: {
201: {},
400: {},
500: {},
},
},
},
'/resource/{id}:customMethod': {
post: {
responses: {
200: {},
400: {},
500: {},
},
},
},
},
},
errors: [],
},
{
name: 'invalid methods',
document: {
paths: {
'/resourceOne': {
post: {
responses: {
200: {},
400: {},
500: {},
},
},
},
'/resourceTwo': {
post: {
responses: {
400: {},
500: {},
},
},
},
'/resourceThree': {
post: {
responses: {
201: {},
200: {},
400: {},
500: {},
},
},
},
},
},
errors: [
{
code: 'xgen-IPA-106-create-method-response-code-is-201',
message:
'The Create method must return a 201 Created response. This method either lacks a 201 Created response or defines a different 2xx status code. http://go/ipa/106',
path: ['paths', '/resourceOne', 'post'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-106-create-method-response-code-is-201',
message:
'The Create method must return a 201 Created response. This method either lacks a 201 Created response or defines a different 2xx status code. http://go/ipa/106',
path: ['paths', '/resourceTwo', 'post'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-106-create-method-response-code-is-201',
message:
'The Create method must return a 201 Created response. This method either lacks a 201 Created response or defines a different 2xx status code. http://go/ipa/106',
path: ['paths', '/resourceThree', 'post'],
severity: DiagnosticSeverity.Warning,
},
],
},
{
name: 'invalid method with exception',
document: {
paths: {
'/resourceOne': {
post: {
responses: {
200: {},
400: {},
500: {},
},
'x-xgen-IPA-exception': {
'xgen-IPA-106-create-method-response-code-is-201': 'Reason',
},
},
},
},
},
errors: [],
},
]);
8 changes: 8 additions & 0 deletions tools/spectral/ipa/rulesets/IPA-106.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ functions:
- createMethodShouldNotHaveQueryParameters
- createMethodRequestBodyIsGetResponse
- createMethodRequestHasNoReadonlyFields
- createMethodResponseCodeIs201Created

rules:
xgen-IPA-106-create-method-request-body-is-request-suffixed-object:
Expand Down Expand Up @@ -43,3 +44,10 @@ rules:
then:
field: '@key'
function: 'createMethodRequestHasNoReadonlyFields'
xgen-IPA-106-create-method-response-code-is-201:
description: 'Create methods must return a 201 Created response code. http://go/ipa/106'
message: '{{error}} http://go/ipa/106'
severity: warn
given: '$.paths[*].post'
then:
function: 'createMethodResponseCodeIs201Created'
1 change: 1 addition & 0 deletions tools/spectral/ipa/rulesets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ For rule definitions, see [IPA-106.yaml](https://github.com/mongodb/openapi/blob
readOnly/writeOnly properties will be ignored. http://go/ipa/106
| warn |
| xgen-IPA-106-create-method-request-has-no-readonly-fields | Create method Request object must not include fields with readOnly:true. http://go/ipa/106 | warn |
| xgen-IPA-106-create-method-response-code-is-201 | Create methods must return a 201 Created response code. http://go/ipa/106 | warn |

### IPA-108

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {
getResourcePathItems,
isCustomMethodIdentifier,
isResourceCollectionIdentifier,
isSingletonResource,
} from './utils/resourceEvaluation.js';
import { hasException } from './utils/exceptions.js';
import {
collectAdoption,
collectAndReturnViolation,
collectException,
handleInternalError,
} from './utils/collectionUtils.js';

const RULE_NAME = 'xgen-IPA-106-create-method-response-code-is-201';
const ERROR_MESSAGE =
'The Create method must return a 201 Created response. This method either lacks a 201 Created response or defines a different 2xx status code.';

export default (input, _, { path, documentInventory }) => {
const oas = documentInventory.resolved;
const resourcePath = path[1];
const resourcePaths = getResourcePathItems(resourcePath, oas.paths);

const isResourceCollection = isResourceCollectionIdentifier(resourcePath) && !isSingletonResource(resourcePaths);
if (isCustomMethodIdentifier(resourcePath) || !isResourceCollection) {
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);
}
collectAdoption(path, RULE_NAME);
};

function checkViolationsAndReturnErrors(input, path) {
try {
const responses = input.responses;

// If there is no 201 response, return a violation
if (!responses || !responses['201']) {
return [{ path, message: ERROR_MESSAGE }];
}

// If there are other 2xx responses that are not 201, return a violation
if (Object.keys(responses).some((key) => key.startsWith('2') && key !== '201')) {
return [{ path, message: ERROR_MESSAGE }];
}

return [];
} catch (e) {
handleInternalError(RULE_NAME, path, e);
}
}
Loading