Skip to content

Commit 1758c33

Browse files
CLOUDP-304958: IPA rule singleton must not have delete
1 parent 08dd612 commit 1758c33

File tree

5 files changed

+142
-0
lines changed

5 files changed

+142
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import testRule from './__helpers__/testRule';
2+
import { DiagnosticSeverity } from '@stoplight/types';
3+
4+
testRule('xgen-IPA-113-singleton-must-not-have-delete-method', [
5+
{
6+
name: 'valid resources',
7+
document: {
8+
paths: {
9+
'/resource': {
10+
post: {},
11+
get: {},
12+
},
13+
'/resource/{exampleId}': {
14+
get: {},
15+
patch: {},
16+
delete: {},
17+
},
18+
'/resource/{exampleId}/singleton': {
19+
get: {},
20+
patch: {},
21+
},
22+
},
23+
},
24+
errors: [],
25+
},
26+
{
27+
name: 'invalid resource',
28+
document: {
29+
paths: {
30+
'/resource/{exampleId}/singleton': {
31+
delete: {},
32+
},
33+
},
34+
},
35+
errors: [
36+
{
37+
code: 'xgen-IPA-113-singleton-must-not-have-delete-method',
38+
message:
39+
'Singleton resources must not define the Delete standard method. If this is not a singleton resource, please implement all CRUDL methods.',
40+
path: ['paths', '/resource/{exampleId}/singleton'],
41+
severity: DiagnosticSeverity.Warning,
42+
},
43+
],
44+
},
45+
{
46+
name: 'invalid resources with exceptions',
47+
document: {
48+
paths: {
49+
'/resource/{exampleId}/singleton': {
50+
delete: {},
51+
'x-xgen-IPA-exception': {
52+
'xgen-IPA-113-singleton-must-not-have-delete-method': 'reason',
53+
},
54+
},
55+
},
56+
},
57+
errors: [],
58+
},
59+
]);

tools/spectral/ipa/rulesets/IPA-113.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
functions:
55
- IPA113SingletonHasNoId
6+
- IPA113SingletonHasNoDeleteMethod
67

78
rules:
89
xgen-IPA-113-singleton-must-not-have-id:
@@ -21,3 +22,16 @@ rules:
2122
given: '$.paths[*]'
2223
then:
2324
function: 'IPA113SingletonHasNoId'
25+
xgen-IPA-113-singleton-must-not-have-delete-method:
26+
description: |
27+
Singleton resources must not define the Delete standard method
28+
29+
##### Implementation details
30+
Rule checks for the following conditions:
31+
- Applies only to singleton resources
32+
- Checks that the resource does not have a DELETE method defined
33+
message: '{{error}} https://mdb.link/mongodb-atlas-openapi-validation#xgen-IPA-113-singleton-must-not-have-delete-method'
34+
severity: warn
35+
given: '$.paths[*]'
36+
then:
37+
function: 'IPA113SingletonHasNoDeleteMethod'

tools/spectral/ipa/rulesets/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,16 @@ Rule checks for the following conditions:
482482
- Verifies that no schema contains 'id' or '_id' properties in their object definitions
483483
- Fails if any response schema contains these identifier properties
484484

485+
#### xgen-IPA-113-singleton-must-not-have-delete-method
486+
487+
![warn](https://img.shields.io/badge/warning-yellow)
488+
Singleton resources must not define the Delete standard method
489+
490+
##### Implementation details
491+
Rule checks for the following conditions:
492+
- Applies only to singleton resources
493+
- Checks that the resource does not have a DELETE method defined
494+
485495

486496

487497
### IPA-123
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {
2+
getResourcePathItems,
3+
isSingletonResource,
4+
isResourceCollectionIdentifier,
5+
hasDeleteMethod,
6+
} from './utils/resourceEvaluation.js';
7+
import { hasException } from './utils/exceptions.js';
8+
import {
9+
collectAdoption,
10+
collectAndReturnViolation,
11+
collectException,
12+
handleInternalError,
13+
} from './utils/collectionUtils.js';
14+
15+
const RULE_NAME = 'xgen-IPA-113-singleton-must-not-have-delete-method';
16+
const ERROR_MESSAGE =
17+
'Singleton resources must not define the Delete standard method. If this is not a singleton resource, please implement all CRUDL methods.';
18+
19+
export default (input, opts, { path, documentInventory }) => {
20+
const oas = documentInventory.resolved;
21+
const resourcePath = path[1];
22+
const resourcePathItems = getResourcePathItems(resourcePath, oas.paths);
23+
24+
if (!(isResourceCollectionIdentifier(resourcePath) && isSingletonResource(resourcePathItems))) {
25+
return;
26+
}
27+
28+
if (hasException(input, RULE_NAME)) {
29+
collectException(input, RULE_NAME, path);
30+
return;
31+
}
32+
33+
const errors = checkViolationsAndReturnErrors(input, path);
34+
if (errors.length !== 0) {
35+
return collectAndReturnViolation(path, RULE_NAME, errors);
36+
}
37+
collectAdoption(path, RULE_NAME);
38+
};
39+
40+
function checkViolationsAndReturnErrors(input, path) {
41+
try {
42+
if (hasDeleteMethod(input)) {
43+
return [{ path, message: ERROR_MESSAGE }];
44+
}
45+
return [];
46+
} catch (e) {
47+
handleInternalError(RULE_NAME, path, e);
48+
}
49+
}

tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ export function hasPostMethod(pathObject) {
102102
return Object.keys(pathObject).includes('post');
103103
}
104104

105+
/**
106+
* Checks if a path object has a DELETE method
107+
*
108+
* @param pathObject the path object to evaluate
109+
* @returns {boolean}
110+
*/
111+
export function hasDeleteMethod(pathObject) {
112+
return Object.keys(pathObject).includes('delete');
113+
}
114+
105115
/**
106116
* Get all path items for a resource based on the path for the resource collection
107117
* For example, resource collection path '/resource' may return path items for ['/resource', '/resource{id}', '/resource{id}:customMethod']

0 commit comments

Comments
 (0)