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
Expand Up @@ -402,6 +402,32 @@ testRule('xgen-IPA-107-update-method-request-body-is-get-method-response', [
},
},
},
'/resource/{id}/singleton': {
get: {
responses: {
200: {
content: {
'application/vnd.atlas.2023-01-01+json': {
schema: {
$ref: '#/components/schemas/SchemaOne',
},
},
},
},
},
},
patch: {
requestBody: {
content: {
'application/vnd.atlas.2023-01-01+json': {
schema: {
$ref: '#/components/schemas/SchemaThree',
},
},
},
},
},
},
},
},
errors: [
Expand Down Expand Up @@ -517,6 +543,20 @@ testRule('xgen-IPA-107-update-method-request-body-is-get-method-response', [
],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-107-update-method-request-body-is-get-method-response',
message:
'The request body schema properties of the Update method must match the response body schema properties of the Get method.',
path: [
'paths',
'/resource/{id}/singleton',
'patch',
'requestBody',
'content',
'application/vnd.atlas.2023-01-01+json',
],
severity: DiagnosticSeverity.Warning,
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,30 @@ testRule('xgen-IPA-107-update-method-request-has-no-readonly-fields', [
},
},
},
'/resource/{id}/singleton': {
patch: {
requestBody: {
content: {
'application/vnd.atlas.2023-01-01+json': {
schema: {
$ref: '#/components/schemas/SchemaWithReadOnly',
},
},
},
},
},
put: {
requestBody: {
content: {
'application/vnd.atlas.2023-01-01+json': {
schema: {
$ref: '#/components/schemas/SchemaWithReadOnly',
},
},
},
},
},
},
},
},
errors: [
Expand Down Expand Up @@ -182,6 +206,34 @@ testRule('xgen-IPA-107-update-method-request-has-no-readonly-fields', [
path: ['paths', '/resource/{id}', 'put', 'requestBody', 'content', 'application/vnd.atlas.2024-01-01+json'],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-107-update-method-request-has-no-readonly-fields',
message:
'The Update method request object must not include input fields (readOnly properties). Found readOnly property at: id. ',
path: [
'paths',
'/resource/{id}/singleton',
'patch',
'requestBody',
'content',
'application/vnd.atlas.2023-01-01+json',
],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-107-update-method-request-has-no-readonly-fields',
message:
'The Update method request object must not include input fields (readOnly properties). Found readOnly property at: id. ',
path: [
'paths',
'/resource/{id}/singleton',
'put',
'requestBody',
'content',
'application/vnd.atlas.2023-01-01+json',
],
severity: DiagnosticSeverity.Warning,
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,34 @@ testRule('xgen-IPA-107-update-method-response-is-get-method-response', [
},
},
},
'/resourceFour/{id}/singleton': {
get: {
responses: {
200: {
content: {
'application/vnd.atlas.2024-01-05+json': {
schema: {
$ref: '#/components/schemas/ResourceSchema',
},
},
},
},
},
},
patch: {
responses: {
200: {
content: {
'application/vnd.atlas.2024-01-05+json': {
schema: {
$ref: '#/components/schemas/OtherSchema',
},
},
},
},
},
},
},
},
components: componentSchemas,
},
Expand Down Expand Up @@ -375,6 +403,20 @@ testRule('xgen-IPA-107-update-method-response-is-get-method-response', [
],
severity: DiagnosticSeverity.Warning,
},
{
code: 'xgen-IPA-107-update-method-response-is-get-method-response',
message: 'The schema in the Update method response must be the same schema as the response of the Get method.',
path: [
'paths',
'/resourceFour/{id}/singleton',
'patch',
'responses',
'200',
'content',
'application/vnd.atlas.2024-01-05+json',
],
severity: DiagnosticSeverity.Warning,
},
],
},
{
Expand Down
8 changes: 4 additions & 4 deletions tools/spectral/ipa/rulesets/IPA-107.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ rules:

##### Implementation details

Validation checks the PATCH/PUT methods for single resource paths and singleton resources.
Validation checks the PATCH/PUT methods for single resource paths and [singleton resources](https://go/ipa/113).

- Query parameters `envelope` and `pretty` are exempt from this rule
- Operation objects with `x-xgen-IPA-exception` for this rule are excluded from validation
Expand Down Expand Up @@ -46,7 +46,7 @@ rules:

##### Implementation details
Rule checks for the following conditions:
- Applies only to single resource paths with JSON content types
- Applies only to single resource paths and singleton resources with JSON content types
- Ignores singleton resources and responses without a schema
- Validation ignores resources without a Get method
- Fails if the Get method doesn't have a schema reference or if the schemas don't match
Expand All @@ -63,7 +63,7 @@ rules:

##### Implementation details
Rule checks for the following conditions:
- Applies only to Update methods on single resource paths
- Applies only to Update methods on single resource paths or singleton resources
- Applies only to JSON content types
- Searches through the request schema to find any properties marked with readOnly attribute
- Fails if any readOnly properties are found in the request schema
Expand All @@ -79,7 +79,7 @@ rules:

##### Implementation details

Validation checks the PATCH/PUT methods for single resource paths.
Validation checks the PATCH/PUT methods for single resource paths and singleton resources.
- Validation ignores resources without a Get method.
- `readOnly:true` properties of Get method response will be ignored.
- `writeOnly:true` properties of Update method request will be ignored.
Expand Down
8 changes: 4 additions & 4 deletions tools/spectral/ipa/rulesets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ Rules are based on [http://go/ipa/IPA-107](http://go/ipa/IPA-107).
![warn](https://img.shields.io/badge/warning-yellow)
Update operations must not accept query parameters.
##### Implementation details
Validation checks the PATCH/PUT methods for single resource paths and singleton resources.
Validation checks the PATCH/PUT methods for single resource paths and [singleton resources](https://go/ipa/113).

- Query parameters `envelope` and `pretty` are exempt from this rule
- Operation objects with `x-xgen-IPA-exception` for this rule are excluded from validation
Expand All @@ -301,7 +301,7 @@ Validation checks the PATCH/PUT methods for single resource paths and [singleton
![warn](https://img.shields.io/badge/warning-yellow)
The response body of the Update method should consist of the same resource object returned by the Get method.
##### Implementation details Rule checks for the following conditions:
- Applies only to single resource paths with JSON content types
- Applies only to single resource paths and singleton resources with JSON content types
- Ignores singleton resources and responses without a schema
- Validation ignores resources without a Get method
- Fails if the Get method doesn't have a schema reference or if the schemas don't match
Expand All @@ -313,7 +313,7 @@ Update method Request object must not include fields with readOnly:true.

##### Implementation details
Rule checks for the following conditions:
- Applies only to Update methods on single resource paths
- Applies only to Update methods on single resource paths or singleton resources
- Applies only to JSON content types
- Searches through the request schema to find any properties marked with readOnly attribute
- Fails if any readOnly properties are found in the request schema
Expand All @@ -325,7 +325,7 @@ The request body must contain the resource being updated, i.e. the resource or p

##### Implementation details

Validation checks the PATCH/PUT methods for single resource paths.
Validation checks the PATCH/PUT methods for single resource paths and singleton resources.
- Validation ignores resources without a Get method.
- `readOnly:true` properties of Get method response will be ignored.
- `writeOnly:true` properties of Update method request will be ignored.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { isSingleResourceIdentifier } from './utils/resourceEvaluation.js';
import {
getResourcePathItems,
isResourceCollectionIdentifier,
isSingleResourceIdentifier,
isSingletonResource,
} from './utils/resourceEvaluation.js';
import { resolveObject } from './utils/componentUtils.js';
import { hasException } from './utils/exceptions.js';
import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js';
Expand All @@ -20,9 +25,14 @@ export default (input, _, { path, documentInventory }) => {
const oas = documentInventory.resolved;
const unresolvedOas = documentInventory.unresolved;
const resourcePath = path[1];
let mediaType = input;
const mediaType = input;
const resourcePathItems = getResourcePathItems(resourcePath, oas.paths);

if (!isSingleResourceIdentifier(resourcePath) || !mediaType.endsWith('json')) {
if (
!input.endsWith('json') ||
(!isSingleResourceIdentifier(resourcePath) &&
!(isResourceCollectionIdentifier(resourcePath) && isSingletonResource(resourcePathItems)))
) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { isSingleResourceIdentifier } from './utils/resourceEvaluation.js';
import {
getResourcePathItems,
isResourceCollectionIdentifier,
isSingleResourceIdentifier,
isSingletonResource,
} from './utils/resourceEvaluation.js';
import { resolveObject } from './utils/componentUtils.js';
import { hasException } from './utils/exceptions.js';
import { collectAdoption, collectAndReturnViolation, collectException } from './utils/collectionUtils.js';
Expand All @@ -17,8 +22,13 @@ const ERROR_MESSAGE = 'The Update method request object must not include input f
export default (input, _, { path, documentInventory }) => {
const resourcePath = path[1];
const oas = documentInventory.resolved;
const resourcePathItems = getResourcePathItems(resourcePath, oas.paths);

if (!isSingleResourceIdentifier(resourcePath) || !input.endsWith('json')) {
if (
!input.endsWith('json') ||
(!isSingleResourceIdentifier(resourcePath) &&
!(isResourceCollectionIdentifier(resourcePath) && isSingletonResource(resourcePathItems)))
) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { isSingleResourceIdentifier } from './utils/resourceEvaluation.js';
import {
getResourcePathItems,
isResourceCollectionIdentifier,
isSingleResourceIdentifier,
isSingletonResource,
} from './utils/resourceEvaluation.js';
import { resolveObject } from './utils/componentUtils.js';
import { hasException } from './utils/exceptions.js';
import {
Expand All @@ -24,8 +29,13 @@ export default (input, _, { path, documentInventory }) => {
const oas = documentInventory.unresolved;
const resourcePath = path[1];
const mediaType = input;
const resourcePathItems = getResourcePathItems(resourcePath, oas.paths);

if (!mediaType.endsWith('json') || !isSingleResourceIdentifier(resourcePath)) {
if (
!mediaType.endsWith('json') ||
(!isSingleResourceIdentifier(resourcePath) &&
!(isResourceCollectionIdentifier(resourcePath) && isSingletonResource(resourcePathItems)))
) {
return;
}

Expand Down
Loading