forked from matrix-org/synapse
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow new users to be registered via the admin API even if the monthl…
…y active user limit has been reached (matrix-org#7263)
- v1.27.0rc1
- v1.26.0
- v1.26.0rc2
- v1.26.0rc1
- v1.26.0-deb
- v1.25.0
- v1.25.0rc1
- v1.24.0
- v1.24.0rc2
- v1.24.0rc1
- v1.23.1
- v1.23.0
- v1.23.0rc1
- v1.22.1
- v1.22.0
- v1.22.0rc2
- v1.22.0rc1
- v1.21.2
- v1.21.1
- v1.21.0
- v1.21.0rc3
- v1.21.0rc2
- v1.21.0rc1
- v1.20.1
- v1.20.0
- v1.20.0rc5
- v1.20.0rc4
- v1.20.0rc3
- v1.20.0rc2
- v1.20.0rc1
- v1.19.3
- v1.19.2
- v1.19.1
- v1.19.1rc1
- v1.19.0
- v1.19.0rc1
- v1.18.0
- v1.18.0rc2
- v1.18.0rc1
- v1.17.0
- v1.17.0rc1
- v1.17.0-mod1-modular-vdhtest2
- v1.16.1
- v1.16.0
- v1.16.0rc2
- v1.16.0rc1
- v1.15.2
- v1.15.1
- v1.15.0
- v1.15.0rc1
Showing
4 changed files
with
172 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Allow new users to be registered via the admin API even if the monthly active user limit has been reached. Contributed by @dkimpel. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,9 +22,12 @@ | |
|
||
import synapse.rest.admin | ||
from synapse.api.constants import UserTypes | ||
from synapse.api.errors import HttpResponseException, ResourceLimitError | ||
from synapse.rest.client.v1 import login | ||
from synapse.rest.client.v2_alpha import sync | ||
|
||
from tests import unittest | ||
from tests.unittest import override_config | ||
|
||
|
||
class UserRegisterTestCase(unittest.HomeserverTestCase): | ||
|
@@ -320,6 +323,52 @@ def nonce(): | |
self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"]) | ||
self.assertEqual("Invalid user type", channel.json_body["error"]) | ||
|
||
@override_config( | ||
{"limit_usage_by_mau": True, "max_mau_value": 2, "mau_trial_days": 0} | ||
) | ||
def test_register_mau_limit_reached(self): | ||
""" | ||
Check we can register a user via the shared secret registration API | ||
even if the MAU limit is reached. | ||
""" | ||
handler = self.hs.get_registration_handler() | ||
store = self.hs.get_datastore() | ||
|
||
# Set monthly active users to the limit | ||
store.get_monthly_active_count = Mock(return_value=self.hs.config.max_mau_value) | ||
# Check that the blocking of monthly active users is working as expected | ||
# The registration of a new user fails due to the limit | ||
self.get_failure( | ||
handler.register_user(localpart="local_part"), ResourceLimitError | ||
) | ||
|
||
# Register new user with admin API | ||
request, channel = self.make_request("GET", self.url) | ||
self.render(request) | ||
nonce = channel.json_body["nonce"] | ||
|
||
want_mac = hmac.new(key=b"shared", digestmod=hashlib.sha1) | ||
want_mac.update( | ||
nonce.encode("ascii") + b"\x00bob\x00abc123\x00admin\x00support" | ||
) | ||
want_mac = want_mac.hexdigest() | ||
|
||
body = json.dumps( | ||
{ | ||
"nonce": nonce, | ||
"username": "bob", | ||
"password": "abc123", | ||
"admin": True, | ||
"user_type": UserTypes.SUPPORT, | ||
"mac": want_mac, | ||
} | ||
) | ||
request, channel = self.make_request("POST", self.url, body.encode("utf8")) | ||
self.render(request) | ||
|
||
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"]) | ||
self.assertEqual("@bob:test", channel.json_body["user_id"]) | ||
|
||
|
||
class UsersListTestCase(unittest.HomeserverTestCase): | ||
|
||
|
@@ -368,6 +417,7 @@ class UserRestTestCase(unittest.HomeserverTestCase): | |
servlets = [ | ||
synapse.rest.admin.register_servlets, | ||
login.register_servlets, | ||
sync.register_servlets, | ||
] | ||
|
||
def prepare(self, reactor, clock, hs): | ||
|
@@ -386,7 +436,6 @@ def test_requester_is_no_admin(self): | |
""" | ||
If the user is not a server admin, an error is returned. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
url = "/_synapse/admin/v2/users/@bob:test" | ||
|
||
request, channel = self.make_request( | ||
|
@@ -409,7 +458,6 @@ def test_user_does_not_exist(self): | |
""" | ||
Tests that a lookup for a user that does not exist returns a 404 | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
|
||
request, channel = self.make_request( | ||
"GET", | ||
|
@@ -425,7 +473,6 @@ def test_create_server_admin(self): | |
""" | ||
Check that a new admin user is created successfully. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
url = "/_synapse/admin/v2/users/@bob:test" | ||
|
||
# Create user (server admin) | ||
|
@@ -473,7 +520,6 @@ def test_create_user(self): | |
""" | ||
Check that a new regular user is created successfully. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
url = "/_synapse/admin/v2/users/@bob:test" | ||
|
||
# Create user | ||
|
@@ -516,14 +562,114 @@ def test_create_user(self): | |
self.assertEqual(False, channel.json_body["is_guest"]) | ||
self.assertEqual(False, channel.json_body["deactivated"]) | ||
|
||
@override_config( | ||
{"limit_usage_by_mau": True, "max_mau_value": 2, "mau_trial_days": 0} | ||
) | ||
def test_create_user_mau_limit_reached_active_admin(self): | ||
""" | ||
Check that an admin can register a new user via the admin API | ||
even if the MAU limit is reached. | ||
Admin user was active before creating user. | ||
""" | ||
|
||
handler = self.hs.get_registration_handler() | ||
|
||
# Sync to set admin user to active | ||
# before limit of monthly active users is reached | ||
request, channel = self.make_request( | ||
"GET", "/sync", access_token=self.admin_user_tok | ||
) | ||
self.render(request) | ||
|
||
if channel.code != 200: | ||
raise HttpResponseException( | ||
channel.code, channel.result["reason"], channel.result["body"] | ||
) | ||
|
||
# Set monthly active users to the limit | ||
self.store.get_monthly_active_count = Mock( | ||
return_value=self.hs.config.max_mau_value | ||
) | ||
# Check that the blocking of monthly active users is working as expected | ||
# The registration of a new user fails due to the limit | ||
self.get_failure( | ||
handler.register_user(localpart="local_part"), ResourceLimitError | ||
) | ||
|
||
# Register new user with admin API | ||
url = "/_synapse/admin/v2/users/@bob:test" | ||
|
||
# Create user | ||
body = json.dumps({"password": "abc123", "admin": False}) | ||
|
||
request, channel = self.make_request( | ||
"PUT", | ||
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(False, channel.json_body["admin"]) | ||
|
||
@override_config( | ||
{"limit_usage_by_mau": True, "max_mau_value": 2, "mau_trial_days": 0} | ||
) | ||
def test_create_user_mau_limit_reached_passive_admin(self): | ||
""" | ||
Check that an admin can register a new user via the admin API | ||
even if the MAU limit is reached. | ||
Admin user was not active before creating user. | ||
""" | ||
|
||
handler = self.hs.get_registration_handler() | ||
|
||
# Set monthly active users to the limit | ||
self.store.get_monthly_active_count = Mock( | ||
return_value=self.hs.config.max_mau_value | ||
) | ||
# Check that the blocking of monthly active users is working as expected | ||
# The registration of a new user fails due to the limit | ||
self.get_failure( | ||
handler.register_user(localpart="local_part"), ResourceLimitError | ||
) | ||
|
||
# Register new user with admin API | ||
url = "/_synapse/admin/v2/users/@bob:test" | ||
|
||
# Create user | ||
body = json.dumps({"password": "abc123", "admin": False}) | ||
|
||
request, channel = self.make_request( | ||
"PUT", | ||
url, | ||
access_token=self.admin_user_tok, | ||
content=body.encode(encoding="utf_8"), | ||
) | ||
self.render(request) | ||
|
||
# Admin user is not blocked by mau anymore | ||
self.assertEqual(201, int(channel.result["code"]), msg=channel.result["body"]) | ||
self.assertEqual("@bob:test", channel.json_body["name"]) | ||
self.assertEqual(False, channel.json_body["admin"]) | ||
|
||
@override_config( | ||
{ | ||
"email": { | ||
"enable_notifs": True, | ||
"notif_for_new_users": True, | ||
"notif_from": "[email protected]", | ||
}, | ||
"public_baseurl": "https://example.com", | ||
} | ||
) | ||
def test_create_user_email_notif_for_new_users(self): | ||
""" | ||
Check that a new regular user is created successfully and | ||
got an email pusher. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
self.hs.config.email_enable_notifs = True | ||
self.hs.config.email_notif_for_new_users = True | ||
url = "/_synapse/admin/v2/users/@bob:test" | ||
|
||
# Create user | ||
|
@@ -554,14 +700,21 @@ def test_create_user_email_notif_for_new_users(self): | |
self.assertEqual(len(pushers), 1) | ||
self.assertEqual("@bob:test", pushers[0]["user_name"]) | ||
|
||
@override_config( | ||
{ | ||
"email": { | ||
"enable_notifs": False, | ||
"notif_for_new_users": False, | ||
"notif_from": "[email protected]", | ||
}, | ||
"public_baseurl": "https://example.com", | ||
} | ||
) | ||
def test_create_user_email_no_notif_for_new_users(self): | ||
""" | ||
Check that a new regular user is created successfully and | ||
got not an email pusher. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
self.hs.config.email_enable_notifs = False | ||
self.hs.config.email_notif_for_new_users = False | ||
url = "/_synapse/admin/v2/users/@bob:test" | ||
|
||
# Create user | ||
|
@@ -595,7 +748,6 @@ def test_set_password(self): | |
""" | ||
Test setting a new password for another user. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
|
||
# Change password | ||
body = json.dumps({"password": "hahaha"}) | ||
|
@@ -614,7 +766,6 @@ def test_set_displayname(self): | |
""" | ||
Test setting the displayname of another user. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
|
||
# Modify user | ||
body = json.dumps({"displayname": "foobar"}) | ||
|
@@ -645,7 +796,6 @@ def test_set_threepid(self): | |
""" | ||
Test setting threepid for an other user. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
|
||
# Delete old and add new threepid to user | ||
body = json.dumps( | ||
|
@@ -711,7 +861,6 @@ def test_set_user_as_admin(self): | |
""" | ||
Test setting the admin flag on a user. | ||
""" | ||
self.hs.config.registration_shared_secret = None | ||
|
||
# Set a user as an admin | ||
body = json.dumps({"admin": True}) | ||
|
@@ -743,7 +892,6 @@ 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 | ||
url = "/_synapse/admin/v2/users/@bob:test" | ||
|
||
# Create user | ||
|