mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-07-23 03:20:41 -04:00
Allow admins to require a manual approval process before new accounts can be used (using MSC3866) (#13556)
This commit is contained in:
parent
8625ad8099
commit
be76cd8200
21 changed files with 731 additions and 34 deletions
|
@ -25,10 +25,10 @@ from parameterized import parameterized, parameterized_class
|
|||
from twisted.test.proto_helpers import MemoryReactor
|
||||
|
||||
import synapse.rest.admin
|
||||
from synapse.api.constants import UserTypes
|
||||
from synapse.api.constants import ApprovalNoticeMedium, LoginType, UserTypes
|
||||
from synapse.api.errors import Codes, HttpResponseException, ResourceLimitError
|
||||
from synapse.api.room_versions import RoomVersions
|
||||
from synapse.rest.client import devices, login, logout, profile, room, sync
|
||||
from synapse.rest.client import devices, login, logout, profile, register, room, sync
|
||||
from synapse.rest.media.v1.filepath import MediaFilePaths
|
||||
from synapse.server import HomeServer
|
||||
from synapse.types import JsonDict, UserID
|
||||
|
@ -578,6 +578,16 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
_search_test(None, "foo", "user_id")
|
||||
_search_test(None, "bar", "user_id")
|
||||
|
||||
@override_config(
|
||||
{
|
||||
"experimental_features": {
|
||||
"msc3866": {
|
||||
"enabled": True,
|
||||
"require_approval_for_new_accounts": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
def test_invalid_parameter(self) -> None:
|
||||
"""
|
||||
If parameters are invalid, an error is returned.
|
||||
|
@ -623,6 +633,16 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
self.assertEqual(400, channel.code, msg=channel.json_body)
|
||||
self.assertEqual(Codes.INVALID_PARAM, channel.json_body["errcode"])
|
||||
|
||||
# invalid approved
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
self.url + "?approved=not_bool",
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(400, channel.code, msg=channel.json_body)
|
||||
self.assertEqual(Codes.INVALID_PARAM, channel.json_body["errcode"])
|
||||
|
||||
# unkown order_by
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
|
@ -841,6 +861,69 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
self._order_test([self.admin_user, user1, user2], "creation_ts", "f")
|
||||
self._order_test([user2, user1, self.admin_user], "creation_ts", "b")
|
||||
|
||||
@override_config(
|
||||
{
|
||||
"experimental_features": {
|
||||
"msc3866": {
|
||||
"enabled": True,
|
||||
"require_approval_for_new_accounts": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
def test_filter_out_approved(self) -> None:
|
||||
"""Tests that the endpoint can filter out approved users."""
|
||||
# Create our users.
|
||||
self._create_users(2)
|
||||
|
||||
# Get the list of users.
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
self.url,
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
self.assertEqual(200, channel.code, channel.result)
|
||||
|
||||
# Exclude the admin, because we don't want to accidentally un-approve the admin.
|
||||
non_admin_user_ids = [
|
||||
user["name"]
|
||||
for user in channel.json_body["users"]
|
||||
if user["name"] != self.admin_user
|
||||
]
|
||||
|
||||
self.assertEqual(2, len(non_admin_user_ids), non_admin_user_ids)
|
||||
|
||||
# Select a user and un-approve them. We do this rather than the other way around
|
||||
# because, since these users are created by an admin, we consider them already
|
||||
# approved.
|
||||
not_approved_user = non_admin_user_ids[0]
|
||||
|
||||
channel = self.make_request(
|
||||
"PUT",
|
||||
f"/_synapse/admin/v2/users/{not_approved_user}",
|
||||
{"approved": False},
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
self.assertEqual(200, channel.code, channel.result)
|
||||
|
||||
# Now get the list of users again, this time filtering out approved users.
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
self.url + "?approved=false",
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
self.assertEqual(200, channel.code, channel.result)
|
||||
|
||||
non_admin_user_ids = [
|
||||
user["name"]
|
||||
for user in channel.json_body["users"]
|
||||
if user["name"] != self.admin_user
|
||||
]
|
||||
|
||||
# We should only have our unapproved user now.
|
||||
self.assertEqual(1, len(non_admin_user_ids), non_admin_user_ids)
|
||||
self.assertEqual(not_approved_user, non_admin_user_ids[0])
|
||||
|
||||
def _order_test(
|
||||
self,
|
||||
expected_user_list: List[str],
|
||||
|
@ -1272,6 +1355,7 @@ class UserRestTestCase(unittest.HomeserverTestCase):
|
|||
synapse.rest.admin.register_servlets,
|
||||
login.register_servlets,
|
||||
sync.register_servlets,
|
||||
register.register_servlets,
|
||||
]
|
||||
|
||||
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||
|
@ -2536,6 +2620,104 @@ class UserRestTestCase(unittest.HomeserverTestCase):
|
|||
# Ensure they're still alive
|
||||
self.assertEqual(0, channel.json_body["deactivated"])
|
||||
|
||||
@override_config(
|
||||
{
|
||||
"experimental_features": {
|
||||
"msc3866": {
|
||||
"enabled": True,
|
||||
"require_approval_for_new_accounts": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
def test_approve_account(self) -> None:
|
||||
"""Tests that approving an account correctly sets the approved flag for the user."""
|
||||
url = self.url_prefix % "@bob:test"
|
||||
|
||||
# Create the user using the client-server API since otherwise the user will be
|
||||
# marked as approved automatically.
|
||||
channel = self.make_request(
|
||||
"POST",
|
||||
"register",
|
||||
{
|
||||
"username": "bob",
|
||||
"password": "test",
|
||||
"auth": {"type": LoginType.DUMMY},
|
||||
},
|
||||
)
|
||||
self.assertEqual(403, channel.code, channel.result)
|
||||
self.assertEqual(Codes.USER_AWAITING_APPROVAL, channel.json_body["errcode"])
|
||||
self.assertEqual(
|
||||
ApprovalNoticeMedium.NONE, channel.json_body["approval_notice_medium"]
|
||||
)
|
||||
|
||||
# Get user
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
url,
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, channel.code, msg=channel.json_body)
|
||||
self.assertIs(False, channel.json_body["approved"])
|
||||
|
||||
# Approve user
|
||||
channel = self.make_request(
|
||||
"PUT",
|
||||
url,
|
||||
access_token=self.admin_user_tok,
|
||||
content={"approved": True},
|
||||
)
|
||||
|
||||
self.assertEqual(200, channel.code, msg=channel.json_body)
|
||||
self.assertIs(True, channel.json_body["approved"])
|
||||
|
||||
# Check that the user is now approved
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
url,
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, channel.code, msg=channel.json_body)
|
||||
self.assertIs(True, channel.json_body["approved"])
|
||||
|
||||
@override_config(
|
||||
{
|
||||
"experimental_features": {
|
||||
"msc3866": {
|
||||
"enabled": True,
|
||||
"require_approval_for_new_accounts": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
def test_register_approved(self) -> None:
|
||||
url = self.url_prefix % "@bob:test"
|
||||
|
||||
# Create user
|
||||
channel = self.make_request(
|
||||
"PUT",
|
||||
url,
|
||||
access_token=self.admin_user_tok,
|
||||
content={"password": "abc123", "approved": True},
|
||||
)
|
||||
|
||||
self.assertEqual(201, channel.code, msg=channel.json_body)
|
||||
self.assertEqual("@bob:test", channel.json_body["name"])
|
||||
self.assertEqual(1, channel.json_body["approved"])
|
||||
|
||||
# Get user
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
url,
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, channel.code, msg=channel.json_body)
|
||||
self.assertEqual("@bob:test", channel.json_body["name"])
|
||||
self.assertEqual(1, channel.json_body["approved"])
|
||||
|
||||
def _is_erased(self, user_id: str, expect: bool) -> None:
|
||||
"""Assert that the user is erased or not"""
|
||||
d = self.store.is_user_erased(user_id)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue