Skip to content

Commit

Permalink
added nullcheck for decoded object.
Browse files Browse the repository at this point in the history
Signed-off-by: Dave Shanley <dave@quobix.com>
  • Loading branch information
daveshanley committed Jul 30, 2023
1 parent 98029fc commit 64f44a5
Showing 1 changed file with 74 additions and 72 deletions.
146 changes: 74 additions & 72 deletions schema_validation/validate_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,94 +84,96 @@ func validateSchema(schema *base.Schema, payload []byte, decodedObject interface
jsch, _ := compiler.Compile("schema.json")

// 4. validate the object against the schema
scErrs := jsch.Validate(decodedObject)
if scErrs != nil {
var schemaValidationErrors []*errors.SchemaValidationFailure

// check for invalid JSON type errors.
if _, ok := scErrs.(jsonschema.InvalidJSONTypeError); ok {
violation := &errors.SchemaValidationFailure{
Reason: scErrs.Error(),
Location: "unavailable", // we don't have a location for this error, so we'll just say it's unavailable.
if decodedObject != nil {
scErrs := jsch.Validate(decodedObject)
if scErrs != nil {
var schemaValidationErrors []*errors.SchemaValidationFailure

// check for invalid JSON type errors.
if _, ok := scErrs.(jsonschema.InvalidJSONTypeError); ok {
violation := &errors.SchemaValidationFailure{
Reason: scErrs.Error(),
Location: "unavailable", // we don't have a location for this error, so we'll just say it's unavailable.
}
schemaValidationErrors = append(schemaValidationErrors, violation)
}
schemaValidationErrors = append(schemaValidationErrors, violation)
}

if jk, ok := scErrs.(*jsonschema.ValidationError); ok {
if jk, ok := scErrs.(*jsonschema.ValidationError); ok {

// flatten the validationErrors
schFlatErrs := jk.BasicOutput().Errors
// flatten the validationErrors
schFlatErrs := jk.BasicOutput().Errors

for q := range schFlatErrs {
er := schFlatErrs[q]
if er.KeywordLocation == "" || strings.HasPrefix(er.Error, "doesn't validate with") {
continue // ignore this error, it's useless tbh, utter noise.
}
if er.Error != "" {
for q := range schFlatErrs {
er := schFlatErrs[q]
if er.KeywordLocation == "" || strings.HasPrefix(er.Error, "doesn't validate with") {
continue // ignore this error, it's useless tbh, utter noise.
}
if er.Error != "" {

// re-encode the schema.
var renderedNode yaml.Node
_ = yaml.Unmarshal(renderedSchema, &renderedNode)
// re-encode the schema.
var renderedNode yaml.Node
_ = yaml.Unmarshal(renderedSchema, &renderedNode)

// locate the violated property in the schema
located := LocateSchemaPropertyNodeByJSONPath(renderedNode.Content[0], er.KeywordLocation)
// locate the violated property in the schema
located := LocateSchemaPropertyNodeByJSONPath(renderedNode.Content[0], er.KeywordLocation)

// extract the element specified by the instance
val := instanceLocationRegex.FindStringSubmatch(er.InstanceLocation)
var referenceObject string
// extract the element specified by the instance
val := instanceLocationRegex.FindStringSubmatch(er.InstanceLocation)
var referenceObject string

if len(val) > 0 {
referenceIndex, _ := strconv.Atoi(val[1])
if reflect.ValueOf(decodedObject).Type().Kind() == reflect.Slice {
found := decodedObject.([]any)[referenceIndex]
recoded, _ := json.MarshalIndent(found, "", " ")
referenceObject = string(recoded)
if len(val) > 0 {
referenceIndex, _ := strconv.Atoi(val[1])
if reflect.ValueOf(decodedObject).Type().Kind() == reflect.Slice {
found := decodedObject.([]any)[referenceIndex]
recoded, _ := json.MarshalIndent(found, "", " ")
referenceObject = string(recoded)
}
}
if referenceObject == "" {
referenceObject = string(payload)
}
}
if referenceObject == "" {
referenceObject = string(payload)
}

violation := &errors.SchemaValidationFailure{
Reason: er.Error,
Location: er.InstanceLocation,
DeepLocation: er.KeywordLocation,
AbsoluteLocation: er.AbsoluteKeywordLocation,
ReferenceSchema: string(renderedSchema),
ReferenceObject: referenceObject,
OriginalError: jk,
}
// if we have a location within the schema, add it to the error
if located != nil {
line := located.Line
// if the located node is a map or an array, then the actual human interpretable
// line on which the violation occurred is the line of the key, not the value.
if located.Kind == yaml.MappingNode || located.Kind == yaml.SequenceNode {
if line > 0 {
line--
}
violation := &errors.SchemaValidationFailure{
Reason: er.Error,
Location: er.InstanceLocation,
DeepLocation: er.KeywordLocation,
AbsoluteLocation: er.AbsoluteKeywordLocation,
ReferenceSchema: string(renderedSchema),
ReferenceObject: referenceObject,
OriginalError: jk,
}
// if we have a location within the schema, add it to the error
if located != nil {
line := located.Line
// if the located node is a map or an array, then the actual human interpretable
// line on which the violation occurred is the line of the key, not the value.
if located.Kind == yaml.MappingNode || located.Kind == yaml.SequenceNode {
if line > 0 {
line--
}
}

// location of the violation within the rendered schema.
violation.Line = line
violation.Column = located.Column
// location of the violation within the rendered schema.
violation.Line = line
violation.Column = located.Column
}
schemaValidationErrors = append(schemaValidationErrors, violation)
}
schemaValidationErrors = append(schemaValidationErrors, violation)
}
}
}

// add the error to the list
validationErrors = append(validationErrors, &errors.ValidationError{
ValidationType: helpers.Schema,
Message: "schema does not pass validation",
Reason: "Schema failed to validate against the contract requirements",
SpecLine: schema.GoLow().Type.KeyNode.Line,
SpecCol: schema.GoLow().Type.KeyNode.Column,
SchemaValidationErrors: schemaValidationErrors,
HowToFix: errors.HowToFixInvalidSchema,
Context: string(renderedSchema), // attach the rendered schema to the error
})
// add the error to the list
validationErrors = append(validationErrors, &errors.ValidationError{
ValidationType: helpers.Schema,
Message: "schema does not pass validation",
Reason: "Schema failed to validate against the contract requirements",
SpecLine: schema.GoLow().Type.KeyNode.Line,
SpecCol: schema.GoLow().Type.KeyNode.Column,
SchemaValidationErrors: schemaValidationErrors,
HowToFix: errors.HowToFixInvalidSchema,
Context: string(renderedSchema), // attach the rendered schema to the error
})
}
}
if len(validationErrors) > 0 {
return false, validationErrors
Expand Down

0 comments on commit 64f44a5

Please sign in to comment.