WIP, make strict-mode response validation optional

master
Sven Slootweg 2 years ago
parent e0fea190ce
commit 80fbb17b9b

@ -5,7 +5,9 @@ const required = require("@validatem/required");
const isEvent = require("../is-event");
const isMatrixID = require("../is-matrix-id");
module.exports = {
... isEvent,
sender: [ required, isMatrixID ]
module.exports = function isDeviceEvent(strict = false, extraFields = {}) {
return isEvent(strict, {
sender: [ required, isMatrixID ],
... extraFields
});
};

@ -3,8 +3,18 @@
const required = require("@validatem/required");
const isString = require("@validatem/is-string");
const isPlainObject = require("@validatem/is-plain-object");
const allowExtraProperties = require("@validatem/allow-extra-properties");
module.exports = {
module.exports = function isEvent(strict = false, extraFields = {}) {
let fields = {
type: [ required, isString ],
content: [ required, isPlainObject ]
content: [ required, isPlainObject ],
... extraFields
};
if (strict) {
return fields;
} else {
return allowExtraProperties(fields);
}
};

@ -8,12 +8,15 @@ const isTimelineEvent = require("../is-timeline-event");
const isStateEvent = require("../is-state-event");
const optionalArray = require("../optional-array");
let isTimelineList = arrayOf([ required, isTimelineEvent ]);
let isStateList = arrayOf([ required, isStateEvent ]);
module.exports = function isMessagesResponse(strict = false, extraFields = {}) {
// FIXME: Expand validation rules affected by 'strict' setting? eg. allowing extra properties in the messages response itself
let isTimelineList = arrayOf([ required, isTimelineEvent(strict, extraFields) ]);
let isStateList = arrayOf([ required, isStateEvent(strict, extraFields) ]);
module.exports = {
return {
start: [ required, isString ],
end: [ isString ],
chunk: optionalArray(isTimelineList),
state: optionalArray(isStateList)
};
};

@ -6,7 +6,9 @@ const isEvent = require("../is-event");
const isMatrixID = require("../is-matrix-id");
// NOTE: Unspecced, see https://github.com/matrix-org/matrix-doc/issues/2680 - this would normally just be `isEvent` as per the spec
module.exports = {
... isEvent,
sender: [ required, isMatrixID ]
module.exports = function isPresenceEvent(strict = false, extraFields = {}) {
return isEvent(strict, {
sender: [ required, isMatrixID ],
... extraFields
});
};

@ -12,8 +12,8 @@ const isRoomID = require("../is-room-id");
const optionalObject = require("../optional-object");
const isPaginatedChunkOf = require("../is-paginated-chunk-of");
module.exports = {
... isEvent,
module.exports = function isRoomEvent(strict = false, extraFields = {}) {
return isEvent(strict, {
event_id: [ required, isString ],
sender: [ required, isMatrixID ],
origin_server_ts: [ required, isInteger ],
@ -64,5 +64,7 @@ module.exports = {
sender: [ required, isMatrixID ]
}
}
})
}),
... extraFields
});
};

@ -3,14 +3,15 @@
const required = require("@validatem/required");
const isString = require("@validatem/is-string");
const isPlainObject = require("@validatem/is-plain-object");
const isInteger = require("@validatem/is-integer");
const isRoomEvent = require("../is-room-event");
module.exports = {
... isRoomEvent,
module.exports = function isStateEvent(strict = false, extraFields = {}) {
return isRoomEvent(strict, {
state_key: [ required, isString ],
prev_content: isPlainObject,
// Spec violation by Synapse: https://github.com/matrix-org/synapse/issues/6226
membership: [ isString ]
membership: [ isString ],
... extraFields
});
};

@ -6,8 +6,10 @@ const isString = require("@validatem/is-string");
const isEvent = require("../is-event");
const isMatrixID = require("../is-matrix-id");
module.exports = {
... isEvent,
module.exports = function isDeviceEvent(strict = false, extraFields = {}) {
return isEvent(strict, {
state_key: [ required, isString ],
sender: [ required, isMatrixID ]
sender: [ required, isMatrixID ],
... extraFields
});
};

@ -21,14 +21,16 @@ const isMatrixID = require("../is-matrix-id");
const optionalObject = require("../optional-object");
const optionalArray = require("../optional-array");
let isStateList = arrayOf([ required, isStateEvent ]);
let isEventList = arrayOf([ required, isEvent ]);
let isPresenceEventList = arrayOf([ required, isPresenceEvent ]);
let isStrippedEventList = arrayOf([ required, isStrippedEvent ]);
let isDeviceEventList = arrayOf([ required, isDeviceEvent ]);
let isTimelineList = arrayOf([ required, isTimelineEvent ]);
module.exports = function isSyncResponse(strict = false) {
// FIXME: Expand validation rules affected by 'strict' setting? eg. allowing extra properties in the sync response itself
let isStateList = arrayOf([ required, isStateEvent(strict) ]);
let isEventList = arrayOf([ required, isEvent(strict) ]);
let isPresenceEventList = arrayOf([ required, isPresenceEvent(strict) ]);
let isStrippedEventList = arrayOf([ required, isStrippedEvent(strict) ]);
let isDeviceEventList = arrayOf([ required, isDeviceEvent(strict) ]);
let isTimelineList = arrayOf([ required, isTimelineEvent(strict) ]);
module.exports = {
return {
next_batch: [ required, isString ],
// FIXME: also optionalObject for `rooms`
rooms: {
@ -109,4 +111,5 @@ module.exports = {
groups: anything, // NOTE: Non-standard
// TODO: Validate algorithm names below?
"org.matrix.msc2732.device_unused_fallback_key_types": optionalArray(arrayOf([ required, isString ])), // NOTE: https://github.com/matrix-org/matrix-doc/pull/2732
};
};

@ -6,7 +6,10 @@ const isRoomEvent = require("../is-room-event");
const isStateEvent = require("../is-state-event");
// State events are a more specific version of room events: https://github.com/matrix-org/matrix-doc/issues/2681
module.exports = either([
[ isRoomEvent ],
[ isStateEvent ]
]);
module.exports = function (strict = false, extraFields = {}) {
return either([
[ isRoomEvent(strict, extraFields) ],
[ isStateEvent(strict, extraFields) ]
]);
};

@ -7,10 +7,10 @@ const itemDeduplicator = require("../item-deduplicator");
const isMessagesResponse = require("../is-messages-response");
module.exports = function parseMessagesResponse(_response) {
module.exports = function parseMessagesResponse(_response, strict = false) {
// FIXME: Figure out a way to soft-fail, and turn the validation error into a warning event
let [ response ] = validateArguments(arguments, {
response: [ required, isMessagesResponse ]
response: [ required, isMessagesResponse(strict) ]
});
let deduplicateEvent = itemDeduplicator((event) => event.event_id);

@ -31,10 +31,10 @@ function maybeMapObject(object, mappingFunction) {
}
module.exports = function syncResponseToEvents(_syncResponse) {
module.exports = function parseSyncResponse(_syncResponse, strict = false) {
// require("fs").writeFileSync("private/dump.json", JSON.stringify(_syncResponse));
let [ syncResponse ] = validateArguments(arguments, {
syncResponseBody: [ required, isSyncResponse ], // TODO: Validate and normalize the response body, including setting defaults, and allowing extra properties
syncResponseBody: [ required, isSyncResponse(strict) ], // TODO: Validate and normalize the response body, including setting defaults, and allowing extra properties
});
// We keep an event ID -> event body mapping, to ensure that the same event in different places in the response maps to the same in-memory object in our resulting event list; this is useful both to save memory, and to make equality-checking operations work

@ -7,11 +7,13 @@ const simpleSink = require("@promistream/simple-sink");
const filter = require("@promistream/filter");
const mapEvent = require("../map-event");
const createSession = require("../../../../create-session");
let session = {
homeserver: "https://pixie.town",
accessToken: require("../../../private/access-token")
};
// let session = {
// homeserver: "https://pixie.town",
// accessToken: require("../../../private/access-token")
// };
// let since = "s14011802_60514432_167714_6077759_745604_385_21833_2919406_36";
// let since = "s14886247_62932075_392219_6368720_764854_404_25467_3352546_36";
@ -19,6 +21,10 @@ let session = {
let since = "s15508519_65086739_41448_6548141_783165_404_27201_3802507_36";
return Promise.try(() => {
return createSession("https://pixie.town", {
accessToken: require("../../../private/access-token")
});
}).then((session) => {
return pipe([
mmStreamEvents(session, since, { initialLimit: 50, eventMapper: mapEvent }),
filter((event) => event.type === "roomTimelineEvent"),

Loading…
Cancel
Save