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

Add options to disable setting profile info for prevent changes. #7053

Merged
merged 12 commits into from
Mar 10, 2020
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/7053.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.
13 changes: 13 additions & 0 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,19 @@ account_threepid_delegates:
#email: https://example.com # Delegate email sending to example.com
#msisdn: http://localhost:8090 # Delegate SMS sending to this local process

# If disabled, don't let users set their own display names/avatars
# (unless they are a server admin) other than for the very first time.
# Useful when provisioning users based on the contents of a 3rd party
# directory and to avoid ambiguities.
#
#enable_set_displayname: true
#enable_set_avatar_url: true

# If false, stop users from trying to change the 3PIDs associated with
# their accounts.
#
#enable_3pid_changes: true

# Users who register on this homeserver will automatically be joined
# to these rooms
#
Expand Down
17 changes: 17 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,19 @@ 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

# If disabled, don't let users set their own display names/avatars
# (unless they are a server admin) other than for the very first time.
# Useful when provisioning users based on the contents of a 3rd party
# directory and to avoid ambiguities.
#
#enable_set_displayname: true
#enable_set_avatar_url: true

# If false, stop users from trying to change the 3PIDs associated with
# their accounts.
#
#enable_3pid_changes: true

# 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 @@ -599,6 +599,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 @@ -643,6 +648,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 @@ -738,10 +748,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
33 changes: 32 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,19 @@ def test_set_my_name(self):
"Frank Jr.",
)

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

# Set first displayname is allowed, if displayname is null
yield self.store.set_profile_displayname(self.frank.localpart, "Frank")

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 +161,20 @@ def test_set_my_avatar(self):
(yield self.store.get_profile_avatar_url(self.frank.localpart)),
"http://my.server/pic.gif",
)

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

# Set first time avatar is allowed, if avatar is null
yield self.store.set_profile_avatar_url(
self.frank.localpart, "http://my.server/me.png"
)

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