Repository: matrix-org/synapse

Issue:
Change displayname of users as admin does not work
<!--

**IF YOU HAVE SUPPORT QUESTIONS ABOUT RUNNING OR CONFIGURING YOUR OWN HOME SERVER**:
You will likely get better support more quickly if you ask in ** #synapse:matrix.org ** ;)


This is a bug report template. By following the instructions below and
filling out the sections with your information, you will help the us to get all
the necessary data to fix your issue.

You can also preview your report before submitting it. You may remove sections
that aren't relevant to your particular case.

Text between <!-- and --​> marks will be invisible in the report.

-->

### Description

<!-- Describe here the problem that you are experiencing -->
I try to change the displayname of other users as admin. The change in profile ist ok, but I get errors for displayname in rooms.

```
2019-12-19 14:45:57,831 - synapse.access.http.8008 - 233 - INFO - PUT-906- - - 8008 - Received request: PUT /_matrix/client/r0/profile/@user:server.cloudapp.azure.com/displayname
2019-12-19 14:45:57,932 - synapse.handlers.message - 695 - WARNING - PUT-906- Denying new event <FrozenEventV3 event_id='$e_mVDdJ-rQVW25vaOgXIU3zNppPZfOCJUo5YhMQ0rTM', type='m.room.member', state_key='@user:server.cloudapp.azure.com'> because 403: Cannot force another user to join.
2019-12-19 14:45:57,932 - synapse.handlers.profile - 281 - WARNING - PUT-906- Failed to update join event for room !GstgHdhajwAvSueHan:server.cloudapp.azure.com - 403: Cannot force another user to join.
2019-12-19 14:45:57,966 - synapse.handlers.message - 695 - WARNING - PUT-906- Denying new event <FrozenEvent event_id='$157676675735pBzAC:server.cloudapp.azure.com', type='m.room.member', state_key='@user:server.cloudapp.azure.com'> because 403: Cannot force another user to join.
2019-12-19 14:45:57,967 - synapse.handlers.profile - 281 - WARNING - PUT-906- Failed to update join event for room !AvSWOczTtSmEVpjVlF:server.cloudapp.azure.com - 403: Cannot force another user to join.
2019-12-19 14:45:58,724 - synapse.access.http.8008 - 302 - INFO - PUT-906- - - 8008 - {@admin_user:server.cloudapp.azure.com} Processed request: 0.892sec/0.000sec (0.051sec, 0.011sec) (0.085sec/0.662sec/109) 3B 200 "PUT /_matrix/client/r0/profile/@user:server.cloudapp.azure.com/displayname HTTP/1.1" "curl/7.58.0" [0 dbevts]
```

### Steps to reproduce

```
curl -X PUT --header 'Authorization: Bearer access_token' --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ "displayname": "new name" }' 'http://localhost:8008/_matrix/client/r0/profile/@user:server.cloudapp.azure.com/displayname' -i

HTTP/1.1 200 OK
Server: Synapse/1.6.1
Date: Thu, 19 Dec 2019 14:45:57 GMT
Content-Type: application/json
Content-Length: 3
Cache-Control: no-cache, no-store, must-revalidate
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization

{}
```


<!--
Describe how what happens differs from what you expected.

If you can identify any relevant log snippets from _homeserver.log_, please include
those (please be careful to remove any personal or private data). Please surround them with
``` (three backticks, on a line on their own), so that they are formatted legibly.
-->

### Version information

<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->

<!-- Was this issue identified on matrix.org or another homeserver? -->
- **Homeserver**: 

If not matrix.org:

<!--
 What version of Synapse is running?

You can find the Synapse version with this command:

$ curl http://localhost:8008/_synapse/admin/v1/server_version

(You may need to replace `localhost:8008` if Synapse is not configured to
listen on that port.)
-->
- **Version**: v1.6.1

- **Install method**: Ubuntu/Debian package manager
<!-- examples: package manager/git clone/pip  -->

- **Platform**: Ubuntu, Azure VM
<!--
Tell us about the environment in which your homeserver is operating
distro, hardware, if it's running in a vm/container, etc.
-->


How can I support? Do you need more informations?
Callled function: https://github.com/matrix-org/synapse/blob/master/synapse/handlers/profile.py#L257
Error: https://github.com/matrix-org/synapse/blob/master/synapse/event_auth.py#L294


Discussion:
the basic problem is that other servers in the room have no way to know that your user is an admin, so they wouldn't know that you are allowed to send membership events on behalf of the other user.

A potential fix to this would be for synapse to spoof a membership event from the target_user.


Resolving patch:
diff --git a/synapse/handlers/profile.py b/synapse/handlers/profile.py
--- a/synapse/handlers/profile.py
+++ b/synapse/handlers/profile.py
@@ -28,7 +28,7 @@
     SynapseError,
 )
 from synapse.metrics.background_process_metrics import run_as_background_process
-from synapse.types import UserID, get_domain_from_id
+from synapse.types import UserID, create_requester, get_domain_from_id
 
 from ._base import BaseHandler
 
@@ -165,6 +165,12 @@ def set_displayname(self, target_user, requester, new_displayname, by_admin=Fals
         if new_displayname == "":
             new_displayname = None
 
+        # If the admin changes the display name of a user, the requesting user cannot send
+        # the join event to update the displayname in the rooms.
+        # This must be done by the target user himself.
+        if by_admin:
+            requester = create_requester(target_user)
+
         yield self.store.set_profile_displayname(target_user.localpart, new_displayname)
 
         if self.hs.config.user_directory_search_all_users:
@@ -217,6 +223,10 @@ def set_avatar_url(self, target_user, requester, new_avatar_url, by_admin=False)
                 400, "Avatar URL is too long (max %i)" % (MAX_AVATAR_URL_LEN,)
             )
 
+        # Same like set_displayname
+        if by_admin:
+            requester = create_requester(target_user)
+
         yield self.store.set_profile_avatar_url(target_user.localpart, new_avatar_url)
 
         if self.hs.config.user_directory_search_all_users:


Test patch: