Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Add options to prevent users from changing their profile. #7096

Merged
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/7096.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add options to prevent users from changing their profile or associated 3PIDs.
23 changes: 23 additions & 0 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,29 @@ account_threepid_delegates:
#email: https://example.com # Delegate email sending to example.com
#msisdn: http://localhost:8090 # Delegate SMS sending to this local process

# Whether users are allowed to change their displayname after it has
# been initially set. Useful when provisioning users based on the
# contents of a third-party directory.
#
# Does not apply to server administrators. Defaults to 'true'
#
#enable_set_displayname: false

# Whether users are allowed to change their avatar after it has been
# initially set. Useful when provisioning users based on the contents
# of a third-party directory.
#
# Does not apply to server administrators. Defaults to 'true'
#
#enable_set_avatar_url: false

# Whether users can change the 3PIDs associated with their accounts
# (email address and msisdn).
#
# Defaults to 'true'
#
#enable_3pid_changes: false

# Users who register on this homeserver will automatically be joined
# to these rooms
#
Expand Down
27 changes: 27 additions & 0 deletions synapse/config/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ def read_config(self, config, **kwargs):
raise ConfigError("Invalid auto_join_rooms entry %s" % (room_alias,))
self.autocreate_auto_join_rooms = config.get("autocreate_auto_join_rooms", True)

self.enable_set_displayname = config.get("enable_set_displayname", True)
self.enable_set_avatar_url = config.get("enable_set_avatar_url", True)
self.enable_3pid_changes = config.get("enable_3pid_changes", True)

self.disable_msisdn_registration = config.get(
"disable_msisdn_registration", False
)
Expand Down Expand Up @@ -330,6 +334,29 @@ def generate_config_section(self, generate_secrets=False, **kwargs):
#email: https://example.com # Delegate email sending to example.com
#msisdn: http://localhost:8090 # Delegate SMS sending to this local process

# Whether users are allowed to change their displayname after it has
# been initially set. Useful when provisioning users based on the
# contents of a third-party directory.
#
# Does not apply to server administrators. Defaults to 'true'
#
#enable_set_displayname: false

# Whether users are allowed to change their avatar after it has been
# initially set. Useful when provisioning users based on the contents
# of a third-party directory.
#
# Does not apply to server administrators. Defaults to 'true'
#
#enable_set_avatar_url: false
dklimpel marked this conversation as resolved.
Show resolved Hide resolved

# Whether users can change the 3PIDs associated with their accounts
# (email address and msisdn).
#
# Defaults to 'true'
#
#enable_3pid_changes: false

# Users who register on this homeserver will automatically be joined
# to these rooms
#
Expand Down
16 changes: 16 additions & 0 deletions synapse/handlers/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ 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 not by_admin and not self.hs.config.enable_set_displayname:
profile = yield self.store.get_profileinfo(target_user.localpart)
if profile.display_name:
raise SynapseError(
400,
"Changing display name is disabled on this server",
Codes.FORBIDDEN,
)

