From af36536336842c8a2d2042c1c73a3f1fcc2adaf8 Mon Sep 17 00:00:00 2001 From: claude Date: Fri, 24 Jul 2026 08:36:28 +0000 Subject: [PATCH] Fix oauth2 list client search crashing 'oauth2 list --search-client-name' crashed with an AttributeError (objects.file instead of objects.filter) and both search branches used the invalid '__ilike' lookup, which raises FieldError for --search-client-id. Use filter() with '__icontains' (the Django equivalent of SQL ILIKE substring matching) and report a not-found search on stderr instead of relying on the dead DoesNotExist handler (filter() never raises it). Adds regression tests for oauth2 list and both search options. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01AgWqnQ8ExYjdZofXbvJZEz --- .../mailauth/management/commands/oauth2.py | 12 +++--- .../tests/test_management_commands.py | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/authserver/mailauth/management/commands/oauth2.py b/authserver/mailauth/management/commands/oauth2.py index 9672f372..c33ce605 100644 --- a/authserver/mailauth/management/commands/oauth2.py +++ b/authserver/mailauth/management/commands/oauth2.py @@ -121,16 +121,16 @@ def _create(self, **kwargs: Any) -> None: def _list(self, **kwargs: Any) -> None: clients = [] # type: List[oauth2_models.Application] if kwargs["search_client_id"]: - try: - clients = list(appmodel.objects.filter(client_id__ilike=kwargs["search_client_id"])) - except appmodel.DoesNotExist: + clients = list(appmodel.objects.filter(client_id__icontains=kwargs["search_client_id"])) + if not clients: self.stderr.write(self.style.ERROR("Client ID not found %s" % kwargs["search_client_id"])) + return elif kwargs["search_client_name"]: - try: - clients = list(appmodel.objects.file(name__ilike=kwargs["search_client_name"])) - except appmodel.DoesNotExist: + clients = list(appmodel.objects.filter(name__icontains=kwargs["search_client_name"])) + if not clients: self.stderr.write(self.style.ERROR("Client name not found %s" % kwargs["search_client_name"])) + return else: clients = list(appmodel.objects.all()) diff --git a/authserver/mailauth/tests/test_management_commands.py b/authserver/mailauth/tests/test_management_commands.py index bb69d313..d2e672c9 100644 --- a/authserver/mailauth/tests/test_management_commands.py +++ b/authserver/mailauth/tests/test_management_commands.py @@ -181,3 +181,40 @@ def test_list_can_filter_by_name_in_json_output(self) -> None: payload = json.loads(out.getvalue()) self.assertEqual(1, len(payload)) self.assertEqual(self.permission.permission_name, payload[0]["permission_name"]) + + +class OAuth2CommandTests(TestCase): + def setUp(self) -> None: + self.app = models.MNApplication.objects.create( + name="testclient", + client_type=models.MNApplication.CLIENT_CONFIDENTIAL, + authorization_grant_type=models.MNApplication.GRANT_AUTHORIZATION_CODE, + redirect_uris="https://client.example.com/callback", + ) + + def test_list_all(self) -> None: + out = StringIO() + with redirect_stdout(out): + call_command("oauth2", "list") + self.assertIn("testclient", out.getvalue()) + self.assertIn(self.app.client_id, out.getvalue()) + + def test_list_search_by_client_name(self) -> None: + out = StringIO() + with redirect_stdout(out): + call_command("oauth2", "list", "--search-client-name", "testclient") + self.assertIn(self.app.client_id, out.getvalue()) + + def test_list_search_by_client_id(self) -> None: + out = StringIO() + with redirect_stdout(out): + call_command("oauth2", "list", "--search-client-id", self.app.client_id) + self.assertIn("testclient", out.getvalue()) + + def test_list_search_by_client_name_not_found(self) -> None: + out = StringIO() + err = StringIO() + with redirect_stdout(out), redirect_stderr(err): + call_command("oauth2", "list", "--search-client-name", "does-not-exist") + self.assertNotIn(self.app.client_id, out.getvalue()) + self.assertIn("Client name not found", err.getvalue())