diff --git a/synapse/events/__init__.py b/synapse/events/__init__.py
index f813fa2fe7..a842661a90 100644
--- a/synapse/events/__init__.py
+++ b/synapse/events/__init__.py
@@ -16,13 +16,13 @@
import os
from distutils.util import strtobool
+from typing import Optional, Type
import six
from unpaddedbase64 import encode_base64
-from synapse.api.errors import UnsupportedRoomVersionError
-from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, EventFormatVersions
+from synapse.api.room_versions import EventFormatVersions, RoomVersion, RoomVersions
from synapse.types import JsonDict
from synapse.util.caches import intern_dict
from synapse.util.frozenutils import freeze
@@ -189,9 +189,15 @@ class EventBase(object):
redacts = _event_dict_property("redacts", None)
room_id = _event_dict_property("room_id")
sender = _event_dict_property("sender")
+ state_key = _event_dict_property("state_key")
+ type = _event_dict_property("type")
user_id = _event_dict_property("sender")
@property
+ def event_id(self) -> str:
+ raise NotImplementedError()
+
+ @property
def membership(self):
return self.content["membership"]
@@ -281,10 +287,7 @@ class FrozenEvent(EventBase):
else:
frozen_dict = event_dict
- self.event_id = event_dict["event_id"]
- self.type = event_dict["type"]
- if "state_key" in event_dict:
- self.state_key = event_dict["state_key"]
+ self._event_id = event_dict["event_id"]
super(FrozenEvent, self).__init__(
frozen_dict,
@@ -294,6 +297,10 @@ class FrozenEvent(EventBase):
rejected_reason=rejected_reason,
)
+ @property
+ def event_id(self) -> str:
+ return self._event_id
+
def __str__(self):
return self.__repr__()
@@ -332,9 +339,6 @@ class FrozenEventV2(EventBase):
frozen_dict = event_dict
self._event_id = None
- self.type = event_dict["type"]
- if "state_key" in event_dict:
- self.state_key = event_dict["state_key"]
super(FrozenEventV2, self).__init__(
frozen_dict,
@@ -404,28 +408,7 @@ class FrozenEventV3(FrozenEventV2):
return self._event_id
-def room_version_to_event_format(room_version):
- """Converts a room version string to the event format
-
- Args:
- room_version (str)
-
- Returns:
- int
-
- Raises:
- UnsupportedRoomVersionError if the room version is unknown
- """
- v = KNOWN_ROOM_VERSIONS.get(room_version)
-
- if not v:
- # this can happen if support is withdrawn for a room version
- raise UnsupportedRoomVersionError()
-
- return v.event_format
-
-
-def event_type_from_format_version(format_version):
+def event_type_from_format_version(format_version: int) -> Type[EventBase]:
"""Returns the python type to use to construct an Event object for the
given event format version.
@@ -445,3 +428,14 @@ def event_type_from_format_version(format_version):
return FrozenEventV3
else:
raise Exception("No event format %r" % (format_version,))
+
+
+def make_event_from_dict(
+ event_dict: JsonDict,
+ room_version: RoomVersion = RoomVersions.V1,
+ internal_metadata_dict: JsonDict = {},
+ rejected_reason: Optional[str] = None,
+) -> EventBase:
+ """Construct an EventBase from the given event dict"""
+ event_type = event_type_from_format_version(room_version.event_format)
+ return event_type(event_dict, internal_metadata_dict, rejected_reason)
diff --git a/synapse/events/builder.py b/synapse/events/builder.py
index 8d63ad6dc3..a0c4a40c27 100644
--- a/synapse/events/builder.py
+++ b/synapse/events/builder.py
@@ -28,11 +28,7 @@ from synapse.api.room_versions import (
RoomVersion,
)
from synapse.crypto.event_signing import add_hashes_and_signatures
-from synapse.events import (
- EventBase,
- _EventInternalMetadata,
- event_type_from_format_version,
-)
+from synapse.events import EventBase, _EventInternalMetadata, make_event_from_dict
from synapse.types import EventID, JsonDict
from synapse.util import Clock
from synapse.util.stringutils import random_string
@@ -256,8 +252,8 @@ def create_local_event_from_event_dict(
event_dict.setdefault("signatures", {})
add_hashes_and_signatures(room_version, event_dict, hostname, signing_key)
- return event_type_from_format_version(format_version)(
- event_dict, internal_metadata_dict=internal_metadata_dict
+ return make_event_from_dict(
+ event_dict, room_version, internal_metadata_dict=internal_metadata_dict
)
diff --git a/synapse/events/spamcheck.py b/synapse/events/spamcheck.py
index 5a907718d6..b7a31c9a7d 100644
--- a/synapse/events/spamcheck.py
+++ b/synapse/events/spamcheck.py
@@ -58,13 +58,33 @@ class SpamChecker(object):
return self.spam_checker.check_event_for_spam(event)
- def user_may_invite(self, inviter_userid, invitee_userid, room_id):
+ def user_may_invite(
+ self,
+ inviter_userid,
+ invitee_userid,
+ third_party_invite,
+ room_id,
+ new_room,
+ published_room,
+ ):
"""Checks if a given user may send an invite
If this method returns false, the invite will be rejected.
Args:
- userid (string): The sender's user ID
+ inviter_userid (str)
+ invitee_userid (str|None): The user ID of the invitee. Is None
+ if this is a third party invite and the 3PID is not bound to a
+ user ID.
+ third_party_invite (dict|None): If a third party invite then is a
+ dict containing the medium and address of the invitee.
+ room_id (str)
+ new_room (bool): Whether the user is being invited to the room as
+ part of a room creation, if so the invitee would have been
+ included in the call to `user_may_create_room`.
+ published_room (bool): Whether the room the user is being invited
+ to has been published in the local homeserver's public room
+ directory.
Returns:
bool: True if the user may send an invite, otherwise False
@@ -73,16 +93,29 @@ class SpamChecker(object):
return True
return self.spam_checker.user_may_invite(
- inviter_userid, invitee_userid, room_id
+ inviter_userid,
+ invitee_userid,
+ third_party_invite,
+ room_id,
+ new_room,
+ published_room,
)
- def user_may_create_room(self, userid):
+ def user_may_create_room(
+ self, userid, invite_list, third_party_invite_list, cloning
+ ):
"""Checks if a given user may create a room
If this method returns false, the creation request will be rejected.
Args:
userid (string): The sender's user ID
+ invite_list (list[str]): List of user IDs that would be invited to
+ the new room.
+ third_party_invite_list (list[dict]): List of third party invites
+ for the new room.
+ cloning (bool): Whether the user is cloning an existing room, e.g.
+ upgrading a room.
Returns:
bool: True if the user may create a room, otherwise False
@@ -90,7 +123,9 @@ class SpamChecker(object):
if self.spam_checker is None:
return True
- return self.spam_checker.user_may_create_room(userid)
+ return self.spam_checker.user_may_create_room(
+ userid, invite_list, third_party_invite_list, cloning
+ )
def user_may_create_room_alias(self, userid, room_alias):
"""Checks if a given user may create a room alias
@@ -125,3 +160,21 @@ class SpamChecker(object):
return True
return self.spam_checker.user_may_publish_room(userid, room_id)
+
+ def user_may_join_room(self, userid, room_id, is_invited):
+ """Checks if a given users is allowed to join a room.
+
+ Is not called when the user creates a room.
+
+ Args:
+ userid (str)
+ room_id (str)
+ is_invited (bool): Whether the user is invited into the room
+
+ Returns:
+ bool: Whether the user may join the room
+ """
+ if self.spam_checker is None:
+ return True
+
+ return self.spam_checker.user_may_join_room(userid, room_id, is_invited)
diff --git a/synapse/events/third_party_rules.py b/synapse/events/third_party_rules.py
index 86f7e5f8aa..459132d388 100644
--- a/synapse/events/third_party_rules.py
+++ b/synapse/events/third_party_rules.py
@@ -74,15 +74,16 @@ class ThirdPartyEventRules(object):
is_requester_admin (bool): If the requester is an admin
Returns:
- defer.Deferred
+ defer.Deferred[bool]: Whether room creation is allowed or denied.
"""
if self.third_party_rules is None:
- return
+ return True
- yield self.third_party_rules.on_create_room(
+ ret = yield self.third_party_rules.on_create_room(
requester, config, is_requester_admin
)
+ return ret
@defer.inlineCallbacks
def check_threepid_can_be_invited(self, medium, address, room_id):
|