def event_from_pdu_json( pdu_json: JsonDict, room_version: RoomVersion, outlier: bool = False ) -> EventBase: """Construct an EventBase from an event json received over federation Args: pdu_json: pdu as received over federation room_version: The version of the room this event belongs to outlier: True to mark this event as an outlier Raises: SynapseError: if the pdu is missing required fields or is otherwise not a valid matrix event """ # we could probably enforce a bunch of other fields here (room_id, sender, # origin, etc etc) assert_params_in_dict(pdu_json, ("type", "depth")) depth = pdu_json["depth"] if not isinstance(depth, int): raise SynapseError(400, "Depth %r not an intger" % (depth,), Codes.BAD_JSON) if depth < 0: raise SynapseError(400, "Depth too small", Codes.BAD_JSON) elif depth > MAX_DEPTH: raise SynapseError(400, "Depth too large", Codes.BAD_JSON) # Validate that the JSON conforms to the specification. if room_version.strict_canonicaljson: validate_canonicaljson(pdu_json) event = make_event_from_dict(pdu_json, room_version) event.internal_metadata.outlier = outlier return event
def validate_new(self, event: EventBase, config: HomeServerConfig): """Validates the event has roughly the right format Args: event: The event to validate. config: The homeserver's configuration. """ self.validate_builder(event) if event.format_version == EventFormatVersions.V1: EventID.from_string(event.event_id) required = [ "auth_events", "content", "hashes", "origin", "prev_events", "sender", "type", ] for k in required: if not hasattr(event, k): raise SynapseError(400, "Event does not have key %s" % (k,)) # Check that the following keys have string values event_strings = ["origin"] for s in event_strings: if not isinstance(getattr(event, s), str): raise SynapseError(400, "'%s' not a string type" % (s,)) # Depending on the room version, ensure the data is spec compliant JSON. if event.room_version.strict_canonicaljson: # Note that only the client controlled portion of the event is # checked, since we trust the portions of the event we created. validate_canonicaljson(event.content) if event.type == EventTypes.Aliases: if "aliases" in event.content: for alias in event.content["aliases"]: if len(alias) > MAX_ALIAS_LENGTH: raise SynapseError( 400, ( "Can't create aliases longer than" " %d characters" % (MAX_ALIAS_LENGTH,) ), Codes.INVALID_PARAM, ) if event.type == EventTypes.Retention: self._validate_retention(event) if event.type == EventTypes.ServerACL: if not server_matches_acl_event(config.server_name, event): raise SynapseError( 400, "Can't create an ACL event that denies the local server" )
def event_from_pdu_json(pdu_json: JsonDict, room_version: RoomVersion) -> EventBase: """Construct an EventBase from an event json received over federation Args: pdu_json: pdu as received over federation room_version: The version of the room this event belongs to Raises: SynapseError: if the pdu is missing required fields or is otherwise not a valid matrix event """ # we could probably enforce a bunch of other fields here (room_id, sender, # origin, etc etc) assert_params_in_dict(pdu_json, ("type", "depth")) # Strip any unauthorized values from "unsigned" if they exist if "unsigned" in pdu_json: _strip_unsigned_values(pdu_json) depth = pdu_json["depth"] if not isinstance(depth, int): raise SynapseError(400, "Depth %r not an intger" % (depth,), Codes.BAD_JSON) if depth < 0: raise SynapseError(400, "Depth too small", Codes.BAD_JSON) elif depth > MAX_DEPTH: raise SynapseError(400, "Depth too large", Codes.BAD_JSON) # Validate that the JSON conforms to the specification. if room_version.strict_canonicaljson: validate_canonicaljson(pdu_json) event = make_event_from_dict(pdu_json, room_version) return event
def validate_new(self, event: EventBase, config: HomeServerConfig) -> None: """Validates the event has roughly the right format Suitable for checking a locally-created event. It has stricter checks than is appropriate for an event received over federation (for which, see event_auth.validate_event_for_room_version) Args: event: The event to validate. config: The homeserver's configuration. """ self.validate_builder(event) if event.format_version == EventFormatVersions.V1: EventID.from_string(event.event_id) required = [ "auth_events", "content", "hashes", "origin", "prev_events", "sender", "type", ] for k in required: if k not in event: raise SynapseError(400, "Event does not have key %s" % (k, )) # Check that the following keys have string values event_strings = ["origin"] for s in event_strings: if not isinstance(getattr(event, s), str): raise SynapseError(400, "'%s' not a string type" % (s, )) # Depending on the room version, ensure the data is spec compliant JSON. if event.room_version.strict_canonicaljson: # Note that only the client controlled portion of the event is # checked, since we trust the portions of the event we created. validate_canonicaljson(event.content) if event.type == EventTypes.Aliases: if "aliases" in event.content: for alias in event.content["aliases"]: if len(alias) > MAX_ALIAS_LENGTH: raise SynapseError( 400, ("Can't create aliases longer than" " %d characters" % (MAX_ALIAS_LENGTH, )), Codes.INVALID_PARAM, ) if event.type == EventTypes.Retention: self._validate_retention(event) if event.type == EventTypes.ServerACL: if not server_matches_acl_event(config.server.server_name, event): raise SynapseError( 400, "Can't create an ACL event that denies the local server") if event.type == EventTypes.PowerLevels: try: jsonschema.validate( instance=event.content, schema=POWER_LEVELS_SCHEMA, cls=plValidator, ) except jsonschema.ValidationError as e: if e.path: # example: "users_default": '0' is not of type 'integer' # cast safety: path entries can be integers, if we fail to validate # items in an array. However the POWER_LEVELS_SCHEMA doesn't expect # to see any arrays. message = ( '"' + cast(str, e.path[-1]) + '": ' + e.message # noqa: B306 ) # jsonschema.ValidationError.message is a valid attribute else: # example: '0' is not of type 'integer' message = e.message # noqa: B306 # jsonschema.ValidationError.message is a valid attribute raise SynapseError( code=400, msg=message, errcode=Codes.BAD_JSON, )