Skip to content

Commit

Permalink
fix: Required properties warning now checked in child refs (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
rmkeezer committed Aug 26, 2020
1 parent e547026 commit 5f2ae83
Show file tree
Hide file tree
Showing 4 changed files with 333 additions and 17 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ The supported rules are described below:
| property_case_collision | Flag any property with a `name` that is identical to another property's `name` except for the naming convention | shared |
| enum_case_convention | Flag any enum with a `value` that does not follow a given case convention. snake_case_only must be 'off' to use. | shared |
| json_or_param_binary_string | Flag parameters or application/json request/response bodies with schema type: string, format: binary. | oas3 |
| undefined_required_properties| Flag any schema with undefined required properties | shared |

##### security_definitions
| Rule | Description | Spec |
Expand Down Expand Up @@ -383,6 +384,7 @@ The default values for each rule are described below.
| Rule | Default |
| --------------------------- | ------- |
| json_or_param_binary_string | warning |
| undefined_required_properties | warning |

##### shared

Expand Down
3 changes: 2 additions & 1 deletion src/.defaultsForValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ const defaults = {
'inconsistent_property_type': 'warning',
'property_case_convention': [ 'error', 'lower_snake_case'],
'property_case_collision': 'error',
'enum_case_convention': [ 'warning', 'lower_snake_case']
'enum_case_convention': [ 'warning', 'lower_snake_case'],
'undefined_required_properties': 'warning'
},
'walker': {
'no_empty_descriptions': 'error',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,43 @@

const { walk } = require('../../../utils');
const MessageCarrier = require('../../../utils/messageCarrier');
const at = require('lodash/at');

module.exports.validate = function({ jsSpec }) {
const reduceObj = function(jsSpec, obj) {
if (obj['$ref']) {
const objPath = obj['$ref'].split('/');
objPath.shift();
return reduceObj(jsSpec, at(jsSpec, [objPath])[0]);
}
return obj;
};

const checkReqProp = function(jsSpec, obj, requiredProp) {
obj = reduceObj(jsSpec, obj);
if (obj.properties && obj.properties[requiredProp]) {
return true;
} else if (Array.isArray(obj.anyOf) || Array.isArray(obj.oneOf)) {
const childList = obj.anyOf || obj.oneOf;
let reqPropDefined = true;
childList.forEach((childObj) => {
if (!checkReqProp(jsSpec, childObj, requiredProp)) {
reqPropDefined = false;
}
});
return reqPropDefined;
} else if (Array.isArray(obj.allOf)) {
let reqPropDefined = false;
obj.allOf.forEach((childObj) => {
if (checkReqProp(jsSpec, childObj, requiredProp)) {
reqPropDefined = true;
}
});
return reqPropDefined;
}
return false;
}

module.exports.validate = function({ jsSpec }, config) {
const messages = new MessageCarrier();

walk(jsSpec, [], function(obj, path) {
Expand All @@ -36,13 +71,14 @@ module.exports.validate = function({ jsSpec }) {
}

// Assertation 2
const undefinedRequiredProperties = config.schemas.undefined_required_properties;
if (Array.isArray(obj.required)) {
obj.required.forEach((requiredProp, i) => {
if (!obj.properties || !obj.properties[requiredProp]) {
if (!checkReqProp(jsSpec, obj, requiredProp)) {
messages.addMessage(
path.concat([`required[${i}]`]).join('.'),
"Schema properties specified as 'required' must be defined",
'error'
"Schema properties specified as 'required' should be defined",
undefinedRequiredProperties
);
}
});
Expand Down
Loading

0 comments on commit 5f2ae83

Please sign in to comment.