Branch off member and non member sends

Unclean, needs tidy-up, but works
This commit is contained in:
Daniel Wagner-Hall 2016-02-15 18:21:30 +00:00
parent 1a2197d7bf
commit 4bfb32f685
5 changed files with 99 additions and 74 deletions

View file

@ -216,7 +216,7 @@ class DirectoryHandler(BaseHandler):
aliases = yield self.store.get_aliases_for_room(room_id) aliases = yield self.store.get_aliases_for_room(room_id)
msg_handler = self.hs.get_handlers().message_handler msg_handler = self.hs.get_handlers().message_handler
yield msg_handler.create_and_send_event({ yield msg_handler.create_and_send_nonmember_event({
"type": EventTypes.Aliases, "type": EventTypes.Aliases,
"state_key": self.hs.hostname, "state_key": self.hs.hostname,
"room_id": room_id, "room_id": room_id,

View file

@ -1658,7 +1658,7 @@ class FederationHandler(BaseHandler):
self.auth.check(event, context.current_state) self.auth.check(event, context.current_state)
yield self._validate_keyserver(event, auth_events=context.current_state) yield self._validate_keyserver(event, auth_events=context.current_state)
member_handler = self.hs.get_handlers().room_member_handler member_handler = self.hs.get_handlers().room_member_handler
yield member_handler.send_membership_event(event, context) yield member_handler.send_membership_event(event, context, from_client=False)
else: else:
destinations = set([x.split(":", 1)[-1] for x in (sender, room_id)]) destinations = set([x.split(":", 1)[-1] for x in (sender, room_id)])
yield self.replication_layer.forward_third_party_invite( yield self.replication_layer.forward_third_party_invite(
@ -1687,7 +1687,7 @@ class FederationHandler(BaseHandler):
# TODO: Make sure the signatures actually are correct. # TODO: Make sure the signatures actually are correct.
event.signatures.update(returned_invite.signatures) event.signatures.update(returned_invite.signatures)
member_handler = self.hs.get_handlers().room_member_handler member_handler = self.hs.get_handlers().room_member_handler
yield member_handler.send_membership_event(event, context) yield member_handler.send_membership_event(event, context, from_client=False)
@defer.inlineCallbacks @defer.inlineCallbacks
def add_display_name_to_third_party_invite(self, event_dict, event, context): def add_display_name_to_third_party_invite(self, event_dict, event, context):

View file

@ -16,7 +16,7 @@
from twisted.internet import defer from twisted.internet import defer
from synapse.api.constants import EventTypes, Membership from synapse.api.constants import EventTypes, Membership
from synapse.api.errors import AuthError, Codes from synapse.api.errors import AuthError, Codes, SynapseError
from synapse.streams.config import PaginationConfig from synapse.streams.config import PaginationConfig
from synapse.events.utils import serialize_event from synapse.events.utils import serialize_event
from synapse.events.validator import EventValidator from synapse.events.validator import EventValidator
@ -216,7 +216,7 @@ class MessageHandler(BaseHandler):
defer.returnValue((event, context)) defer.returnValue((event, context))
@defer.inlineCallbacks @defer.inlineCallbacks
def send_event(self, event, context, ratelimit=True, is_guest=False, room_hosts=None): def send_nonmember_event(self, event, context, ratelimit=True):
""" """
Persists and notifies local clients and federation of an event. Persists and notifies local clients and federation of an event.
@ -226,61 +226,63 @@ class MessageHandler(BaseHandler):
ratelimit (bool): Whether to rate limit this send. ratelimit (bool): Whether to rate limit this send.
is_guest (bool): Whether the sender is a guest. is_guest (bool): Whether the sender is a guest.
""" """
if event.type == EventTypes.Member:
raise SynapseError(
500,
"Tried to send member even through non-member codepath"
)
user = UserID.from_string(event.sender) user = UserID.from_string(event.sender)
assert self.hs.is_mine(user), "User must be our own: %s" % (user,) assert self.hs.is_mine(user), "User must be our own: %s" % (user,)
if event.is_state(): if event.is_state():
prev_state = context.current_state.get((event.type, event.state_key)) prev_state = self.deduplicate_state_event(event, context)
if prev_state and event.user_id == prev_state.user_id: if prev_state is not None:
prev_content = encode_canonical_json(prev_state.content) defer.returnValue(prev_state)
next_content = encode_canonical_json(event.content)
if prev_content == next_content:
# Duplicate suppression for state updates with same sender
# and content.
defer.returnValue(prev_state)
if event.type == EventTypes.Member: yield self.handle_new_client_event(
member_handler = self.hs.get_handlers().room_member_handler event=event,
yield member_handler.send_membership_event( context=context,
event, ratelimit=ratelimit,
context, )
is_guest=is_guest,
ratelimit=ratelimit,
room_hosts=room_hosts
)
else:
yield self.handle_new_client_event(
event=event,
context=context,
ratelimit=ratelimit,
)
if event.type == EventTypes.Message: if event.type == EventTypes.Message:
presence = self.hs.get_handlers().presence_handler presence = self.hs.get_handlers().presence_handler
with PreserveLoggingContext(): with PreserveLoggingContext():
presence.bump_presence_active_time(user) presence.bump_presence_active_time(user)
def deduplicate_state_event(self, event, context):
prev_state = context.current_state.get((event.type, event.state_key))
if prev_state and event.user_id == prev_state.user_id:
prev_content = encode_canonical_json(prev_state.content)
next_content = encode_canonical_json(event.content)
if prev_content == next_content:
return prev_state
return None
@defer.inlineCallbacks @defer.inlineCallbacks
def create_and_send_event(self, event_dict, ratelimit=True, def create_and_send_nonmember_event(
token_id=None, txn_id=None, is_guest=False, self,
room_hosts=None): event_dict,
ratelimit=True,
token_id=None,
txn_id=None
):
""" """
Creates an event, then sends it. Creates an event, then sends it.
See self.create_event and self.send_event. See self.create_event and self.send_nonmember_event.
""" """
event, context = yield self.create_event( event, context = yield self.create_event(
event_dict, event_dict,
token_id=token_id, token_id=token_id,
txn_id=txn_id txn_id=txn_id
) )
yield self.send_event( yield self.send_nonmember_event(
event, event,
context, context,
ratelimit=ratelimit, ratelimit=ratelimit,
is_guest=is_guest,
room_hosts=room_hosts,
) )
defer.returnValue(event) defer.returnValue(event)

View file

@ -179,13 +179,24 @@ class RoomCreationHandler(BaseHandler):
) )
msg_handler = self.hs.get_handlers().message_handler msg_handler = self.hs.get_handlers().message_handler
room_member_handler = self.hs.get_handlers().room_member_handler
for event in creation_events: for event in creation_events:
yield msg_handler.create_and_send_event(event, ratelimit=False) if event["type"] == EventTypes.Member:
# TODO(danielwh): This is hideous
yield room_member_handler.update_membership(
requester,
user,
room_id,
"join",
ratelimit=False,
)
else:
yield msg_handler.create_and_send_nonmember_event(event, ratelimit=False)
if "name" in config: if "name" in config:
name = config["name"] name = config["name"]
yield msg_handler.create_and_send_event({ yield msg_handler.create_and_send_nonmember_event({
"type": EventTypes.Name, "type": EventTypes.Name,
"room_id": room_id, "room_id": room_id,
"sender": user_id, "sender": user_id,
@ -195,7 +206,7 @@ class RoomCreationHandler(BaseHandler):
if "topic" in config: if "topic" in config:
topic = config["topic"] topic = config["topic"]
yield msg_handler.create_and_send_event({ yield msg_handler.create_and_send_nonmember_event({
"type": EventTypes.Topic, "type": EventTypes.Topic,
"room_id": room_id, "room_id": room_id,
"sender": user_id, "sender": user_id,
@ -204,13 +215,13 @@ class RoomCreationHandler(BaseHandler):
}, ratelimit=False) }, ratelimit=False)
for invitee in invite_list: for invitee in invite_list:
yield msg_handler.create_and_send_event({ room_member_handler.update_membership(
"type": EventTypes.Member, requester,
"state_key": invitee, UserID.from_string(invitee),
"room_id": room_id, room_id,
"sender": user_id, "invite",
"content": {"membership": Membership.INVITE}, ratelimit=False,
}, ratelimit=False) )
for invite_3pid in invite_3pid_list: for invite_3pid in invite_3pid_list:
id_server = invite_3pid["id_server"] id_server = invite_3pid["id_server"]
@ -222,7 +233,7 @@ class RoomCreationHandler(BaseHandler):
medium, medium,
address, address,
id_server, id_server,
token_id=None, requester,
txn_id=None, txn_id=None,
) )
@ -439,12 +450,14 @@ class RoomMemberHandler(BaseHandler):
errcode=Codes.BAD_STATE errcode=Codes.BAD_STATE
) )
yield msg_handler.send_event( member_handler = self.hs.get_handlers().room_member_handler
yield member_handler.send_membership_event(
event, event,
context, context,
ratelimit=ratelimit,
is_guest=requester.is_guest, is_guest=requester.is_guest,
ratelimit=ratelimit,
room_hosts=room_hosts, room_hosts=room_hosts,
from_client=True,
) )
if action == "forget": if action == "forget":
@ -452,7 +465,7 @@ class RoomMemberHandler(BaseHandler):
@defer.inlineCallbacks @defer.inlineCallbacks
def send_membership_event( def send_membership_event(
self, event, context, is_guest=False, room_hosts=None, ratelimit=True self, event, context, is_guest=False, room_hosts=None, ratelimit=True, from_client=True,
): ):
""" Change the membership status of a user in a room. """ Change the membership status of a user in a room.
@ -461,6 +474,16 @@ class RoomMemberHandler(BaseHandler):
Raises: Raises:
SynapseError if there was a problem changing the membership. SynapseError if there was a problem changing the membership.
""" """
if from_client:
user = UserID.from_string(event.sender)
assert self.hs.is_mine(user), "User must be our own: %s" % (user,)
if event.is_state():
prev_state = self.hs.get_handlers().message_handler.deduplicate_state_event(event, context)
if prev_state is not None:
return
target_user_id = event.state_key target_user_id = event.state_key
target_user = UserID.from_string(event.state_key) target_user = UserID.from_string(event.state_key)
@ -549,13 +572,11 @@ class RoomMemberHandler(BaseHandler):
room_id, room_id,
event.user_id event.user_id
) )
defer.returnValue({"room_id": room_id})
return return
# FIXME: This isn't idempotency. # FIXME: This isn't idempotency.
if prev_state and prev_state.membership == event.membership: if prev_state and prev_state.membership == event.membership:
# double same action, treat this event as a NOOP. # double same action, treat this event as a NOOP.
defer.returnValue({})
return return
yield self.handle_new_client_event( yield self.handle_new_client_event(
@ -569,8 +590,6 @@ class RoomMemberHandler(BaseHandler):
user = UserID.from_string(event.user_id) user = UserID.from_string(event.user_id)
user_left_room(self.distributor, user, event.room_id) user_left_room(self.distributor, user, event.room_id)
defer.returnValue({"room_id": room_id})
@defer.inlineCallbacks @defer.inlineCallbacks
def lookup_room_alias(self, room_alias): def lookup_room_alias(self, room_alias):
""" """
@ -657,7 +676,7 @@ class RoomMemberHandler(BaseHandler):
medium, medium,
address, address,
id_server, id_server,
token_id, requester,
txn_id txn_id
): ):
invitee = yield self._lookup_3pid( invitee = yield self._lookup_3pid(
@ -665,19 +684,12 @@ class RoomMemberHandler(BaseHandler):
) )
if invitee: if invitee:
# make sure it looks like a user ID; it'll throw if it's invalid. handler = self.hs.get_handlers().room_member_handler
UserID.from_string(invitee) yield handler.update_membership(
yield self.hs.get_handlers().message_handler.create_and_send_event( requester,
{ UserID.from_string(invitee),
"type": EventTypes.Member, room_id,
"content": { "invite",
"membership": unicode("invite")
},
"room_id": room_id,
"sender": inviter.to_string(),
"state_key": invitee,
},
token_id=token_id,
txn_id=txn_id, txn_id=txn_id,
) )
else: else:
@ -687,7 +699,7 @@ class RoomMemberHandler(BaseHandler):
address, address,
room_id, room_id,
inviter, inviter,
token_id, requester.access_token_id,
txn_id=txn_id txn_id=txn_id
) )
@ -798,7 +810,7 @@ class RoomMemberHandler(BaseHandler):
) )
) )
msg_handler = self.hs.get_handlers().message_handler msg_handler = self.hs.get_handlers().message_handler
yield msg_handler.create_and_send_event( yield msg_handler.create_and_send_nonmember_event(
{ {
"type": EventTypes.ThirdPartyInvite, "type": EventTypes.ThirdPartyInvite,
"content": { "content": {

View file

@ -150,10 +150,21 @@ class RoomStateEventRestServlet(ClientV1RestServlet):
event_dict["state_key"] = state_key event_dict["state_key"] = state_key
msg_handler = self.handlers.message_handler msg_handler = self.handlers.message_handler
yield msg_handler.create_and_send_event( event, context = yield msg_handler.create_event(
event_dict, token_id=requester.access_token_id, txn_id=txn_id, event_dict,
token_id=requester.access_token_id,
txn_id=txn_id,
) )
if event_type == EventTypes.Member:
yield self.handlers.room_member_handler.send_membership_event(
event,
context,
is_guest=requester.is_guest,
)
else:
yield msg_handler.send_nonmember_event(event, context)
defer.returnValue((200, {})) defer.returnValue((200, {}))
@ -171,7 +182,7 @@ class RoomSendEventRestServlet(ClientV1RestServlet):
content = _parse_json(request) content = _parse_json(request)
msg_handler = self.handlers.message_handler msg_handler = self.handlers.message_handler
event = yield msg_handler.create_and_send_event( event = yield msg_handler.create_and_send_nonmember_event(
{ {
"type": event_type, "type": event_type,
"content": content, "content": content,
@ -434,7 +445,7 @@ class RoomMembershipRestServlet(ClientV1RestServlet):
content["medium"], content["medium"],
content["address"], content["address"],
content["id_server"], content["id_server"],
requester.access_token_id, requester,
txn_id txn_id
) )
defer.returnValue((200, {})) defer.returnValue((200, {}))
@ -490,7 +501,7 @@ class RoomRedactEventRestServlet(ClientV1RestServlet):
content = _parse_json(request) content = _parse_json(request)
msg_handler = self.handlers.message_handler msg_handler = self.handlers.message_handler
event = yield msg_handler.create_and_send_event( event = yield msg_handler.create_and_send_nonmember_event(
{ {
"type": EventTypes.Redaction, "type": EventTypes.Redaction,
"content": content, "content": content,