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

Ensure 'deactivated' parameter is a boolean on user admin API, Fix error handling of call to deactivate user #6990

Merged
merged 5 commits into from
Feb 26, 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/6990.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent user from setting 'deactivated' to anything other than a bool on the v2 PUT /users Admin API.
11 changes: 7 additions & 4 deletions synapse/rest/admin/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,16 @@ async def on_PUT(self, request, user_id):
)

if "deactivated" in body:
deactivate = bool(body["deactivated"])
deactivate = body["deactivated"]
if not isinstance(deactivate, bool):
raise SynapseError(
400, "'deactivated' parameter is not of type boolean"
)

if deactivate and not user["deactivated"]:
result = await self.deactivate_account_handler.deactivate_account(
await self.deactivate_account_handler.deactivate_account(
target_user.to_string(), False
)
if not result:
raise SynapseError(500, "Could not deactivate user")

user = await self.admin_handler.get_user(target_user)
return 200, user
Expand Down
1 change: 1 addition & 0 deletions synapse/rest/client/v1/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ def complete_sso_login(
redirect_url = self._add_login_token_to_redirect_url(
client_redirect_url, login_token
)
# Load page
request.redirect(redirect_url)
finish_request(request)

Expand Down
59 changes: 59 additions & 0 deletions tests/rest/admin/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,62 @@ def test_requester_is_admin(self):
self.assertEqual(1, channel.json_body["admin"])
self.assertEqual(0, channel.json_body["is_guest"])
self.assertEqual(1, channel.json_body["deactivated"])

def test_accidental_deactivation_prevention(self):
"""
Ensure an account can't accidentally be deactivated by using a str value
for the deactivated body parameter
"""
self.hs.config.registration_shared_secret = None

# Create user
body = json.dumps({"password": "abc123"})

request, channel = self.make_request(
"PUT",
self.url,
access_token=self.admin_user_tok,
content=body.encode(encoding="utf_8"),
)
self.render(request)

self.assertEqual(201, int(channel.result["code"]), msg=channel.result["body"])
self.assertEqual("@bob:test", channel.json_body["name"])
self.assertEqual("bob", channel.json_body["displayname"])

# Get user
request, channel = self.make_request(
"GET", self.url, access_token=self.admin_user_tok,
)
self.render(request)

self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
self.assertEqual("@bob:test", channel.json_body["name"])
self.assertEqual("bob", channel.json_body["displayname"])
self.assertEqual(0, channel.json_body["deactivated"])

# Change password (and use a str for deactivate instead of a bool)
body = json.dumps({"password": "abc123", "deactivated": "false"}) # oops!

request, channel = self.make_request(
"PUT",
self.url,
access_token=self.admin_user_tok,
content=body.encode(encoding="utf_8"),
)
self.render(request)

self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"])

# Check user is not deactivated
request, channel = self.make_request(
"GET", self.url, access_token=self.admin_user_tok,
)
self.render(request)

self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
self.assertEqual("@bob:test", channel.json_body["name"])
self.assertEqual("bob", channel.json_body["displayname"])

# Ensure they're still alive
self.assertEqual(0, channel.json_body["deactivated"])