Linearize updates to membership via PUT /state/

This commit is contained in:
Erik Johnston 2017-01-09 18:25:13 +00:00
parent 9898bbd9dc
commit 6823fe5241
4 changed files with 38 additions and 18 deletions

View File

@ -89,7 +89,7 @@ class RoomMemberHandler(BaseHandler):
duplicate = yield msg_handler.deduplicate_state_event(event, context) duplicate = yield msg_handler.deduplicate_state_event(event, context)
if duplicate is not None: if duplicate is not None:
# Discard the new event since this membership change is a no-op. # Discard the new event since this membership change is a no-op.
return defer.returnValue(duplicate)
yield msg_handler.handle_new_client_event( yield msg_handler.handle_new_client_event(
requester, requester,
@ -120,6 +120,8 @@ class RoomMemberHandler(BaseHandler):
if prev_member_event.membership == Membership.JOIN: if prev_member_event.membership == Membership.JOIN:
user_left_room(self.distributor, target, room_id) user_left_room(self.distributor, target, room_id)
defer.returnValue(event)
@defer.inlineCallbacks @defer.inlineCallbacks
def remote_join(self, remote_room_hosts, room_id, user, content): def remote_join(self, remote_room_hosts, room_id, user, content):
if len(remote_room_hosts) == 0: if len(remote_room_hosts) == 0:
@ -187,6 +189,7 @@ class RoomMemberHandler(BaseHandler):
ratelimit=True, ratelimit=True,
content=None, content=None,
): ):
content_specified = bool(content)
if content is None: if content is None:
content = {} content = {}
@ -229,6 +232,12 @@ class RoomMemberHandler(BaseHandler):
errcode=Codes.BAD_STATE errcode=Codes.BAD_STATE
) )
same_content = content == old_state.content
same_membership = old_membership == effective_membership_state
same_sender = requester.user.to_string() == old_state.sender
if same_sender and same_membership and same_content:
defer.returnValue(old_state)
is_host_in_room = yield self._is_host_in_room(current_state_ids) is_host_in_room = yield self._is_host_in_room(current_state_ids)
if effective_membership_state == Membership.JOIN: if effective_membership_state == Membership.JOIN:
@ -247,8 +256,9 @@ class RoomMemberHandler(BaseHandler):
content["membership"] = Membership.JOIN content["membership"] = Membership.JOIN
profile = self.hs.get_handlers().profile_handler profile = self.hs.get_handlers().profile_handler
content["displayname"] = yield profile.get_displayname(target) if not content_specified:
content["avatar_url"] = yield profile.get_avatar_url(target) content["displayname"] = yield profile.get_displayname(target)
content["avatar_url"] = yield profile.get_avatar_url(target)
if requester.is_guest: if requester.is_guest:
content["kind"] = "guest" content["kind"] = "guest"
@ -290,7 +300,7 @@ class RoomMemberHandler(BaseHandler):
defer.returnValue({}) defer.returnValue({})
yield self._local_membership_update( res = yield self._local_membership_update(
requester=requester, requester=requester,
target=target, target=target,
room_id=room_id, room_id=room_id,
@ -300,6 +310,7 @@ class RoomMemberHandler(BaseHandler):
prev_event_ids=latest_event_ids, prev_event_ids=latest_event_ids,
content=content, content=content,
) )
defer.returnValue(res)
@defer.inlineCallbacks @defer.inlineCallbacks
def send_membership_event( def send_membership_event(

View File

@ -152,23 +152,29 @@ class RoomStateEventRestServlet(ClientV1RestServlet):
if state_key is not None: if state_key is not None:
event_dict["state_key"] = state_key event_dict["state_key"] = state_key
msg_handler = self.handlers.message_handler
event, context = yield msg_handler.create_event(
event_dict,
token_id=requester.access_token_id,
txn_id=txn_id,
)
if event_type == EventTypes.Member: if event_type == EventTypes.Member:
yield self.handlers.room_member_handler.send_membership_event( membership = content.get("membership", None)
event = yield self.handlers.room_member_handler.update_membership(
requester, requester,
event, target=UserID.from_string(state_key),
context, room_id=room_id,
action=membership,
content=content,
) )
else: else:
msg_handler = self.handlers.message_handler
event, context = yield msg_handler.create_event(
event_dict,
token_id=requester.access_token_id,
txn_id=txn_id,
)
yield msg_handler.send_nonmember_event(requester, event, context) yield msg_handler.send_nonmember_event(requester, event, context)
defer.returnValue((200, {"event_id": event.event_id})) ret = {}
if event:
ret = {"event_id": event.event_id}
defer.returnValue((200, ret))
# TODO: Needs unit testing for generic events + feedback # TODO: Needs unit testing for generic events + feedback

View File

@ -259,8 +259,8 @@ class RoomPermissionsTestCase(RestTestCase):
# set [invite/join/left] of self, set [invite/join/left] of other, # set [invite/join/left] of self, set [invite/join/left] of other,
# expect all 404s because room doesn't exist on any server # expect all 404s because room doesn't exist on any server
for usr in [self.user_id, self.rmcreator_id]: for usr in [self.user_id, self.rmcreator_id]:
yield self.join(room=room, user=usr, expect_code=403) yield self.join(room=room, user=usr, expect_code=404)
yield self.leave(room=room, user=usr, expect_code=403) yield self.leave(room=room, user=usr, expect_code=404)
@defer.inlineCallbacks @defer.inlineCallbacks
def test_membership_private_room_perms(self): def test_membership_private_room_perms(self):

View File

@ -87,7 +87,10 @@ class RestTestCase(unittest.TestCase):
(code, response) = yield self.mock_resource.trigger( (code, response) = yield self.mock_resource.trigger(
"PUT", path, json.dumps(data) "PUT", path, json.dumps(data)
) )
self.assertEquals(expect_code, code, msg=str(response)) self.assertEquals(
expect_code, code,
msg="Expected: %d, got: %d, resp: %r" % (expect_code, code, response)
)
self.auth_user_id = temp_id self.auth_user_id = temp_id