Skip to content
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:
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
)

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