mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-14 19:23:53 +01:00
Only check history visibility when filtering
When filtering events to send to server we check more than just history visibility. However when deciding whether to backfill or not we only care about the history visibility.
This commit is contained in:
parent
8b63fe4c26
commit
d1523aed6b
2 changed files with 46 additions and 35 deletions
|
@ -891,9 +891,11 @@ class FederationHandler(BaseHandler):
|
||||||
get_prev_content=False,
|
get_prev_content=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# We set `check_history_visibility_only` as we might otherwise get false
|
||||||
|
# positives from users having been erased.
|
||||||
filtered_extremities = yield filter_events_for_server(
|
filtered_extremities = yield filter_events_for_server(
|
||||||
self.store, self.server_name, list(extremities_events.values()),
|
self.store, self.server_name, list(extremities_events.values()),
|
||||||
redact=False,
|
redact=False, check_history_visibility_only=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not filtered_extremities:
|
if not filtered_extremities:
|
||||||
|
|
|
@ -216,7 +216,8 @@ def filter_events_for_client(store, user_id, events, is_peeking=False,
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def filter_events_for_server(store, server_name, events, redact=True):
|
def filter_events_for_server(store, server_name, events, redact=True,
|
||||||
|
check_history_visibility_only=False):
|
||||||
"""Filter a list of events based on whether given server is allowed to
|
"""Filter a list of events based on whether given server is allowed to
|
||||||
see them.
|
see them.
|
||||||
|
|
||||||
|
@ -226,34 +227,25 @@ def filter_events_for_server(store, server_name, events, redact=True):
|
||||||
events (iterable[FrozenEvent])
|
events (iterable[FrozenEvent])
|
||||||
redact (bool): Whether to return a redacted version of the event, or
|
redact (bool): Whether to return a redacted version of the event, or
|
||||||
to filter them out entirely.
|
to filter them out entirely.
|
||||||
|
check_history_visibility_only (bool): Whether to only check the
|
||||||
|
history visibility, rather than things like if the sender has been
|
||||||
|
erased. This is used e.g. during pagination to decide whether to
|
||||||
|
backfill or not.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
Deferred[list[FrozenEvent]]
|
Deferred[list[FrozenEvent]]
|
||||||
"""
|
"""
|
||||||
# Whatever else we do, we need to check for senders which have requested
|
|
||||||
# erasure of their data.
|
|
||||||
erased_senders = yield store.are_users_erased(
|
|
||||||
(e.sender for e in events),
|
|
||||||
)
|
|
||||||
|
|
||||||
def redact_disallowed(event, state):
|
def is_sender_erased(event, erased_senders):
|
||||||
# if the sender has been gdpr17ed, always return a redacted
|
|
||||||
# copy of the event.
|
|
||||||
if erased_senders[event.sender]:
|
if erased_senders[event.sender]:
|
||||||
logger.info(
|
logger.info(
|
||||||
"Sender of %s has been erased, redacting",
|
"Sender of %s has been erased, redacting",
|
||||||
event.event_id,
|
event.event_id,
|
||||||
)
|
)
|
||||||
if redact:
|
return True
|
||||||
return prune_event(event)
|
return False
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# state will be None if we decided we didn't need to filter by
|
|
||||||
# room membership.
|
|
||||||
if not state:
|
|
||||||
return event
|
|
||||||
|
|
||||||
|
def check_event_is_visible(event, state):
|
||||||
history = state.get((EventTypes.RoomHistoryVisibility, ''), None)
|
history = state.get((EventTypes.RoomHistoryVisibility, ''), None)
|
||||||
if history:
|
if history:
|
||||||
visibility = history.content.get("history_visibility", "shared")
|
visibility = history.content.get("history_visibility", "shared")
|
||||||
|
@ -275,18 +267,15 @@ def filter_events_for_server(store, server_name, events, redact=True):
|
||||||
|
|
||||||
memtype = ev.membership
|
memtype = ev.membership
|
||||||
if memtype == Membership.JOIN:
|
if memtype == Membership.JOIN:
|
||||||
return event
|
return True
|
||||||
elif memtype == Membership.INVITE:
|
elif memtype == Membership.INVITE:
|
||||||
if visibility == "invited":
|
if visibility == "invited":
|
||||||
return event
|
return True
|
||||||
else:
|
else:
|
||||||
# server has no users in the room: redact
|
# server has no users in the room: redact
|
||||||
if redact:
|
return False
|
||||||
return prune_event(event)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return event
|
return True
|
||||||
|
|
||||||
# Next lets check to see if all the events have a history visibility
|
# Next lets check to see if all the events have a history visibility
|
||||||
# of "shared" or "world_readable". If thats the case then we don't
|
# of "shared" or "world_readable". If thats the case then we don't
|
||||||
|
@ -315,16 +304,31 @@ def filter_events_for_server(store, server_name, events, redact=True):
|
||||||
for e in itervalues(event_map)
|
for e in itervalues(event_map)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not check_history_visibility_only:
|
||||||
|
erased_senders = yield store.are_users_erased(
|
||||||
|
(e.sender for e in events),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# We don't want to check whether users are erased, which is equivalent
|
||||||
|
# to no users having been erased.
|
||||||
|
erased_senders = {}
|
||||||
|
|
||||||
if all_open:
|
if all_open:
|
||||||
# all the history_visibility state affecting these events is open, so
|
# all the history_visibility state affecting these events is open, so
|
||||||
# we don't need to filter by membership state. We *do* need to check
|
# we don't need to filter by membership state. We *do* need to check
|
||||||
# for user erasure, though.
|
# for user erasure, though.
|
||||||
if erased_senders:
|
if erased_senders:
|
||||||
events = [
|
to_return = []
|
||||||
redact_disallowed(e, None)
|
for e in events:
|
||||||
for e in events
|
if not is_sender_erased(e, erased_senders):
|
||||||
]
|
to_return.append(e)
|
||||||
|
elif redact:
|
||||||
|
to_return.append(prune_event(e))
|
||||||
|
|
||||||
|
defer.returnValue(to_return)
|
||||||
|
|
||||||
|
# If there are no erased users then we can just return the given list
|
||||||
|
# of events without having to copy it.
|
||||||
defer.returnValue(events)
|
defer.returnValue(events)
|
||||||
|
|
||||||
# Ok, so we're dealing with events that have non-trivial visibility
|
# Ok, so we're dealing with events that have non-trivial visibility
|
||||||
|
@ -380,8 +384,13 @@ def filter_events_for_server(store, server_name, events, redact=True):
|
||||||
for e_id, key_to_eid in iteritems(event_to_state_ids)
|
for e_id, key_to_eid in iteritems(event_to_state_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
to_return = (
|
to_return = []
|
||||||
redact_disallowed(e, event_to_state[e.event_id])
|
for e in events:
|
||||||
for e in events
|
erased = is_sender_erased(e, erased_senders)
|
||||||
)
|
visible = check_event_is_visible(e, event_to_state[e.event_id])
|
||||||
defer.returnValue([e for e in to_return if e is not None])
|
if visible and not erased:
|
||||||
|
to_return.append(e)
|
||||||
|
elif redact:
|
||||||
|
to_return.append(prune_event(e))
|
||||||
|
|
||||||
|
defer.returnValue(to_return)
|
||||||
|
|
Loading…
Reference in a new issue