Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.
17 changes: 15 additions & 2 deletions synapse/handlers/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# limitations under the License.

import logging
import random

from synapse.api.errors import (
AuthError,
Expand Down Expand Up @@ -213,8 +214,14 @@ async def get_avatar_url(self, target_user):
async def set_avatar_url(
self, target_user, requester, new_avatar_url, by_admin=False
):
"""target_user is the user whose avatar_url is to be changed;
auth_user is the user attempting to make this change."""
"""Set a new avatar URL for a user.

Args:
target_user (UserID): the user whose displayname is to be changed.
requester (Requester): The user attempting to make this change.
new_displayname (str): The displayname to give this user.
by_admin (bool): Whether this change was made by an administrator.
"""
if not self.hs.is_mine(target_user):
raise SynapseError(400, "User is not hosted on this homeserver")

Expand Down Expand Up @@ -278,6 +285,12 @@ async def _update_join_states(self, requester, target_user):

await self.ratelimit(requester)

# Do not actually update the room state for shadow-banned users.
if requester.shadow_banned:
# We randomly sleep a bit just to annoy the requester.
await self.clock.sleep(random.randint(1, 10))
return

room_ids = await self.store.get_rooms_for_user(target_user.to_string())

for room_id in room_ids:
Expand Down
57 changes: 45 additions & 12 deletions tests/rest/client/test_shadow_banned.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,13 @@

import synapse.rest.admin
from synapse.api.constants import EventTypes
from synapse.rest.client.v1 import directory, login, room
from synapse.rest.client.v1 import directory, login, profile, room
from synapse.rest.client.v2_alpha import room_upgrade_rest_servlet

from tests import unittest


# To avoid the tests timing out don't add a delay to "annoy the requester".
@patch("random.randint", new=lambda a, b: 0)
class RoomTestCase(unittest.HomeserverTestCase):
servlets = [
synapse.rest.admin.register_servlets_for_client_rest_resource,
directory.register_servlets,
login.register_servlets,
room.register_servlets,
room_upgrade_rest_servlet.register_servlets,
]

class _ShadowBannedBase(unittest.HomeserverTestCase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elegant way to break the classes up 👍

def prepare(self, reactor, clock, homeserver):
# Create two users, one of which is shadow-banned.
self.banned_user_id = self.register_user("banned", "test")
Expand All @@ -52,6 +42,18 @@ def prepare(self, reactor, clock, homeserver):
self.other_user_id = self.register_user("otheruser", "pass")
self.other_access_token = self.login("otheruser", "pass")


# To avoid the tests timing out don't add a delay to "annoy the requester".
@patch("random.randint", new=lambda a, b: 0)
class RoomTestCase(_ShadowBannedBase):
servlets = [
synapse.rest.admin.register_servlets_for_client_rest_resource,
directory.register_servlets,
login.register_servlets,
room.register_servlets,
room_upgrade_rest_servlet.register_servlets,
]

def test_invite(self):
"""Invites from shadow-banned users don't actually get sent."""

Expand Down Expand Up @@ -176,3 +178,34 @@ def test_upgrade(self):
summary = self.get_success(self.store.get_room_summary(new_room_id))
# The summary should be empty since the room doesn't exist.
self.assertEqual(summary, {})


# To avoid the tests timing out don't add a delay to "annoy the requester".
@patch("random.randint", new=lambda a, b: 0)
class ProfileTestCase(_ShadowBannedBase):
servlets = [
synapse.rest.admin.register_servlets_for_client_rest_resource,
login.register_servlets,
profile.register_servlets,
]

def test_displayname(self):
"""Profile changes should succeed, but don't end up in a room."""
# The update should succeed.
request, channel = self.make_request(
"PUT",
"/_matrix/client/r0/profile/%s/displayname" % (self.banned_user_id,),
{"displayname": "new display name"},
access_token=self.banned_access_token,
)
self.render(request)
self.assertEquals(200, channel.code, channel.result)
self.assertEqual(channel.json_body, {})

# The user's display name should be updated.
request, channel = self.make_request(
"GET", "/profile/%s/displayname" % (self.banned_user_id,)
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
self.assertEqual(channel.json_body["displayname"], "new display name")