mirror of
https://github.com/element-hq/synapse.git
synced 2024-11-26 11:36:03 +03:00
Add tests for List Users Admin API (#9045)
This commit is contained in:
parent
42a8e81370
commit
c55e62548c
3 changed files with 215 additions and 30 deletions
1
changelog.d/9045.misc
Normal file
1
changelog.d/9045.misc
Normal file
|
@ -0,0 +1 @@
|
|||
Add tests to `test_user.UsersListTestCase` for List Users Admin API.
|
|
@ -83,17 +83,32 @@ class UsersRestServletV2(RestServlet):
|
|||
The parameter `deactivated` can be used to include deactivated users.
|
||||
"""
|
||||
|
||||
def __init__(self, hs):
|
||||
def __init__(self, hs: "HomeServer"):
|
||||
self.hs = hs
|
||||
self.store = hs.get_datastore()
|
||||
self.auth = hs.get_auth()
|
||||
self.admin_handler = hs.get_admin_handler()
|
||||
|
||||
async def on_GET(self, request):
|
||||
async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
|
||||
await assert_requester_is_admin(self.auth, request)
|
||||
|
||||
start = parse_integer(request, "from", default=0)
|
||||
limit = parse_integer(request, "limit", default=100)
|
||||
|
||||
if start < 0:
|
||||
raise SynapseError(
|
||||
400,
|
||||
"Query parameter from must be a string representing a positive integer.",
|
||||
errcode=Codes.INVALID_PARAM,
|
||||
)
|
||||
|
||||
if limit < 0:
|
||||
raise SynapseError(
|
||||
400,
|
||||
"Query parameter limit must be a string representing a positive integer.",
|
||||
errcode=Codes.INVALID_PARAM,
|
||||
)
|
||||
|
||||
user_id = parse_string(request, "user_id", default=None)
|
||||
name = parse_string(request, "name", default=None)
|
||||
guests = parse_boolean(request, "guests", default=True)
|
||||
|
@ -103,7 +118,7 @@ class UsersRestServletV2(RestServlet):
|
|||
start, limit, user_id, name, guests, deactivated
|
||||
)
|
||||
ret = {"users": users, "total": total}
|
||||
if len(users) >= limit:
|
||||
if (start + limit) < total:
|
||||
ret["next_token"] = str(start + len(users))
|
||||
|
||||
return 200, ret
|
||||
|
|
|
@ -28,6 +28,7 @@ from synapse.api.errors import Codes, HttpResponseException, ResourceLimitError
|
|||
from synapse.api.room_versions import RoomVersions
|
||||
from synapse.rest.client.v1 import login, logout, profile, room
|
||||
from synapse.rest.client.v2_alpha import devices, sync
|
||||
from synapse.types import JsonDict
|
||||
|
||||
from tests import unittest
|
||||
from tests.test_utils import make_awaitable
|
||||
|
@ -468,13 +469,6 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
self.admin_user = self.register_user("admin", "pass", admin=True)
|
||||
self.admin_user_tok = self.login("admin", "pass")
|
||||
|
||||
self.user1 = self.register_user(
|
||||
"user1", "pass1", admin=False, displayname="Name 1"
|
||||
)
|
||||
self.user2 = self.register_user(
|
||||
"user2", "pass2", admin=False, displayname="Name 2"
|
||||
)
|
||||
|
||||
def test_no_auth(self):
|
||||
"""
|
||||
Try to list users without authentication.
|
||||
|
@ -488,6 +482,7 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
"""
|
||||
If the user is not a server admin, an error is returned.
|
||||
"""
|
||||
self._create_users(1)
|
||||
other_user_token = self.login("user1", "pass1")
|
||||
|
||||
channel = self.make_request("GET", self.url, access_token=other_user_token)
|
||||
|
@ -499,6 +494,8 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
"""
|
||||
List all users, including deactivated users.
|
||||
"""
|
||||
self._create_users(2)
|
||||
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
self.url + "?deactivated=true",
|
||||
|
@ -511,14 +508,7 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
self.assertEqual(3, channel.json_body["total"])
|
||||
|
||||
# Check that all fields are available
|
||||
for u in channel.json_body["users"]:
|
||||
self.assertIn("name", u)
|
||||
self.assertIn("is_guest", u)
|
||||
self.assertIn("admin", u)
|
||||
self.assertIn("user_type", u)
|
||||
self.assertIn("deactivated", u)
|
||||
self.assertIn("displayname", u)
|
||||
self.assertIn("avatar_url", u)
|
||||
self._check_fields(channel.json_body["users"])
|
||||
|
||||
def test_search_term(self):
|
||||
"""Test that searching for a users works correctly"""
|
||||
|
@ -549,6 +539,7 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
|
||||
# Check that users were returned
|
||||
self.assertTrue("users" in channel.json_body)
|
||||
self._check_fields(channel.json_body["users"])
|
||||
users = channel.json_body["users"]
|
||||
|
||||
# Check that the expected number of users were returned
|
||||
|
@ -561,25 +552,30 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
u = users[0]
|
||||
self.assertEqual(expected_user_id, u["name"])
|
||||
|
||||
self._create_users(2)
|
||||
|
||||
user1 = "@user1:test"
|
||||
user2 = "@user2:test"
|
||||
|
||||
# Perform search tests
|
||||
_search_test(self.user1, "er1")
|
||||
_search_test(self.user1, "me 1")
|
||||
_search_test(user1, "er1")
|
||||
_search_test(user1, "me 1")
|
||||
|
||||
_search_test(self.user2, "er2")
|
||||
_search_test(self.user2, "me 2")
|
||||
_search_test(user2, "er2")
|
||||
_search_test(user2, "me 2")
|
||||
|
||||
_search_test(self.user1, "er1", "user_id")
|
||||
_search_test(self.user2, "er2", "user_id")
|
||||
_search_test(user1, "er1", "user_id")
|
||||
_search_test(user2, "er2", "user_id")
|
||||
|
||||
# Test case insensitive
|
||||
_search_test(self.user1, "ER1")
|
||||
_search_test(self.user1, "NAME 1")
|
||||
_search_test(user1, "ER1")
|
||||
_search_test(user1, "NAME 1")
|
||||
|
||||
_search_test(self.user2, "ER2")
|
||||
_search_test(self.user2, "NAME 2")
|
||||
_search_test(user2, "ER2")
|
||||
_search_test(user2, "NAME 2")
|
||||
|
||||
_search_test(self.user1, "ER1", "user_id")
|
||||
_search_test(self.user2, "ER2", "user_id")
|
||||
_search_test(user1, "ER1", "user_id")
|
||||
_search_test(user2, "ER2", "user_id")
|
||||
|
||||
_search_test(None, "foo")
|
||||
_search_test(None, "bar")
|
||||
|
@ -587,6 +583,179 @@ class UsersListTestCase(unittest.HomeserverTestCase):
|
|||
_search_test(None, "foo", "user_id")
|
||||
_search_test(None, "bar", "user_id")
|
||||
|
||||
def test_invalid_parameter(self):
|
||||
"""
|
||||
If parameters are invalid, an error is returned.
|
||||
"""
|
||||
|
||||
# negative limit
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?limit=-5", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(Codes.INVALID_PARAM, channel.json_body["errcode"])
|
||||
|
||||
# negative from
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?from=-5", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(Codes.INVALID_PARAM, channel.json_body["errcode"])
|
||||
|
||||
# invalid guests
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?guests=not_bool", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(Codes.UNKNOWN, channel.json_body["errcode"])
|
||||
|
||||
# invalid deactivated
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?deactivated=not_bool", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(Codes.UNKNOWN, channel.json_body["errcode"])
|
||||
|
||||
def test_limit(self):
|
||||
"""
|
||||
Testing list of users with limit
|
||||
"""
|
||||
|
||||
number_users = 20
|
||||
# Create one less user (since there's already an admin user).
|
||||
self._create_users(number_users - 1)
|
||||
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?limit=5", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(channel.json_body["total"], number_users)
|
||||
self.assertEqual(len(channel.json_body["users"]), 5)
|
||||
self.assertEqual(channel.json_body["next_token"], "5")
|
||||
self._check_fields(channel.json_body["users"])
|
||||
|
||||
def test_from(self):
|
||||
"""
|
||||
Testing list of users with a defined starting point (from)
|
||||
"""
|
||||
|
||||
number_users = 20
|
||||
# Create one less user (since there's already an admin user).
|
||||
self._create_users(number_users - 1)
|
||||
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?from=5", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(channel.json_body["total"], number_users)
|
||||
self.assertEqual(len(channel.json_body["users"]), 15)
|
||||
self.assertNotIn("next_token", channel.json_body)
|
||||
self._check_fields(channel.json_body["users"])
|
||||
|
||||
def test_limit_and_from(self):
|
||||
"""
|
||||
Testing list of users with a defined starting point and limit
|
||||
"""
|
||||
|
||||
number_users = 20
|
||||
# Create one less user (since there's already an admin user).
|
||||
self._create_users(number_users - 1)
|
||||
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?from=5&limit=10", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(channel.json_body["total"], number_users)
|
||||
self.assertEqual(channel.json_body["next_token"], "15")
|
||||
self.assertEqual(len(channel.json_body["users"]), 10)
|
||||
self._check_fields(channel.json_body["users"])
|
||||
|
||||
def test_next_token(self):
|
||||
"""
|
||||
Testing that `next_token` appears at the right place
|
||||
"""
|
||||
|
||||
number_users = 20
|
||||
# Create one less user (since there's already an admin user).
|
||||
self._create_users(number_users - 1)
|
||||
|
||||
# `next_token` does not appear
|
||||
# Number of results is the number of entries
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?limit=20", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(channel.json_body["total"], number_users)
|
||||
self.assertEqual(len(channel.json_body["users"]), number_users)
|
||||
self.assertNotIn("next_token", channel.json_body)
|
||||
|
||||
# `next_token` does not appear
|
||||
# Number of max results is larger than the number of entries
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?limit=21", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(channel.json_body["total"], number_users)
|
||||
self.assertEqual(len(channel.json_body["users"]), number_users)
|
||||
self.assertNotIn("next_token", channel.json_body)
|
||||
|
||||
# `next_token` does appear
|
||||
# Number of max results is smaller than the number of entries
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?limit=19", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(channel.json_body["total"], number_users)
|
||||
self.assertEqual(len(channel.json_body["users"]), 19)
|
||||
self.assertEqual(channel.json_body["next_token"], "19")
|
||||
|
||||
# Check
|
||||
# Set `from` to value of `next_token` for request remaining entries
|
||||
# `next_token` does not appear
|
||||
channel = self.make_request(
|
||||
"GET", self.url + "?from=19", access_token=self.admin_user_tok,
|
||||
)
|
||||
|
||||
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
|
||||
self.assertEqual(channel.json_body["total"], number_users)
|
||||
self.assertEqual(len(channel.json_body["users"]), 1)
|
||||
self.assertNotIn("next_token", channel.json_body)
|
||||
|
||||
def _check_fields(self, content: JsonDict):
|
||||
"""Checks that the expected user attributes are present in content
|
||||
Args:
|
||||
content: List that is checked for content
|
||||
"""
|
||||
for u in content:
|
||||
self.assertIn("name", u)
|
||||
self.assertIn("is_guest", u)
|
||||
self.assertIn("admin", u)
|
||||
self.assertIn("user_type", u)
|
||||
self.assertIn("deactivated", u)
|
||||
self.assertIn("displayname", u)
|
||||
self.assertIn("avatar_url", u)
|
||||
|
||||
def _create_users(self, number_users: int):
|
||||
"""
|
||||
Create a number of users
|
||||
Args:
|
||||
number_users: Number of users to be created
|
||||
"""
|
||||
for i in range(1, number_users + 1):
|
||||
self.register_user(
|
||||
"user%d" % i, "pass%d" % i, admin=False, displayname="Name %d" % i,
|
||||
)
|
||||
|
||||
|
||||
class DeactivateAccountTestCase(unittest.HomeserverTestCase):
|
||||
|
||||
|
|
Loading…
Reference in a new issue