diff --git a/synapse/handlers/profile.py b/synapse/handlers/profile.py index ce044aa480..5c4a54b920 100644 --- a/synapse/handlers/profile.py +++ b/synapse/handlers/profile.py @@ -627,13 +627,23 @@ class ProfileHandler: propagate=propagate, ) else: - await self.set_profile_field( - target_user=target_user, - requester=requester, - field_name=field_name, - new_value=new_value, - by_admin=by_admin, - ) + # For custom fields, we need to call a separate delete method + # for empty strings. + if new_value == "": + await self.delete_profile_field( + target_user=target_user, + requester=requester, + field_name=field_name, + by_admin=by_admin, + ) + else: + await self.set_profile_field( + target_user=target_user, + requester=requester, + field_name=field_name, + new_value=new_value, + by_admin=by_admin, + ) async def set_profile_field( self, diff --git a/synapse/replication/http/profile.py b/synapse/replication/http/profile.py index 93b7be2d07..c5e5448f8e 100644 --- a/synapse/replication/http/profile.py +++ b/synapse/replication/http/profile.py @@ -63,7 +63,7 @@ class ReplicationProfileSetFieldValue(ReplicationEndpoint): async def _serialize_payload( # type: ignore[override] requester_id: str, field_name: str, - new_value: str | None, + new_value: str, by_admin: bool = False, propagate: bool = False, authenticated_entity: str | None = None, @@ -84,7 +84,9 @@ class ReplicationProfileSetFieldValue(ReplicationEndpoint): # ie an admin who has done the request on behalf of the user. requester = create_requester( user_id=user_id, - authenticated_entity=content["authenticated_entity"] if content["by_admin"] else None, + authenticated_entity=content["authenticated_entity"] + if content["by_admin"] + else None, ) await self._profile_handler.set_field( target_user=UserID.from_string(user_id), diff --git a/synapse/rest/client/profile.py b/synapse/rest/client/profile.py index e7b2e4bcda..7cd4678bc0 100644 --- a/synapse/rest/client/profile.py +++ b/synapse/rest/client/profile.py @@ -241,12 +241,6 @@ class ProfileFieldRestServlet(RestServlet): async def on_DELETE( self, request: SynapseRequest, user_id: str, field_name: str ) -> tuple[int, JsonDict]: - if not self._is_profile_worker: - raise SynapseError( - HTTPStatus.METHOD_NOT_ALLOWED, - "Can only handle DELETE /profile on instances configured to handle the profile_updates stream writer", - Codes.UNRECOGNIZED, - ) if not UserID.is_valid(user_id): raise SynapseError( HTTPStatus.BAD_REQUEST, "Invalid user id", Codes.INVALID_PARAM @@ -286,17 +280,32 @@ class ProfileFieldRestServlet(RestServlet): Codes.USER_ACCOUNT_SUSPENDED, ) - if field_name == ProfileFields.DISPLAYNAME: - await self.profile_handler.set_displayname( - user, requester, "", by_admin=is_admin, propagate=propagate - ) - elif field_name == ProfileFields.AVATAR_URL: - await self.profile_handler.set_avatar_url( - user, requester, "", by_admin=is_admin, propagate=propagate + if self._is_profile_worker: + await self.profile_handler.set_field( + target_user=user, + requester=requester, + field_name=field_name, + new_value="", + by_admin=is_admin, + propagate=propagate, ) else: - await self.profile_handler.delete_profile_field( - user, requester, field_name, by_admin=is_admin + # Offload to the right worker via http replication + set_profile_data_client = ReplicationProfileSetFieldValue.make_client( + self.hs + ) + profile_updates_writer_instance = ( + self.hs.config.worker.writers.profile_updates[0] + ) + await set_profile_data_client( + instance_name=profile_updates_writer_instance, + user_id=user.to_string(), + requester_id=requester.user.to_string(), + field_name=field_name, + new_value="", + by_admin=is_admin, + propagate=propagate, + authenticated_entity=requester.authenticated_entity, ) return 200, {}