Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redact membership events if the user requested erasure upon deactivating #17076

Merged
merged 11 commits into from
Apr 25, 2024
37 changes: 34 additions & 3 deletions synapse/handlers/deactivate_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
import logging
from typing import TYPE_CHECKING, Optional

from synapse.api.constants import Membership
from synapse.api.constants import EventTypes, Membership
from synapse.api.errors import SynapseError
from synapse.events import EventBase
from synapse.handlers.device import DeviceHandler
from synapse.metrics.background_process_metrics import run_as_background_process
from synapse.types import Codes, Requester, UserID, create_requester
Expand All @@ -48,6 +49,7 @@ def __init__(self, hs: "HomeServer"):
self.user_directory_handler = hs.get_user_directory_handler()
self._server_name = hs.hostname
self._third_party_rules = hs.get_module_api_callbacks().third_party_event_rules
self._event_creation_handler = hs.get_event_creation_handler()

# Flag that indicates whether the process to part users from rooms is running
self._user_parter_running = False
Expand Down Expand Up @@ -261,11 +263,40 @@ async def _part_user(self, user_id: str) -> None:
user = UserID.from_string(user_id)

rooms_for_user = await self.store.get_rooms_for_user(user_id)
requester = create_requester(user, authenticated_entity=self._server_name)
should_erase = await self.store.is_user_erased(user_id)

for room_id in rooms_for_user:
logger.info("User parter parting %r from %r", user_id, room_id)
try:
# Before parting the user, redact all membership events if requested
if should_erase:
event_ids = await self.store.get_membership_event_ids_for_user(
user_id, room_id
)
events: list[EventBase] = await self.store.get_events_as_list(
event_ids
)
for event in events:
has_profile = (
"displayname" in event.content
or "avatar_url" in event.content
)
if has_profile and "redacted_because" not in event.unsigned:
erikjohnston marked this conversation as resolved.
Show resolved Hide resolved
event_dict = {
"type": EventTypes.Redaction,
"room_id": event["room_id"],
"sender": requester.user.to_string(),
}
if event.room_version.updated_redaction_rules:
event_dict["content"]["redacts"] = event.event_id
else:
event_dict["redacts"] = event.event_id
await self._event_creation_handler.create_event(
requester, event_dict, ratelimit=False
erikjohnston marked this conversation as resolved.
Show resolved Hide resolved
)

await self._room_member_handler.update_membership(
create_requester(user, authenticated_entity=self._server_name),
requester,
user,
room_id,
"leave",
Expand Down
22 changes: 22 additions & 0 deletions synapse/storage/databases/main/roommember.py
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,28 @@ async def get_rooms_user_has_been_in(self, user_id: str) -> Set[str]:

return set(room_ids)

async def get_membership_event_ids_for_user(
self, user_id: str, room_id: str
) -> Set[str]:
"""Get all event_ids for the given user and room.
Args:
user_id: The user ID to get the event IDs for.
room_id: The room ID to look up events for.
Returns:
Set of event IDs
"""

event_ids = await self.db_pool.simple_select_onecol(
table="room_memberships",
keyvalues={"user_id": user_id, "room_id": room_id},
retcol="event_id",
desc="get_membership_event_ids_for_user",
)

return set(event_ids)

@cached(max_entries=5000)
async def _get_membership_from_event_id(
self, member_event_id: str
Expand Down
Loading