Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions synapse/config/experimental.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,8 +584,7 @@ def read_config(

# MSC4293: Redact on Kick/Ban
self.msc4293_enabled: bool = experimental.get("msc4293_enabled", False)

# MSC4306: Thread Subscriptions
# (and MSC4308: sliding sync extension for thread subscriptions)
self.msc4306_enabled: bool = experimental.get("msc4306_enabled", False)

56 changes: 37 additions & 19 deletions synapse/storage/databases/main/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ async def _persist_events_and_state_updates(

# check that sender can redact
redact_allowed = await self._can_sender_redact(event)

# Signal that this user's past events in this room
# should be redacted by adding an entry to
# `room_ban_redactions`.
if redact_allowed:
await self.db_pool.simple_upsert(
"room_ban_redactions",
Expand Down Expand Up @@ -451,31 +455,45 @@ async def _persist_events_and_state_updates(
)

async def _can_sender_redact(self, event: EventBase) -> bool:
state_filter = StateFilter.from_types([(EventTypes.PowerLevels, "")])
state_filter = StateFilter.from_types(
[(EventTypes.PowerLevels, ""), (EventTypes.Create, "")]
)
state = await self.store.get_partial_filtered_current_state_ids(
event.room_id, state_filter
)
pl_id = state[(EventTypes.PowerLevels, "")]
pl_event = await self.store.get_event(pl_id)
if pl_event:
sender_level = pl_event.content.get("users", {}).get(event.sender)
if sender_level is None:
sender_level = pl_event.content.get("users_default", 0)

redact_level = pl_event.content.get("redact")
if not redact_level:
redact_level = pl_event.content.get("events_default", 0)

room_redaction_level = pl_event.content.get("events", {}).get(
"m.room.redaction"
)
if room_redaction_level:
if sender_level < room_redaction_level:
return False

if sender_level >= redact_level:
pl_event = await self.store.get_event(pl_id, allow_none=True)

if pl_event is None:
# per the spec, if a power level event isn't in the room, grant the creator
# level 100 and all other users 0
create_id = state[(EventTypes.Create, "")]
create_event = await self.store.get_event(create_id, allow_none=True)
if create_event is None:
# not sure how this would happen but if it does then just deny the redaction
return False
if create_event.sender == event.sender:
return True

assert pl_event is not None
sender_level = pl_event.content.get("users", {}).get(event.sender)
if sender_level is None:
sender_level = pl_event.content.get("users_default", 0)

redact_level = pl_event.content.get("redact")
if not redact_level:
redact_level = pl_event.content.get("events_default", 0)

room_redaction_level = pl_event.content.get("events", {}).get(
"m.room.redaction"
)
if room_redaction_level:
if sender_level < room_redaction_level:
return False

if sender_level >= redact_level:
return True

return False

async def _calculate_sliding_sync_table_changes(
Expand Down
5 changes: 4 additions & 1 deletion synapse/storage/databases/main/events_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1614,7 +1614,10 @@ def _fetch_event_rows(
continue
redacting_event_id, redact_end_ordering = res
if redact_end_ordering:
if e_row.stream_ordering > redact_end_ordering:
# Avoid redacting any events arriving *after* the membership event which
# ends an active redaction - note that this will always redact
# backfilled events, as they have a negative stream ordering
if e_row.stream_ordering >= redact_end_ordering:
continue
e_row.redactions.append(redacting_event_id)
return event_dict
Expand Down
14 changes: 7 additions & 7 deletions tests/rest/client/test_rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4590,7 +4590,7 @@ def _check_redactions(
def test_banning_local_member_with_flag_redacts_their_events(self) -> None:
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)

# bad user send some messages
# bad user sends some messages
originals = []
for i in range(5):
event = {"body": f"bothersome noise {i}", "msgtype": "m.text"}
Expand Down Expand Up @@ -4916,7 +4916,7 @@ def test_redaction_flag_ignored_for_user_if_banner_lacks_redaction_power(
)
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)

# bad user send some messages
# bad user sends some messages
original_ids = []
for i in range(15):
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
Expand Down Expand Up @@ -4955,7 +4955,7 @@ def test_redaction_flag_ignored_for_user_if_banner_lacks_redaction_power(
def test_kicking_local_member_with_flag_redacts_their_events(self) -> None:
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)

# bad user send some messages
# bad user sends some messages
originals = []
for i in range(5):
event = {"body": f"bothersome noise {i}", "msgtype": "m.text"}
Expand Down Expand Up @@ -5273,7 +5273,7 @@ def test_redaction_flag_ignored_for_user_if_kicker_lacks_redaction_power(
)
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)

# bad user send some messages
# bad user sends some messages
original_ids = []
for i in range(15):
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
Expand Down Expand Up @@ -5312,7 +5312,7 @@ def test_redaction_flag_ignored_for_user_if_kicker_lacks_redaction_power(
def test_MSC4293_flag_ignored_in_other_membership_events(self) -> None:
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)

# bad user send some messages
# bad user sends some messages
original_ids = []
for i in range(15):
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
Expand Down Expand Up @@ -5399,7 +5399,7 @@ def test_MSC4293_redaction_applied_via_kick_api(self) -> None:
"""
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)

# bad user send some messages
# bad user sends some messages
original_ids = []
for i in range(15):
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
Expand Down Expand Up @@ -5444,7 +5444,7 @@ def test_MSC4293_redaction_applied_via_ban_api(self) -> None:
"""
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)

# bad user send some messages
# bad user sends some messages
original_ids = []
for i in range(15):
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
Expand Down
Loading