Fix FTI-3278, missing null type for kong request-validator plugin on nullable true. (#4675)

This commit is contained in:
Filipe Freire authored and GitHub committed 2022-04-19 20:53:20 +00:00
1 parent d039038f80
commit 7e209fa20a
4 files changed
+191 -2

No files matched your search

@@ -0,0 +1,65 @@
{
"_format_version": "1.1",
"services": [
{
"name": "cktest_cards_api",
"protocol": "https",
"host": "alb-dev01.openapi-test.merlin",
"port": 443,
"path": "/",
"plugins": [],
"routes": [
{
"tags": [
"OAS3_import",
"OAS3file_nullable-true.yaml"
],
"name": "cktest_cards_api-get_api1",
"methods": [
"GET"
],
"paths": [
"/cktest/cktest_cards/api1$"
],
"strip_path": false
},
{
"tags": [
"OAS3_import",
"OAS3file_nullable-true.yaml"
],
"name": "cktest_cards_api-post_api1",
"methods": [
"POST"
],
"paths": [
"/cktest/cktest_cards/api1$"
],
"strip_path": false,
"plugins": [
{
"name": "request-validator",
"config": {
"version": "draft4",
"body_schema": "{\"type\":\"object\",\"title\":\"request-body-nullable\",\"description\":\"This object is sent in post application request.\",\"required\":[\"redirectUri\"],\"properties\":{\"redirectUri\":{\"type\":[\"string\",\"null\"],\"nullable\":true}}}",
"allowed_content_types": [
"application/json"
],
"verbose_response": true
},
"tags": [
"OAS3_import",
"OAS3file_nullable-true.yaml"
],
"enabled": true
}
]
}
],
"tags": [
"OAS3_import",
"OAS3file_nullable-true.yaml"
]
}
]
}
@@ -0,0 +1,59 @@
openapi: '3.0.2'
x-kong-name: cktest_cards_api
info:
title: FTI-3278 Test
version: '1.0'
description: A sample API specification for FTI-3278
contact:
email: support@insomnia.rest
servers:
- url: https://alb-dev01.openapi-test.merlin/
tags:
- name: oauth2-credential-flow
paths:
/cktest/cktest_cards/api1:
get:
description: test oauth2
operationId: get_api1
tags:
- oauth2-credential-flow
responses:
'200':
description: OK
post:
description: test oauth2
operationId: post_api1
x-kong-plugin-request-validator:
enabled: true
config:
verbose_response: true
requestBody:
content:
application/json:
schema:
"$ref": "#/components/schemas/request-body-nullable"
responses:
'200':
description: OK
tags:
- oauth2-credential-flow
components:
schemas:
request-body-nullable:
type: object
title: request-body-nullable
description: This object is sent in post application request.
required:
- redirectUri
properties:
redirectUri:
type: string
nullable: true
@@ -1,7 +1,7 @@
import { ParameterSchema, RequestTerminationPlugin, RequestValidatorPlugin, xKongPluginKeyAuth, xKongPluginRequestTermination, xKongPluginRequestValidator } from '../types/kong';
import { OA3Operation, OA3Parameter } from '../types/openapi3';
import { getSpec, pluginDummy, tags, UserDCPlugin } from './jest/test-helpers';
import { ALLOW_ALL_SCHEMA, generateGlobalPlugins, generateRequestValidatorPlugin } from './plugins';
import { ALLOW_ALL_SCHEMA, generateBodyOptions, generateGlobalPlugins, generateRequestValidatorPlugin } from './plugins';
describe('plugins', () => {
describe('generateGlobalPlugins()', () => {
@@ -393,5 +393,63 @@ describe('plugins', () => {
});
});
});
describe('body_schema generateBodyOptions FTI-3278', () => {
it('should keep to properties[].type unchanged nullable is not set', () => {
const generated = generateBodyOptions({
requestBody: {
content: {
'application/json': {
schema: {
properties: {
redirectUri: {
type: 'string',
},
},
},
},
},
},
});
expect(generated.bodySchema).toStrictEqual('{\"properties\":{\"redirectUri\":{\"type\":\"string\"}}}');
});
it('should keep to properties[].type unchanged nullable is false', () => {
const generated = generateBodyOptions({
requestBody: {
content: {
'application/json': {
schema: {
properties: {
redirectUri: {
type: 'string',
nullable: false,
},
},
},
},
},
},
});
expect(generated.bodySchema).toStrictEqual('{\"properties\":{\"redirectUri\":{\"type\":\"string\",\"nullable\":false}}}');
});
it('should append null to properties[].type if nullable is true', () => {
const generated = generateBodyOptions({
requestBody: {
content: {
'application/json': {
schema: {
properties: {
redirectUri: {
type: 'string',
nullable: true,
},
},
},
},
},
},
});
expect(generated.bodySchema).toStrictEqual('{\"properties\":{\"redirectUri\":{\"type\":[\"string\",\"null\"],\"nullable\":true}}}');
});
});
});
});
@@ -85,7 +85,7 @@ const generateParameterSchema = (operation?: OA3Operation) => {
return parameterSchemas;
};
function generateBodyOptions(operation?: OA3Operation) {
export function generateBodyOptions(operation?: OA3Operation) {
let bodySchema;
let allowedContentTypes;
const bodyContent = (operation?.requestBody as OA3RequestBody)?.content;
@@ -96,6 +96,13 @@ function generateBodyOptions(operation?: OA3Operation) {
if (allowedContentTypes.includes(jsonContentType)) {
const item = bodyContent[jsonContentType];
const schema = item.schema;
for (const key in schema.properties) {
// Append 'null' to property type if nullable true, see FTI-3278
if (schema.properties[key].nullable === true) {
schema.properties[key].type = [schema.properties[key].type, 'null'];
}
}
bodySchema = JSON.stringify(item.schema);
}
}