if len(new_displayname) > MAX_DISPLAYNAME_LEN:
raise SynapseError(
400, "Displayname is too long (max %i)" % (MAX_DISPLAYNAME_LEN,)
Expand Down Expand Up @@ -218,6 +227,13 @@ 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 not by_admin and not self.hs.config.enable_set_avatar_url:
profile = yield self.store.get_profileinfo(target_user.localpart)
if profile.avatar_url:
raise SynapseError(
400, "Changing avatar is disabled on this server", Codes.FORBIDDEN
)

if len(new_avatar_url) > MAX_AVATAR_URL_LEN:
raise SynapseError(
400, "Avatar URL is too long (max %i)" % (MAX_AVATAR_URL_LEN,)
Expand Down
16 changes: 16 additions & 0 deletions synapse/rest/client/v2_alpha/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,11 @@ async def on_GET(self, request):
return 200, {"threepids": threepids}

async def on_POST(self, request):
if not self.hs.config.enable_3pid_changes:
raise SynapseError(
400, "3PID changes are disabled on this server", Codes.FORBIDDEN
)

requester = await self.auth.get_user_by_req(request)
user_id = requester.user.to_string()
body = parse_json_object_from_request(request)
Expand Down Expand Up @@ -646,6 +651,11 @@ def __init__(self, hs):

@interactive_auth_handler
async def on_POST(self, request):
if not self.hs.config.enable_3pid_changes:
raise SynapseError(
400, "3PID changes are disabled on this server", Codes.FORBIDDEN
)

requester = await self.auth.get_user_by_req(request)
user_id = requester.user.to_string()
body = parse_json_object_from_request(request)
Expand Down Expand Up @@ -741,10 +751,16 @@ class ThreepidDeleteRestServlet(RestServlet):

def __init__(self, hs):
super(ThreepidDeleteRestServlet, self).__init__()
self.hs = hs
self.auth = hs.get_auth()
self.auth_handler = hs.get_auth_handler()

async def on_POST(self, request):
if not self.hs.config.enable_3pid_changes:
raise SynapseError(
400, "3PID changes are disabled on this server", Codes.FORBIDDEN
)

body = parse_json_object_from_request(request)
assert_params_in_dict(body, ["medium", "address"])

Expand Down
65 changes: 64 additions & 1 deletion tests/handlers/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from twisted.internet import defer

import synapse.types
from synapse.api.errors import AuthError
from synapse.api.errors import AuthError, SynapseError
from synapse.handlers.profile import MasterProfileHandler
from synapse.types import UserID

Expand Down Expand Up @@ -70,6 +70,7 @@ def register_query_handler(query_type, handler):
yield self.store.create_profile(self.frank.localpart)

self.handler = hs.get_profile_handler()
self.hs = hs

@defer.inlineCallbacks
def test_get_my_name(self):
Expand All @@ -90,6 +91,33 @@ def test_set_my_name(self):
"Frank Jr.",
)

# Set displayname again
yield self.handler.set_displayname(
self.frank, synapse.types.create_requester(self.frank), "Frank"
)

self.assertEquals(
(yield self.store.get_profile_displayname(self.frank.localpart)), "Frank",
)

@defer.inlineCallbacks
def test_set_my_name_if_disabled(self):
self.hs.config.enable_set_displayname = False

# Setting displayname for the first time is allowed
yield self.store.set_profile_displayname(self.frank.localpart, "Frank")

self.assertEquals(
(yield self.store.get_profile_displayname(self.frank.localpart)), "Frank",
)

# Setting displayname a second time is forbidden
d = self.handler.set_displayname(
self.frank, synapse.types.create_requester(self.frank), "Frank Jr."
)

yield self.assertFailure(d, SynapseError)

@defer.inlineCallbacks
def test_set_my_name_noauth(self):
d = self.handler.set_displayname(
Expand Down Expand Up @@ -147,3 +175,38 @@ def test_set_my_avatar(self):
(yield self.store.get_profile_avatar_url(self.frank.localpart)),
"http://my.server/pic.gif",
)

# Set avatar again
yield self.handler.set_avatar_url(
self.frank,
synapse.types.create_requester(self.frank),
"http://my.server/me.png",
)

self.assertEquals(
(yield self.store.get_profile_avatar_url(self.frank.localpart)),
"http://my.server/me.png",
)

@defer.inlineCallbacks
def test_set_my_avatar_if_disabled(self):
self.hs.config.enable_set_avatar_url = False

# Setting displayname for the first time is allowed
yield self.store.set_profile_avatar_url(
anoadragon453 marked this conversation as resolved.
Show resolved Hide resolved
self.frank.localpart, "http://my.server/me.png"
)

self.assertEquals(
(yield self.store.get_profile_avatar_url(self.frank.localpart)),
"http://my.server/me.png",
)

# Set avatar a second time is forbidden
d = self.handler.set_avatar_url(
self.frank,
synapse.types.create_requester(self.frank),
"http://my.server/pic.gif",
)

yield self.assertFailure(d, SynapseError)
Loading