Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add schema validation support for more json-schema version refs (closes #2354) #4390

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions kafka-ui-react-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@types/testing-library__jest-dom": "^5.14.5",
"ace-builds": "^1.7.1",
"ajv": "^8.6.3",
"ajv-draft-04": "^1.0.0",
"ajv-formats": "^2.1.1",
"classnames": "^2.2.6",
"fetch-mock": "^9.11.0",
Expand Down
14 changes: 14 additions & 0 deletions kafka-ui-react-app/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,27 @@ describe('SendMessage utils', () => {
'Error in parsing the "content" field value',
]);
});

// https://github.com/provectus/kafka-ui/issues/2354
it('should successfully validate when schema references json-schema version draft-07', () => {
const schema = `{"type":"object","title":"A","description":"A","$id":"https://example.com/A.json","$schema":"http://json-schema.org/draft-07/schema#","required":["a"],"properties":{"a":{"type":"number"}}}`;
expect(validateBySchema('{"a": 6}', schema, 'key')).toHaveLength(0);
});
it('should successfully validate when schema references json-schema version draft-06', () => {
const schema = `{"type":"object","title":"A","description":"A","$id":"https://example.com/A.json","$schema":"http://json-schema.org/draft-06/schema#","required":["a"],"properties":{"a":{"type":"number"}}}`;
expect(validateBySchema('{"a": 6}', schema, 'key')).toHaveLength(0);
});
it('should successfully validate when schema references json-schema version draft-04', () => {
const schema = `{"type":"object","title":"A","description":"A","id":"https://example.com/A.json","$schema":"http://json-schema.org/draft-04/schema#","required":["a"],"properties":{"a":{"type":"number"}}}`;
expect(validateBySchema('{"a": 6}', schema, 'key')).toHaveLength(0);
});
it('should successfully validate when schema references json-schema version draft-2019-09', () => {
const schema = `{"type":"object","title":"A","description":"A","$id":"https://example.com/A.json","$schema":"https://json-schema.org/draft/2019-09/schema","required":["a"],"properties":{"a":{"type":"number"}}}`;
expect(validateBySchema('{"a": 6}', schema, 'key')).toHaveLength(0);
});
it('should successfully validate when schema references json-schema version draft-2020-12', () => {
const schema = `{"type":"object","title":"A","description":"A","$id":"https://example.com/A.json","$schema":"https://json-schema.org/draft/2020-12/schema","required":["a"],"properties":{"a":{"type":"number"}}}`;
expect(validateBySchema('{"a": 6}', schema, 'key')).toHaveLength(0);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import {
} from 'generated-sources';
import jsf from 'json-schema-faker';
import { compact } from 'lodash';
import Ajv, { DefinedError } from 'ajv/dist/2020';
import Ajv, { DefinedError } from 'ajv';
import Ajv2019 from 'ajv/dist/2019';
import Ajv2020 from 'ajv/dist/2020';
import * as draft6MetaSchema from 'ajv/dist/refs/json-schema-draft-06.json';
import AjvDraft4 from 'ajv-draft-04';
import addFormats from 'ajv-formats';
import upperFirst from 'lodash/upperFirst';

Expand Down Expand Up @@ -54,6 +58,21 @@ export const getSerdeOptions = (items: SerdeDescription[]) => {
return compact(options);
};

const getAjvVersionForSchemaRef = (schemaRef: string) => {
switch (schemaRef) {
case 'https://json-schema.org/draft/2019-09/schema':
return new Ajv2019();
case 'https://json-schema.org/draft/2020-12/schema':
return new Ajv2020();
case 'http://json-schema.org/draft-06/schema#':
return new Ajv().addMetaSchema(draft6MetaSchema);
case 'http://json-schema.org/draft-04/schema#':
return new AjvDraft4();
default:
return new Ajv();
}
};

export const validateBySchema = (
value: string,
schema: string | undefined,
Expand Down Expand Up @@ -82,7 +101,8 @@ export const validateBySchema = (
return [`Error in parsing the "${type}" field value`];
}
try {
const ajv = new Ajv();
const schemaRef = parsedSchema.$schema;
const ajv = getAjvVersionForSchemaRef(schemaRef);
addFormats(ajv);
const validate = ajv.compile(parsedSchema);
validate(parsedValue);
Expand Down
Loading