Skip to content

Commit

Permalink
fix validation, restrict map value types
Browse files Browse the repository at this point in the history
  • Loading branch information
bhelx committed Oct 29, 2024
1 parent cfc35d7 commit 541037a
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 42 deletions.
48 changes: 32 additions & 16 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ class V1Validator {
* This saves us a lot of code but might be a little bit slower.
*/
validateNode(node: any) {
//console.log(`Validating ${this.getLocation()}`)
this.validateTypedInterface(node)

if (node && typeof node === 'object') {
// i don't think we need to validate array children
if (Array.isArray(node)) return
Expand Down Expand Up @@ -98,32 +100,46 @@ class V1Validator {
* catch in JSON Schema validation.
*/
validateTypedInterface(prop?: XtpTyped): void {
if (!prop || !prop.type) return
if (!prop) return

const validTypes = ['string', 'number', 'integer', 'boolean', 'object', 'array', 'buffer'];
if (!validTypes.includes(prop.type)) {
if (prop.type && !validTypes.includes(prop.type)) {
this.recordError(`Invalid type '${prop.type}'. Options are: ${validTypes.map(t => `'${t}'`).join(', ')}`)
}

if (!prop.format) {
return;
}
if (prop.format) {
let validFormats: XtpFormat[] = [];
if (prop.type === 'string') {
validFormats = ['date-time', 'byte'];
} else if (prop.type === 'number') {
validFormats = ['float', 'double'];
} else if (prop.type === 'integer') {
validFormats = ['int32', 'int64'];
}

let validFormats: XtpFormat[] = [];
if (prop.type === 'string') {
validFormats = ['date-time', 'byte'];
} else if (prop.type === 'number') {
validFormats = ['float', 'double'];
} else if (prop.type === 'integer') {
validFormats = ['int32', 'int64'];
if (!validFormats.includes(prop.format)) {
this.recordError(`Invalid format ${prop.format} for type ${prop.type}. Valid formats are: ${validFormats.join(', ')}`)
}
}

if (!validFormats.includes(prop.format)) {
this.recordError(`Invalid format ${prop.format} for type ${prop.type}. Valid formats are: ${validFormats.join(', ')}`)
}

if (prop.items) this.validateTypedInterface(prop.items)
if (prop.additionalProperties) this.validateTypedInterface(prop.additionalProperties)

if (prop.additionalProperties) {
this.validateTypedInterface(prop.additionalProperties)

// here we are adding some extra constraints on the value type
// we can relax these later when we can ensure we can cast these properly
this.location.push('additionalProperties')
if (prop.additionalProperties.items) {
this.recordError("Arrays are currently not supported for value types of maps")
}
if (prop.additionalProperties.additionalProperties) {
this.recordError("Maps are currently not supported for value types of maps")
}

this.location.pop()
}
}

getLocation(): string {
Expand Down
16 changes: 5 additions & 11 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,16 @@ test('parse-v1-document', () => {
expect(isString(properties[2])).toBe(true)
expect(properties[2].required).toBe(false)
expect(isInt32(properties[3])).toBe(true)
expect(properties[3].required).toBe(false)
expect(isDateTime(properties[4])).toBe(true)
expect(properties[4].required).toBe(false)
expect(isMap(properties[5])).toBe(true)
expect(properties[5].required).toBe(false)
let mType = properties[5].xtpType as MapType
expect(mType.keyType.kind).toBe('string')
expect(mType.valueType.kind).toBe('string')
expect(isMap(properties[6])).toBe(true)
mType = properties[6].xtpType as MapType
expect(mType.keyType.kind).toBe('string')
expect(mType.valueType.kind).toBe('array')
let vType = mType.valueType as ArrayType
expect(vType.elementType.nullable).toBe(true)
expect(vType.elementType.kind).toBe('date-time')
expect(isInt32(properties[7])).toBe(true)
expect(isInt32(properties[6])).toBe(true)
expect(properties[6].required).toBe(false)

// proves we derferenced it
expect(properties[0].$ref?.enum).toStrictEqual(validV1Doc.components.schemas['GhostGang'].enum)
Expand All @@ -66,8 +63,5 @@ test('parse-v1-document', () => {
// proves we derferenced it
expect(exp.input?.$ref?.enum).toStrictEqual(validV1Doc.components.schemas['Fruit'].enum)
expect(exp.output?.contentType).toBe('application/json')



})

3 changes: 3 additions & 0 deletions tests/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ test("parse-invalid-v1-document", () => {
"#/components/schemas/ComplexObject/properties/aString",
"#/components/schemas/ComplexObject/properties/anInt",
"#/components/schemas/ComplexObject/properties/aNonType",
"#/components/schemas/ComplexObject/properties/aMapOfMapsOfNullableDateArrays/additionalProperties",
"#/components/schemas/ComplexObject/properties/aMapOfMapsOfNullableDateArrays/additionalProperties",
"#/components/schemas/ComplexObject/properties/aMapOfMapsOfNullableDateArrays/additionalProperties/additionalProperties",
])
})

Expand Down
8 changes: 8 additions & 0 deletions tests/schemas/v1-invalid-doc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,12 @@ components:
aNonType:
type: non
description: an int prop
aMapOfMapsOfNullableDateArrays:
description: a weird map, it's too deep to cast correctly right now
additionalProperties:
additionalProperties:
items:
nullable: true
type: string
format: date-time

15 changes: 0 additions & 15 deletions tests/schemas/v1-valid-doc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,9 @@ components:
description: a string map
additionalProperties:
type: string
aMapOfNullableDateArrays:
description: a string map
additionalProperties:
items:
nullable: true
type: string
format: date-time
anIntRef:
description: a ref to an int which is weird but whatever!
$ref: "#/components/schemas/MyInt"
aMapOfMapsOfNullableDateArrays:
description: a weird map
additionalProperties:
additionalProperties:
items:
nullable: true
type: string
format: date-time
MyInt:
description: an int as a schema
type: integer
Expand Down

0 comments on commit 541037a

Please sign in to comment.