Implement rules for direct

pull/5484/head
Brendan Abolivier 2019-06-17 15:13:27 +01:00
parent bd8448ccb2
commit 8b2f655589
1 changed files with 101 additions and 13 deletions

View File

@ -15,28 +15,116 @@
from twisted.internet import defer
from synapse.api.constants import EventTypes, Membership
from synapse.config._base import ConfigError
ACESS_RULES_TYPE = "im.vector.room.access_rules"
ACCESS_RULE_RESTRICTED = "restricted"
ACCESS_RULE_UNRESTRICTED = "unrestricted"
ACCESS_RULE_DIRECT = "direct"
class TchapEventRules(object):
ACESS_RULES_TYPE = "im.vector.room.access_rules"
def __init__(self, config):
# We don't have a config yet.
pass
self.id_server = config["id_server"]
@staticmethod
def parse_config(config):
return config
if "id_server" in config:
return config
else:
raise ConfigError("No IS for event rules TchapEventRules")
def check_event_allowed(self, event, state_events):
# TODO: add rules for sending the access rules event
access_rules = state_events.get((ACESS_RULES_TYPE, ""))
if access_rules is None:
rule = ACCESS_RULE_RESTRICTED
else:
rule = access_rules.content.get("rule")
if rule == ACCESS_RULE_RESTRICTED:
ret = self._apply_restricted(event, state_events)
elif rule == ACCESS_RULE_UNRESTRICTED:
ret = self._apply_unrestricted(event, state_events)
elif rule == ACCESS_RULE_DIRECT:
ret = self._apply_direct(event, state_events)
else:
# We currently apply the default (restricted) if we don't know the rule, we
# might want to change that in the future.
ret = self._apply_restricted(event, state_events)
return ret
@defer.inlineCallbacks
def check_event_allowed(self, event, context):
def _apply_restricted(self, event, state_events):
return True
def _apply_restricted(self):
pass
def _apply_unrestricted(self, event, state_events):
# "unrestricted" currently means that every event is allowed.
return True
def _apply_unrestricted(self):
pass
def _apply_direct(self, event, state_events):
# "direct" currently means that no member is allowed apart from the two initial
# members the room was created for (i.e. the room's creator and their first
# invitee).
# TODO: figure out how to know if the room was created with "is_direct".
def _apply_direct(self):
pass
if event.type != EventTypes.Member and event.type != EventTypes.ThirdPartyInvite:
return True
# Get the m.room.member and m.room.third_party_invite events from the room's
# state.
member_events = []
threepid_invite_events = []
for key, event in state_events.items():
if key[0] == EventTypes.Member:
member_events.append(event)
if key[0] == EventTypes.ThirdPartyInvite:
threepid_invite_events.append(event)
# There should never be more than one 3PID invite in the room state:
if len(threepid_invite_events) == 1 and event.type == EventTypes.ThirdPartyInvite:
# If we already have a 3PID invite in flight, don't accept another one.
return False
if len(member_events) == 2:
# If the user was within the two initial user of the room, Synapse would have
# looked it up successfully and thus sent a m.room.member here instead of
# m.room.third_party_invite.
if event.type == EventTypes.ThirdPartyInvite:
return False
# We can only have m.room.member events here. The rule in this case is to only
# allow the event if its target is one of the initial two members in the room,
# i.e. the state key of one of the two m.room.member states in the room.
target = event.state_key
for e in member_events:
if e.state_key == target:
return True
return False
# We're alone in the room (and always have been) and there's one 3PID invite in
# flight.
if len(member_events) == 1 and len(threepid_invite_events) == 1:
# We can only have m.room.member events here. In this case, we can only allow
# the event if it's either a m.room.member from the joined user (we can assume
# that the only m.room.member event is a join otherwise we wouldn't be able to
# send an event to the room) or an a m.room.member with the "invite"
# membership which target is the invited user.
target = event.state_key
is_from_threepid_invite = self._is_invite_from_threepid(
event, threepid_invite_events[0],
)
if is_from_threepid_invite or target == member_events[0].state_key:
return True
return False
return True
def _is_invite_from_threepid(self, invite, threepid_invite):
token = invite.content.get("third_party_signed", {}).get("token", "")
return token == threepid_invite.state_key