lib: validate extension values (#251)

BREAKING CHANGE:

This validates the value of the cloud event extension based on the spec, 
https://github.com/cloudevents/spec/blob/master/spec.md#type-system

Signed-off-by: Lucas Holmquist <lholmqui@redhat.com>
This commit is contained in:
Lucas Holmquist 2020-07-27 13:19:09 -04:00 committed by GitHub
parent 129ec485d9
commit 3c8273f114
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 7 deletions

View File

@ -9,7 +9,7 @@ import {
CloudEventV1OptionalAttributes,
} from "./interfaces";
import { validateV1, validateV03 } from "./spec";
import { ValidationError, isBinary, asBase64 } from "./validation";
import { ValidationError, isBinary, asBase64, isValidType } from "./validation";
import CONSTANTS from "../constants";
import { isString } from "util";
@ -108,6 +108,13 @@ export class CloudEvent implements CloudEventV1, CloudEventV03 {
if (!key.match(/^[a-z0-9]{1,20}$/)) {
throw new ValidationError("invalid extension name");
}
// Value should be spec compliant
// https://github.com/cloudevents/spec/blob/master/spec.md#type-system
if (!isValidType(value)) {
throw new ValidationError("invalid extension value");
}
this[key] = value;
}

View File

@ -81,5 +81,5 @@ export const asData = (data: unknown, contentType: string): string => {
return isBinary(maybeJson) ? asBase64(maybeJson) : maybeJson;
};
export const isValidType = (v: boolean | number | string | Date | Uint32Array): boolean =>
isBoolean(v) || isInteger(v) || isString(v) || isDate(v) || isBinary(v);
export const isValidType = (v: boolean | number | string | Date | Uint32Array | unknown): boolean =>
isBoolean(v) || isInteger(v) || isString(v) || isDate(v) || isBinary(v) || isObject(v);

View File

@ -15,6 +15,8 @@ const ext1Name = "lunch";
const ext1Value = "tacos";
const ext2Name = "supper";
const ext2Value = "sushi";
const ext3Name = "snack";
const ext3Value = { value: "chips" };
const data = {
lunchBreak: "noon",
@ -45,6 +47,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
data,
[ext1Name]: ext1Value,
[ext2Name]: ext2Value,
[ext3Name]: ext3Value,
});
it("Sends a binary 1.0 CloudEvent by default", () => {
@ -59,6 +62,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
// Ensure extensions are handled properly
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext1Name}`]).to.equal(ext1Value);
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext2Name}`]).to.equal(ext2Value);
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext3Name}`].value).to.equal(ext3Value.value);
})
.catch(expect.fail);
});
@ -142,6 +146,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
data,
[ext1Name]: ext1Value,
[ext2Name]: ext2Value,
[ext3Name]: ext3Value,
});
it("Sends a binary 0.3 CloudEvent", () => {
@ -156,6 +161,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
// Ensure extensions are handled properly
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext1Name}`]).to.equal(ext1Value);
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext2Name}`]).to.equal(ext2Value);
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext3Name}`].value).to.equal(ext3Value.value);
})
.catch(expect.fail);
});

View File

@ -87,13 +87,13 @@ describe("CloudEvents Spec v1.0", () => {
expect(cloudevent.cloneWith({ extdate: myDate }).validate()).to.equal(true);
});
// even though the spec doesn't allow object types for
// extensions, it could be JSON. And before a JS CE
// is transmitted across the wire, this value will be
// converted to JSON
it("should be ok when the type is an object", () => {
expect(cloudevent.cloneWith({ objectextension: { some: "object" } }).validate()).to.equal(true);
});
it("should be ok when the type is an string converted from an object", () => {
expect(cloudevent.cloneWith({ objectextension: JSON.stringify({ some: "object" }) }).validate()).to.equal(true);
});
});
describe("The Constraints check", () => {