Skip to content
Snippets Groups Projects
Unverified Commit 78a15b1f authored by Richard van der Hoff's avatar Richard van der Hoff Committed by GitHub
Browse files

Store room_versions in EventBase objects (#6875)

This is a bit fiddly because it all has to be done on one fell swoop:

* Wherever we create a new event, pass in the room version (and check it matches the format version)
* When we prune an event, use the room version of the unpruned event to create the pruned version.
* When we pass an event over the replication protocol, pass the room version over alongside it, and use it when deserialising the event again.
parent fe678a09
No related branches found
No related tags found
No related merge requests found
Refactoring work in preparation for changing the event redaction algorithm.
...@@ -15,9 +15,10 @@ ...@@ -15,9 +15,10 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import abc
import os import os
from distutils.util import strtobool from distutils.util import strtobool
from typing import Optional, Type from typing import Dict, Optional, Type
import six import six
...@@ -199,15 +200,25 @@ class _EventInternalMetadata(object): ...@@ -199,15 +200,25 @@ class _EventInternalMetadata(object):
return self._dict.get("redacted", False) return self._dict.get("redacted", False)
class EventBase(object): class EventBase(metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def format_version(self) -> int:
"""The EventFormatVersion implemented by this event"""
...
def __init__( def __init__(
self, self,
event_dict, event_dict: JsonDict,
signatures={}, room_version: RoomVersion,
unsigned={}, signatures: Dict[str, Dict[str, str]],
internal_metadata_dict={}, unsigned: JsonDict,
rejected_reason=None, internal_metadata_dict: JsonDict,
rejected_reason: Optional[str],
): ):
assert room_version.event_format == self.format_version
self.room_version = room_version
self.signatures = signatures self.signatures = signatures
self.unsigned = unsigned self.unsigned = unsigned
self.rejected_reason = rejected_reason self.rejected_reason = rejected_reason
...@@ -303,7 +314,13 @@ class EventBase(object): ...@@ -303,7 +314,13 @@ class EventBase(object):
class FrozenEvent(EventBase): class FrozenEvent(EventBase):
format_version = EventFormatVersions.V1 # All events of this type are V1 format_version = EventFormatVersions.V1 # All events of this type are V1
def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None): def __init__(
self,
event_dict: JsonDict,
room_version: RoomVersion,
internal_metadata_dict: JsonDict = {},
rejected_reason: Optional[str] = None,
):
event_dict = dict(event_dict) event_dict = dict(event_dict)
# Signatures is a dict of dicts, and this is faster than doing a # Signatures is a dict of dicts, and this is faster than doing a
...@@ -326,8 +343,9 @@ class FrozenEvent(EventBase): ...@@ -326,8 +343,9 @@ class FrozenEvent(EventBase):
self._event_id = event_dict["event_id"] self._event_id = event_dict["event_id"]
super(FrozenEvent, self).__init__( super().__init__(
frozen_dict, frozen_dict,
room_version=room_version,
signatures=signatures, signatures=signatures,
unsigned=unsigned, unsigned=unsigned,
internal_metadata_dict=internal_metadata_dict, internal_metadata_dict=internal_metadata_dict,
...@@ -352,7 +370,13 @@ class FrozenEvent(EventBase): ...@@ -352,7 +370,13 @@ class FrozenEvent(EventBase):
class FrozenEventV2(EventBase): class FrozenEventV2(EventBase):
format_version = EventFormatVersions.V2 # All events of this type are V2 format_version = EventFormatVersions.V2 # All events of this type are V2
def __init__(self, event_dict, internal_metadata_dict={}, rejected_reason=None): def __init__(
self,
event_dict: JsonDict,
room_version: RoomVersion,
internal_metadata_dict: JsonDict = {},
rejected_reason: Optional[str] = None,
):
event_dict = dict(event_dict) event_dict = dict(event_dict)
# Signatures is a dict of dicts, and this is faster than doing a # Signatures is a dict of dicts, and this is faster than doing a
...@@ -377,8 +401,9 @@ class FrozenEventV2(EventBase): ...@@ -377,8 +401,9 @@ class FrozenEventV2(EventBase):
self._event_id = None self._event_id = None
super(FrozenEventV2, self).__init__( super().__init__(
frozen_dict, frozen_dict,
room_version=room_version,
signatures=signatures, signatures=signatures,
unsigned=unsigned, unsigned=unsigned,
internal_metadata_dict=internal_metadata_dict, internal_metadata_dict=internal_metadata_dict,
...@@ -445,7 +470,7 @@ class FrozenEventV3(FrozenEventV2): ...@@ -445,7 +470,7 @@ class FrozenEventV3(FrozenEventV2):
return self._event_id return self._event_id
def event_type_from_format_version(format_version: int) -> Type[EventBase]: def _event_type_from_format_version(format_version: int) -> Type[EventBase]:
"""Returns the python type to use to construct an Event object for the """Returns the python type to use to construct an Event object for the
given event format version. given event format version.
...@@ -474,5 +499,5 @@ def make_event_from_dict( ...@@ -474,5 +499,5 @@ def make_event_from_dict(
rejected_reason: Optional[str] = None, rejected_reason: Optional[str] = None,
) -> EventBase: ) -> EventBase:
"""Construct an EventBase from the given event dict""" """Construct an EventBase from the given event dict"""
event_type = event_type_from_format_version(room_version.event_format) event_type = _event_type_from_format_version(room_version.event_format)
return event_type(event_dict, internal_metadata_dict, rejected_reason) return event_type(event_dict, room_version, internal_metadata_dict, rejected_reason)
...@@ -35,26 +35,20 @@ from . import EventBase ...@@ -35,26 +35,20 @@ from . import EventBase
SPLIT_FIELD_REGEX = re.compile(r"(?<!\\)\.") SPLIT_FIELD_REGEX = re.compile(r"(?<!\\)\.")
def prune_event(event): def prune_event(event: EventBase) -> EventBase:
""" Returns a pruned version of the given event, which removes all keys we """ Returns a pruned version of the given event, which removes all keys we
don't know about or think could potentially be dodgy. don't know about or think could potentially be dodgy.
This is used when we "redact" an event. We want to remove all fields that This is used when we "redact" an event. We want to remove all fields that
the user has specified, but we do want to keep necessary information like the user has specified, but we do want to keep necessary information like
type, state_key etc. type, state_key etc.
Args:
event (FrozenEvent)
Returns:
FrozenEvent
""" """
pruned_event_dict = prune_event_dict(event.get_dict()) pruned_event_dict = prune_event_dict(event.get_dict())
from . import event_type_from_format_version from . import make_event_from_dict
pruned_event = event_type_from_format_version(event.format_version)( pruned_event = make_event_from_dict(
pruned_event_dict, event.internal_metadata.get_dict() pruned_event_dict, event.room_version, event.internal_metadata.get_dict()
) )
# Mark the event as redacted # Mark the event as redacted
......
...@@ -18,7 +18,7 @@ import logging ...@@ -18,7 +18,7 @@ import logging
from twisted.internet import defer from twisted.internet import defer
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
from synapse.events import event_type_from_format_version from synapse.events import make_event_from_dict
from synapse.events.snapshot import EventContext from synapse.events.snapshot import EventContext
from synapse.http.servlet import parse_json_object_from_request from synapse.http.servlet import parse_json_object_from_request
from synapse.replication.http._base import ReplicationEndpoint from synapse.replication.http._base import ReplicationEndpoint
...@@ -38,6 +38,9 @@ class ReplicationFederationSendEventsRestServlet(ReplicationEndpoint): ...@@ -38,6 +38,9 @@ class ReplicationFederationSendEventsRestServlet(ReplicationEndpoint):
{ {
"events": [{ "events": [{
"event": { .. serialized event .. }, "event": { .. serialized event .. },
"room_version": .., // "1", "2", "3", etc: the version of the room
// containing the event
"event_format_version": .., // 1,2,3 etc: the event format version
"internal_metadata": { .. serialized internal_metadata .. }, "internal_metadata": { .. serialized internal_metadata .. },
"rejected_reason": .., // The event.rejected_reason field "rejected_reason": .., // The event.rejected_reason field
"context": { .. serialized event context .. }, "context": { .. serialized event context .. },
...@@ -73,6 +76,7 @@ class ReplicationFederationSendEventsRestServlet(ReplicationEndpoint): ...@@ -73,6 +76,7 @@ class ReplicationFederationSendEventsRestServlet(ReplicationEndpoint):
event_payloads.append( event_payloads.append(
{ {
"event": event.get_pdu_json(), "event": event.get_pdu_json(),
"room_version": event.room_version.identifier,
"event_format_version": event.format_version, "event_format_version": event.format_version,
"internal_metadata": event.internal_metadata.get_dict(), "internal_metadata": event.internal_metadata.get_dict(),
"rejected_reason": event.rejected_reason, "rejected_reason": event.rejected_reason,
...@@ -95,12 +99,13 @@ class ReplicationFederationSendEventsRestServlet(ReplicationEndpoint): ...@@ -95,12 +99,13 @@ class ReplicationFederationSendEventsRestServlet(ReplicationEndpoint):
event_and_contexts = [] event_and_contexts = []
for event_payload in event_payloads: for event_payload in event_payloads:
event_dict = event_payload["event"] event_dict = event_payload["event"]
format_ver = event_payload["event_format_version"] room_ver = KNOWN_ROOM_VERSIONS[event_payload["room_version"]]
internal_metadata = event_payload["internal_metadata"] internal_metadata = event_payload["internal_metadata"]
rejected_reason = event_payload["rejected_reason"] rejected_reason = event_payload["rejected_reason"]
EventType = event_type_from_format_version(format_ver) event = make_event_from_dict(
event = EventType(event_dict, internal_metadata, rejected_reason) event_dict, room_ver, internal_metadata, rejected_reason
)
context = EventContext.deserialize( context = EventContext.deserialize(
self.storage, event_payload["context"] self.storage, event_payload["context"]
......
...@@ -17,7 +17,8 @@ import logging ...@@ -17,7 +17,8 @@ import logging
from twisted.internet import defer from twisted.internet import defer
from synapse.events import event_type_from_format_version from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
from synapse.events import make_event_from_dict
from synapse.events.snapshot import EventContext from synapse.events.snapshot import EventContext
from synapse.http.servlet import parse_json_object_from_request from synapse.http.servlet import parse_json_object_from_request
from synapse.replication.http._base import ReplicationEndpoint from synapse.replication.http._base import ReplicationEndpoint
...@@ -37,6 +38,9 @@ class ReplicationSendEventRestServlet(ReplicationEndpoint): ...@@ -37,6 +38,9 @@ class ReplicationSendEventRestServlet(ReplicationEndpoint):
{ {
"event": { .. serialized event .. }, "event": { .. serialized event .. },
"room_version": .., // "1", "2", "3", etc: the version of the room
// containing the event
"event_format_version": .., // 1,2,3 etc: the event format version
"internal_metadata": { .. serialized internal_metadata .. }, "internal_metadata": { .. serialized internal_metadata .. },
"rejected_reason": .., // The event.rejected_reason field "rejected_reason": .., // The event.rejected_reason field
"context": { .. serialized event context .. }, "context": { .. serialized event context .. },
...@@ -77,6 +81,7 @@ class ReplicationSendEventRestServlet(ReplicationEndpoint): ...@@ -77,6 +81,7 @@ class ReplicationSendEventRestServlet(ReplicationEndpoint):
payload = { payload = {
"event": event.get_pdu_json(), "event": event.get_pdu_json(),
"room_version": event.room_version.identifier,
"event_format_version": event.format_version, "event_format_version": event.format_version,
"internal_metadata": event.internal_metadata.get_dict(), "internal_metadata": event.internal_metadata.get_dict(),
"rejected_reason": event.rejected_reason, "rejected_reason": event.rejected_reason,
...@@ -93,12 +98,13 @@ class ReplicationSendEventRestServlet(ReplicationEndpoint): ...@@ -93,12 +98,13 @@ class ReplicationSendEventRestServlet(ReplicationEndpoint):
content = parse_json_object_from_request(request) content = parse_json_object_from_request(request)
event_dict = content["event"] event_dict = content["event"]
format_ver = content["event_format_version"] room_ver = KNOWN_ROOM_VERSIONS[content["room_version"]]
internal_metadata = content["internal_metadata"] internal_metadata = content["internal_metadata"]
rejected_reason = content["rejected_reason"] rejected_reason = content["rejected_reason"]
EventType = event_type_from_format_version(format_ver) event = make_event_from_dict(
event = EventType(event_dict, internal_metadata, rejected_reason) event_dict, room_ver, internal_metadata, rejected_reason
)
requester = Requester.deserialize(self.store, content["requester"]) requester = Requester.deserialize(self.store, content["requester"])
context = EventContext.deserialize(self.storage, content["context"]) context = EventContext.deserialize(self.storage, content["context"])
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment