Fix bugs when joining a remote room that has dodgy event graphs. This should also fix the number of times a HS will trigger a GET /event/

pull/25/head
Erik Johnston 2014-11-27 16:02:26 +00:00
parent 0294fba042
commit 027542e2e5
3 changed files with 68 additions and 31 deletions

View File

@ -202,7 +202,10 @@ class Auth(object):
# Invites are valid iff caller is in the room and target isn't.
if not caller_in_room: # caller isn't joined
raise AuthError(403, "You are not in room %s." % event.room_id)
raise AuthError(
403,
"%s not in room %s." % (event.user_id, event.room_id,)
)
elif target_in_room: # the target is already in the room.
raise AuthError(403, "%s is already in the room." %
target_user_id)
@ -225,7 +228,10 @@ class Auth(object):
# TODO (erikj): Implement kicks.
if not caller_in_room: # trying to leave a room you aren't joined
raise AuthError(403, "You are not in room %s." % event.room_id)
raise AuthError(
403,
"%s not in room %s." % (target_user_id, event.room_id,)
)
elif target_user_id != event.user_id:
if kick_level:
kick_level = int(kick_level)

View File

@ -153,7 +153,7 @@ class FederationHandler(BaseHandler):
event.room_id,
self.server_name
)
if not is_in_room:
if not is_in_room and not event.outlier:
logger.debug("Got event for room we're not in.")
replication_layer = self.replication_layer
@ -163,28 +163,30 @@ class FederationHandler(BaseHandler):
event_id=event.event_id,
)
current_state = yield replication_layer.get_state_for_context(
origin,
context=event.room_id,
event_id=event.event_id,
)
for e in auth_chain:
e.outlier = True
try:
yield self._handle_new_event(e)
yield self.notifier.on_new_room_event(e)
yield self._handle_new_event(e, fetch_missing=False)
except:
logger.exception(
"Failed to parse auth event %s",
e.event_id,
)
for e in current_state:
if not state:
state = yield replication_layer.get_state_for_context(
origin,
context=event.room_id,
event_id=event.event_id,
)
current_state = state
if state:
for e in state:
e.outlier = True
try:
yield self._handle_new_event(e)
yield self.notifier.on_new_room_event(e)
except:
logger.exception(
"Failed to parse state event %s",
@ -284,6 +286,16 @@ class FederationHandler(BaseHandler):
@defer.inlineCallbacks
def on_event_auth(self, event_id):
auth = yield self.store.get_auth_chain(event_id)
for event in auth:
event.signatures.update(
compute_event_signature(
event,
self.hs.hostname,
self.hs.config.signing_key[0]
)
)
defer.returnValue([e for e in auth])
@log_function
@ -343,6 +355,7 @@ class FederationHandler(BaseHandler):
state = ret["state"]
auth_chain = ret["auth_chain"]
auth_chain.sort(key=lambda e: e.depth)
logger.debug("do_invite_join auth_chain: %s", auth_chain)
logger.debug("do_invite_join state: %s", state)
@ -362,10 +375,7 @@ class FederationHandler(BaseHandler):
for e in auth_chain:
e.outlier = True
try:
yield self._handle_new_event(e)
yield self.notifier.on_new_room_event(
e, extra_users=[joinee]
)
yield self._handle_new_event(e, fetch_missing=False)
except:
logger.exception(
"Failed to parse auth event %s",
@ -376,9 +386,9 @@ class FederationHandler(BaseHandler):
# FIXME: Auth these.
e.outlier = True
try:
yield self._handle_new_event(e)
yield self.notifier.on_new_room_event(
e, extra_users=[joinee]
yield self._handle_new_event(
e,
fetch_missing=True
)
except:
logger.exception(
@ -389,7 +399,7 @@ class FederationHandler(BaseHandler):
yield self._handle_new_event(
event,
state=state,
current_state=state
current_state=state,
)
yield self.notifier.on_new_room_event(
@ -552,7 +562,17 @@ class FederationHandler(BaseHandler):
else:
del results[(event.type, event.state_key)]
defer.returnValue(results.values())
res = results.values()
for event in res:
event.signatures.update(
compute_event_signature(
event,
self.hs.hostname,
self.hs.config.signing_key[0]
)
)
defer.returnValue(res)
else:
defer.returnValue([])
@ -623,11 +643,7 @@ class FederationHandler(BaseHandler):
@defer.inlineCallbacks
def _handle_new_event(self, event, state=None, backfilled=False,
current_state=None):
if state:
for s in state:
yield self._handle_new_event(s)
current_state=None, fetch_missing=True):
is_new_state = yield self.state_handler.annotate_event_with_state(
event,
old_state=state
@ -667,11 +683,22 @@ class FederationHandler(BaseHandler):
)
if not e:
raise AuthError(
403,
"Can't find auth event %s." % (e_id, )
e = yield self.replication_layer.get_pdu(
event.origin, e_id, outlier=True
)
if e and fetch_missing:
try:
yield self.on_receive_pdu(event.origin, e, False)
except:
logger.exception(
"Failed to parse auth event %s",
e_id,
)
if not e:
logger.warn("Can't find auth event %s.", e_id)
auth_events[(e.type, e.state_key)] = e
if event.type == RoomMemberEvent.TYPE and not event.auth_events:

View File

@ -42,6 +42,7 @@ class FederationTestCase(unittest.TestCase):
self.auth = NonCallableMock(spec_set=[
"check",
"check_host_in_room",
])
self.hostname = "test"
@ -89,13 +90,16 @@ class FederationTestCase(unittest.TestCase):
self.datastore.persist_event.return_value = defer.succeed(None)
self.datastore.get_room.return_value = defer.succeed(True)
self.auth.check_host_in_room.return_value = defer.succeed(True)
def annotate(ev, old_state=None):
ev.old_state_events = []
return defer.succeed(False)
self.state_handler.annotate_event_with_state.side_effect = annotate
yield self.handlers.federation_handler.on_receive_pdu(pdu, False)
yield self.handlers.federation_handler.on_receive_pdu(
"fo", pdu, False
)
self.datastore.persist_event.assert_called_once_with(
ANY, is_new_state=False, backfilled=False, current_state=None