diff options
author | Patrick Cloke <clokep@users.noreply.github.com> | 2022-05-16 08:42:45 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-16 12:42:45 +0000 |
commit | 86a515ccbf359ecd65a42a3f409b8f97c8f22284 (patch) | |
tree | 0f1b02378c8baa282444026399a3abc42e7a3fb3 /synapse/events | |
parent | Add config flags to allow for cache auto-tuning (#12701) (diff) | |
download | synapse-86a515ccbf359ecd65a42a3f409b8f97c8f22284.tar.xz |
Consolidate logic for parsing relations. (#12693)
Parse the `m.relates_to` event content field (which describes relations) in a single place, this is used during: * Event persistence. * Validation of the Client-Server API. * Fetching bundled aggregations. * Processing of push rules. Each of these separately implement the logic and each made slightly different assumptions about what was valid. Some had minor / potential bugs.
Diffstat (limited to 'synapse/events')
-rw-r--r-- | synapse/events/__init__.py | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/synapse/events/__init__.py b/synapse/events/__init__.py index c238376caf..39ad2793d9 100644 --- a/synapse/events/__init__.py +++ b/synapse/events/__init__.py @@ -15,6 +15,7 @@ # limitations under the License. import abc +import collections.abc import os from typing import ( TYPE_CHECKING, @@ -32,9 +33,11 @@ from typing import ( overload, ) +import attr from typing_extensions import Literal from unpaddedbase64 import encode_base64 +from synapse.api.constants import RelationTypes from synapse.api.room_versions import EventFormatVersions, RoomVersion, RoomVersions from synapse.types import JsonDict, RoomStreamToken from synapse.util.caches import intern_dict @@ -615,3 +618,45 @@ def make_event_from_dict( return event_type( event_dict, room_version, internal_metadata_dict or {}, rejected_reason ) + + +@attr.s(slots=True, frozen=True, auto_attribs=True) +class _EventRelation: + # The target event of the relation. + parent_id: str + # The relation type. + rel_type: str + # The aggregation key. Will be None if the rel_type is not m.annotation or is + # not a string. + aggregation_key: Optional[str] + + +def relation_from_event(event: EventBase) -> Optional[_EventRelation]: + """ + Attempt to parse relation information an event. + + Returns: + The event relation information, if it is valid. None, otherwise. + """ + relation = event.content.get("m.relates_to") + if not relation or not isinstance(relation, collections.abc.Mapping): + # No relation information. + return None + + # Relations must have a type and parent event ID. + rel_type = relation.get("rel_type") + if not isinstance(rel_type, str): + return None + + parent_id = relation.get("event_id") + if not isinstance(parent_id, str): + return None + + # Annotations have a key field. + aggregation_key = None + if rel_type == RelationTypes.ANNOTATION: + aggregation_key = relation.get("key") + if not isinstance(aggregation_key, str): + aggregation_key = None + + return _EventRelation(parent_id, rel_type, aggregation_key) |