Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

Limit displaynames and avatar URLs #5309

Merged
merged 2 commits into from Jun 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/5309.bugfix
@@ -0,0 +1 @@
Prevent users from setting huge displaynames and avatar URLs.
13 changes: 13 additions & 0 deletions synapse/handlers/profile.py
Expand Up @@ -31,6 +31,9 @@

logger = logging.getLogger(__name__)

MAX_DISPLAYNAME_LEN = 100
MAX_AVATAR_URL_LEN = 1000


class BaseProfileHandler(BaseHandler):
"""Handles fetching and updating user profile information.
Expand Down Expand Up @@ -162,6 +165,11 @@ def set_displayname(self, target_user, requester, new_displayname, by_admin=Fals
if not by_admin and target_user != requester.user:
raise AuthError(400, "Cannot set another user's displayname")

if len(new_displayname) > MAX_DISPLAYNAME_LEN:
raise SynapseError(
400, "Displayname is too long (max %i)" % (MAX_DISPLAYNAME_LEN, ),
)

if new_displayname == '':
new_displayname = None

Expand Down Expand Up @@ -217,6 +225,11 @@ def set_avatar_url(self, target_user, requester, new_avatar_url, by_admin=False)
if not by_admin and target_user != requester.user:
raise AuthError(400, "Cannot set another user's avatar_url")

if len(new_avatar_url) > MAX_AVATAR_URL_LEN:
raise SynapseError(
400, "Avatar URL is too long (max %i)" % (MAX_AVATAR_URL_LEN, ),
)

yield self.store.set_profile_avatar_url(
target_user.localpart, new_avatar_url
)
Expand Down
2 changes: 2 additions & 0 deletions synapse/handlers/register.py
Expand Up @@ -531,6 +531,8 @@ def get_or_create_user(self, requester, localpart, displayname,
A tuple of (user_id, access_token).
Raises:
RegistrationError if there was a problem registering.

NB this is only used in tests. TODO: move it to the test package!
"""
if localpart is None:
raise SynapseError(400, "Request must include user id")
Expand Down
62 changes: 60 additions & 2 deletions tests/rest/client/v1/test_profile.py
Expand Up @@ -14,6 +14,8 @@
# limitations under the License.

"""Tests REST events for /profile paths."""
import json

from mock import Mock

from twisted.internet import defer
Expand All @@ -31,8 +33,11 @@
PATH_PREFIX = "/_matrix/client/api/v1"


class ProfileTestCase(unittest.TestCase):
""" Tests profile management. """
class MockHandlerProfileTestCase(unittest.TestCase):
""" Tests rest layer of profile management.

Todo: move these into ProfileTestCase
"""

@defer.inlineCallbacks
def setUp(self):
Expand Down Expand Up @@ -159,6 +164,59 @@ def test_set_my_avatar(self):
self.assertEquals(mocked_set.call_args[0][2], "http://my.server/pic.gif")


class ProfileTestCase(unittest.HomeserverTestCase):

servlets = [
admin.register_servlets_for_client_rest_resource,
login.register_servlets,
profile.register_servlets,
]

def make_homeserver(self, reactor, clock):
self.hs = self.setup_test_homeserver()
return self.hs

def prepare(self, reactor, clock, hs):
self.owner = self.register_user("owner", "pass")
self.owner_tok = self.login("owner", "pass")

def test_set_displayname(self):
request, channel = self.make_request(
"PUT",
"/profile/%s/displayname" % (self.owner, ),
content=json.dumps({"displayname": "test"}),
access_token=self.owner_tok,
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)

res = self.get_displayname()
self.assertEqual(res, "test")

def test_set_displayname_too_long(self):
"""Attempts to set a stupid displayname should get a 400"""
request, channel = self.make_request(
"PUT",
"/profile/%s/displayname" % (self.owner, ),
content=json.dumps({"displayname": "test" * 100}),
access_token=self.owner_tok,
)
self.render(request)
self.assertEqual(channel.code, 400, channel.result)

res = self.get_displayname()
self.assertEqual(res, "owner")

def get_displayname(self):
request, channel = self.make_request(
"GET",
"/profile/%s/displayname" % (self.owner, ),
)
self.render(request)
self.assertEqual(channel.code, 200, channel.result)
return channel.json_body["displayname"]


class ProfilesRestrictedTestCase(unittest.HomeserverTestCase):

servlets = [
Expand Down