mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-19 20:10:25 -04:00
Remove user's avatar URL and displayname when deactivated. (#8932)
This only applies if the user's data is to be erased.
This commit is contained in:
parent
789d9ebad3
commit
7a2e9b549d
13 changed files with 351 additions and 17 deletions
|
@ -18,7 +18,7 @@ from typing import TYPE_CHECKING, Optional
|
|||
|
||||
from synapse.api.errors import SynapseError
|
||||
from synapse.metrics.background_process_metrics import run_as_background_process
|
||||
from synapse.types import UserID, create_requester
|
||||
from synapse.types import Requester, UserID, create_requester
|
||||
|
||||
from ._base import BaseHandler
|
||||
|
||||
|
@ -38,6 +38,7 @@ class DeactivateAccountHandler(BaseHandler):
|
|||
self._device_handler = hs.get_device_handler()
|
||||
self._room_member_handler = hs.get_room_member_handler()
|
||||
self._identity_handler = hs.get_identity_handler()
|
||||
self._profile_handler = hs.get_profile_handler()
|
||||
self.user_directory_handler = hs.get_user_directory_handler()
|
||||
self._server_name = hs.hostname
|
||||
|
||||
|
@ -52,16 +53,23 @@ class DeactivateAccountHandler(BaseHandler):
|
|||
self._account_validity_enabled = hs.config.account_validity.enabled
|
||||
|
||||
async def deactivate_account(
|
||||
self, user_id: str, erase_data: bool, id_server: Optional[str] = None
|
||||
self,
|
||||
user_id: str,
|
||||
erase_data: bool,
|
||||
requester: Requester,
|
||||
id_server: Optional[str] = None,
|
||||
by_admin: bool = False,
|
||||
) -> bool:
|
||||
"""Deactivate a user's account
|
||||
|
||||
Args:
|
||||
user_id: ID of user to be deactivated
|
||||
erase_data: whether to GDPR-erase the user's data
|
||||
requester: The user attempting to make this change.
|
||||
id_server: Use the given identity server when unbinding
|
||||
any threepids. If None then will attempt to unbind using the
|
||||
identity server specified when binding (if known).
|
||||
by_admin: Whether this change was made by an administrator.
|
||||
|
||||
Returns:
|
||||
True if identity server supports removing threepids, otherwise False.
|
||||
|
@ -121,6 +129,12 @@ class DeactivateAccountHandler(BaseHandler):
|
|||
|
||||
# Mark the user as erased, if they asked for that
|
||||
if erase_data:
|
||||
user = UserID.from_string(user_id)
|
||||
# Remove avatar URL from this user
|
||||
await self._profile_handler.set_avatar_url(user, requester, "", by_admin)
|
||||
# Remove displayname from this user
|
||||
await self._profile_handler.set_displayname(user, requester, "", by_admin)
|
||||
|
||||
logger.info("Marking %s as erased", user_id)
|
||||
await self.store.mark_user_erased(user_id)
|
||||
|
||||
|
|
|
@ -286,13 +286,19 @@ class ProfileHandler(BaseHandler):
|
|||
400, "Avatar URL is too long (max %i)" % (MAX_AVATAR_URL_LEN,)
|
||||
)
|
||||
|
||||
avatar_url_to_set = new_avatar_url # type: Optional[str]
|
||||
if new_avatar_url == "":
|
||||
avatar_url_to_set = None
|
||||
|
||||
# Same like set_displayname
|
||||
if by_admin:
|
||||
requester = create_requester(
|
||||
target_user, authenticated_entity=requester.authenticated_entity
|
||||
)
|
||||
|
||||
await self.store.set_profile_avatar_url(target_user.localpart, new_avatar_url)
|
||||
await self.store.set_profile_avatar_url(
|
||||
target_user.localpart, avatar_url_to_set
|
||||
)
|
||||
|
||||
if self.hs.config.user_directory_search_all_users:
|
||||
profile = await self.store.get_profileinfo(target_user.localpart)
|
||||
|
|
|
@ -244,7 +244,7 @@ class UserRestServletV2(RestServlet):
|
|||
|
||||
if deactivate and not user["deactivated"]:
|
||||
await self.deactivate_account_handler.deactivate_account(
|
||||
target_user.to_string(), False
|
||||
target_user.to_string(), False, requester, by_admin=True
|
||||
)
|
||||
elif not deactivate and user["deactivated"]:
|
||||
if "password" not in body:
|
||||
|
@ -486,12 +486,22 @@ class WhoisRestServlet(RestServlet):
|
|||
class DeactivateAccountRestServlet(RestServlet):
|
||||
PATTERNS = admin_patterns("/deactivate/(?P<target_user_id>[^/]*)")
|
||||
|
||||
def __init__(self, hs):
|
||||
def __init__(self, hs: "HomeServer"):
|
||||
self._deactivate_account_handler = hs.get_deactivate_account_handler()
|
||||
self.auth = hs.get_auth()
|
||||
self.is_mine = hs.is_mine
|
||||
self.store = hs.get_datastore()
|
||||
|
||||
async def on_POST(self, request: str, target_user_id: str) -> Tuple[int, JsonDict]:
|
||||
requester = await self.auth.get_user_by_req(request)
|
||||
await assert_user_is_admin(self.auth, requester.user)
|
||||
|
||||
if not self.is_mine(UserID.from_string(target_user_id)):
|
||||
raise SynapseError(400, "Can only deactivate local users")
|
||||
|
||||
if not await self.store.get_user_by_id(target_user_id):
|
||||
raise NotFoundError("User not found")
|
||||
|
||||
async def on_POST(self, request, target_user_id):
|
||||
await assert_requester_is_admin(self.auth, request)
|
||||
body = parse_json_object_from_request(request, allow_empty_body=True)
|
||||
erase = body.get("erase", False)
|
||||
if not isinstance(erase, bool):
|
||||
|
@ -501,10 +511,8 @@ class DeactivateAccountRestServlet(RestServlet):
|
|||
Codes.BAD_JSON,
|
||||
)
|
||||
|
||||
UserID.from_string(target_user_id)
|
||||
|
||||
result = await self._deactivate_account_handler.deactivate_account(
|
||||
target_user_id, erase
|
||||
target_user_id, erase, requester, by_admin=True
|
||||
)
|
||||
if result:
|
||||
id_server_unbind_result = "success"
|
||||
|
|
|
@ -305,7 +305,7 @@ class DeactivateAccountRestServlet(RestServlet):
|
|||
# allow ASes to deactivate their own users
|
||||
if requester.app_service:
|
||||
await self._deactivate_account_handler.deactivate_account(
|
||||
requester.user.to_string(), erase
|
||||
requester.user.to_string(), erase, requester
|
||||
)
|
||||
return 200, {}
|
||||
|
||||
|
@ -313,7 +313,10 @@ class DeactivateAccountRestServlet(RestServlet):
|
|||
requester, request, body, "deactivate your account",
|
||||
)
|
||||
result = await self._deactivate_account_handler.deactivate_account(
|
||||
requester.user.to_string(), erase, id_server=body.get("id_server")
|
||||
requester.user.to_string(),
|
||||
erase,
|
||||
requester,
|
||||
id_server=body.get("id_server"),
|
||||
)
|
||||
if result:
|
||||
id_server_unbind_result = "success"
|
||||
|
|
|
@ -501,7 +501,7 @@ class HomeServer(metaclass=abc.ABCMeta):
|
|||
return InitialSyncHandler(self)
|
||||
|
||||
@cache_in_self
|
||||
def get_profile_handler(self):
|
||||
def get_profile_handler(self) -> ProfileHandler:
|
||||
return ProfileHandler(self)
|
||||
|
||||
@cache_in_self
|
||||
|
|
|
@ -82,7 +82,7 @@ class ProfileWorkerStore(SQLBaseStore):
|
|||
)
|
||||
|
||||
async def set_profile_avatar_url(
|
||||
self, user_localpart: str, new_avatar_url: str
|
||||
self, user_localpart: str, new_avatar_url: Optional[str]
|
||||
) -> None:
|
||||
await self.db_pool.simple_update_one(
|
||||
table="profiles",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue