diff --git a/src/metabase/resources/user.py b/src/metabase/resources/user.py index 3c09ae2..339ac5b 100644 --- a/src/metabase/resources/user.py +++ b/src/metabase/resources/user.py @@ -38,17 +38,39 @@ class User(ListResource, CreateResource, GetResource, UpdateResource, DeleteReso updated_at: datetime @classmethod - def list(cls, using: Metabase) -> List[User]: + def list( + cls, + using: Metabase, + status: str = None, + query: str = None, + group_id: int = None, + include_deactivated: bool = None, + limit: int = None, + offset: int = None, + ) -> List[User]: """ Fetch a list of Users. By default returns every active user but only active users. - If status is deactivated, include deactivated users only. If status is all, include all users (active and inactive). Also supports include_deactivated, which if true, is equivalent to status=all. status and included_deactivated requires superuser permissions. + If status is deactivated, include deactivated users only. If status is all, include all users (active and + inactive). Also supports include_deactivated, which if true, is equivalent to status=all. status and + included_deactivated requires superuser permissions. For users with segmented permissions, return only themselves. - Takes limit, offset for pagination. Takes query for filtering on first name, last name, email. Also takes group_id, which filters on group id. + Takes limit, offset for pagination. Takes query for filtering on first name, last name, email. Also takes + group_id, which filters on group id. """ - response = using.get(cls.ENDPOINT) + response = using.get( + cls.ENDPOINT, + params={ + "status": status, + "query": query, + "group_id": group_id, + "include_deactivated": include_deactivated, + "limit": limit, + "offset": offset, + }, + ) records = [ cls(_using=using, **user) for user in response.json().get("data", []) ] diff --git a/tests/resources/test_user.py b/tests/resources/test_user.py index ea15d1c..21440ad 100644 --- a/tests/resources/test_user.py +++ b/tests/resources/test_user.py @@ -1,5 +1,6 @@ from random import randint +from metabase import PermissionGroup from metabase.exceptions import NotFoundError from metabase.resources.user import User from tests.helpers import IntegrationTestCase @@ -12,12 +13,61 @@ def tearDown(self) -> None: if user.id != 1: user.delete() + groups = PermissionGroup.list(using=self.metabase) + for group in groups: + if group.id > 2: + group.delete() + def test_import(self): """Ensure User can be imported from Metabase.""" from metabase import User self.assertIsNotNone(User(_using=None)) + def test_list(self): + """Ensure User.list() returns a list of Users, and supports filter parameters.""" + users = User.list(using=self.metabase) + self.assertIsInstance(users, list) + self.assertEqual(1, len(users)) + + user1 = User.create( + first_name="Test", + last_name="Test", + email=f"{randint(2, 10000)}@example.com", + password="example123", + using=self.metabase, + ) + group = PermissionGroup.create(using=self.metabase, name="foo") + user2 = User.create( + first_name="Test", + last_name="Test", + email=f"{randint(2, 10000)}@example.com", + password="example123", + group_ids=[1, group.id], + using=self.metabase, + ) + + users = User.list(using=self.metabase) + self.assertEqual(3, len(users)) + + users = User.list(using=self.metabase, query=user1.email) + self.assertEqual(1, len(users)) + self.assertEqual(users[0].id, user1.id) + + users = User.list(using=self.metabase, group_id=group.id) + self.assertEqual(1, len(users)) + self.assertEqual(users[0].id, user2.id) + + user1.delete() + users = User.list(using=self.metabase, include_deactivated=True) + self.assertTrue(user1.id in map(lambda u: u.id, users)) + + users = User.list(using=self.metabase, limit=1) + self.assertEqual(1, len(users)) + + users = User.list(using=self.metabase, limit=2) + self.assertEqual(2, len(users)) + def test_get(self): """ Ensure User.get() returns a User instance for a given ID, or