diff --git a/synapse/handlers/_base.py b/synapse/handlers/_base.py
index 6a26cb1879..6873a4575d 100644
--- a/synapse/handlers/_base.py
+++ b/synapse/handlers/_base.py
@@ -47,37 +47,23 @@ class BaseHandler(object):
self.event_builder_factory = hs.get_event_builder_factory()
@defer.inlineCallbacks
- def _filter_events_for_client(self, user_id, events):
- event_id_to_state = yield self.store.get_state_for_events(
- frozenset(e.event_id for e in events),
- types=(
- (EventTypes.RoomHistoryVisibility, ""),
- (EventTypes.Member, user_id),
- )
- )
+ def _filter_events_for_client(self, user_id, events, is_guest=False):
+ # Assumes that user has at some point joined the room if not is_guest.
- def allowed(event, state):
- if event.type == EventTypes.RoomHistoryVisibility:
+ def allowed(event, membership, visibility):
+ if visibility == "world_readable":
return True
- membership_ev = state.get((EventTypes.Member, user_id), None)
- if membership_ev:
- membership = membership_ev.membership
- else:
- membership = Membership.LEAVE
+ if is_guest:
+ return False
if membership == Membership.JOIN:
return True
- history = state.get((EventTypes.RoomHistoryVisibility, ''), None)
- if history:
- visibility = history.content.get("history_visibility", "shared")
- else:
- visibility = "shared"
+ if event.type == EventTypes.RoomHistoryVisibility:
+ return not is_guest
- if visibility == "public":
- return True
- elif visibility == "shared":
+ if visibility == "shared":
return True
elif visibility == "joined":
return membership == Membership.JOIN
@@ -86,11 +72,44 @@ class BaseHandler(object):
return True
- defer.returnValue([
- event
- for event in events
- if allowed(event, event_id_to_state[event.event_id])
- ])
+ event_id_to_state = yield self.store.get_state_for_events(
+ frozenset(e.event_id for e in events),
+ types=(
+ (EventTypes.RoomHistoryVisibility, ""),
+ (EventTypes.Member, user_id),
+ )
+ )
+
+ events_to_return = []
+ for event in events:
+ state = event_id_to_state[event.event_id]
+
+ membership_event = state.get((EventTypes.Member, user_id), None)
+ if membership_event:
+ membership = membership_event.membership
+ else:
+ membership = None
+
+ visibility_event = state.get((EventTypes.RoomHistoryVisibility, ""), None)
+ if visibility_event:
+ visibility = visibility_event.content.get("history_visibility", "shared")
+ else:
+ visibility = "shared"
+
+ should_include = allowed(event, membership, visibility)
+ if should_include:
+ events_to_return.append(event)
+
+ if is_guest and len(events_to_return) < len(events):
+ # This indicates that some events in the requested range were not
+ # visible to guest users. To be safe, we reject the entire request,
+ # so that we don't have to worry about interpreting visibility
+ # boundaries.
+ raise AuthError(403, "User %s does not have permission" % (
+ user_id
+ ))
+
+ defer.returnValue(events_to_return)
def ratelimit(self, user_id):
time_now = self.clock.time()
|