From 7f9bed3d82a6fdc948e9851c3d2c94005d228b3a Mon Sep 17 00:00:00 2001 From: Vchen7629 Date: Sun, 14 Jun 2026 20:31:49 -0700 Subject: [PATCH 1/3] fix: updated list_keys to only return non revoked api keys --- src/services/api_key_service.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/services/api_key_service.py b/src/services/api_key_service.py index 92879cb58..8bafed106 100644 --- a/src/services/api_key_service.py +++ b/src/services/api_key_service.py @@ -237,7 +237,7 @@ async def list_keys( jwt_token: str = None, ) -> dict[str, Any]: """ - List all API keys for a user (without the actual keys). + List all active (non-revoked) API keys for a user (without the actual keys). Args: user_id: The user's ID @@ -251,7 +251,14 @@ async def list_keys( # Search for user's keys search_body = { - "query": {"term": {"user_id": user_id}}, + "query": { + "bool": { + "must": [ + {"term": {"user_id": user_id}}, + {"term": {"revoked": False }}, + ] + } + }, "sort": [{"created_at": {"order": "desc"}}], "_source": [ "key_id", From 6a800de5798b9e1a49aa029d9518de74737449ed Mon Sep 17 00:00:00 2001 From: Vchen7629 Date: Sun, 14 Jun 2026 20:32:14 -0700 Subject: [PATCH 2/3] test: created unit test to verify that query and return value is correct --- tests/unit/test_api_key_service.py | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/unit/test_api_key_service.py b/tests/unit/test_api_key_service.py index f1de9f058..644daf7d5 100644 --- a/tests/unit/test_api_key_service.py +++ b/tests/unit/test_api_key_service.py @@ -92,3 +92,46 @@ async def test_validate_key_accepts_and_migrates_legacy_hash(monkeypatch): update_doc = opensearch_client.update.await_args.kwargs["body"]["doc"] assert update_doc["key_hash"] == keyed_hash assert "last_used_at" in update_doc + +@pytest.mark.asyncio +async def test_list_keys_returns_only_non_revoked_api_keys(monkeypatch) -> None: + from services.api_key_service import APIKeyService + + service = APIKeyService() + + opensearch_client = AsyncMock() + opensearch_client.search.return_value = { + "hits": { + "hits": [ + { + "_source": { + "key_id": "key-1", + "key_prefix": "orag_aaaaaaaa", + "name": "active key", + "created_at": "2026-06-15T10:03:58.016280", + "last_used_at": None, + "revoked": False, + } + }, + ] + } + } + monkeypatch.setattr("config.settings.clients.opensearch", opensearch_client) + + result = await service.list_keys(user_id="user-1") + + assert result["success"] is True + assert result["keys"] == [ + { + "key_id": "key-1", + "key_prefix": "orag_aaaaaaaa", + "name": "active key", + "created_at": "2026-06-15T10:03:58.016280", + "last_used_at": None, + "revoked": False, + } + ] + + query_must = opensearch_client.search.await_args.kwargs["body"]["query"]["bool"]["must"] + assert {"term": {"user_id": "user-1"}} in query_must + assert {"term": {"revoked": False}} in query_must \ No newline at end of file From 27dc424d4fba1520719fe89d9795f13122551616 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 18 Jun 2026 20:19:27 +0000 Subject: [PATCH 3/3] style: ruff autofix (auto) --- src/services/api_key_service.py | 2 +- tests/unit/test_api_key_service.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/services/api_key_service.py b/src/services/api_key_service.py index 8bafed106..561931381 100644 --- a/src/services/api_key_service.py +++ b/src/services/api_key_service.py @@ -255,7 +255,7 @@ async def list_keys( "bool": { "must": [ {"term": {"user_id": user_id}}, - {"term": {"revoked": False }}, + {"term": {"revoked": False}}, ] } }, diff --git a/tests/unit/test_api_key_service.py b/tests/unit/test_api_key_service.py index 644daf7d5..ace11d0c5 100644 --- a/tests/unit/test_api_key_service.py +++ b/tests/unit/test_api_key_service.py @@ -93,6 +93,7 @@ async def test_validate_key_accepts_and_migrates_legacy_hash(monkeypatch): assert update_doc["key_hash"] == keyed_hash assert "last_used_at" in update_doc + @pytest.mark.asyncio async def test_list_keys_returns_only_non_revoked_api_keys(monkeypatch) -> None: from services.api_key_service import APIKeyService @@ -132,6 +133,6 @@ async def test_list_keys_returns_only_non_revoked_api_keys(monkeypatch) -> None: } ] - query_must = opensearch_client.search.await_args.kwargs["body"]["query"]["bool"]["must"] - assert {"term": {"user_id": "user-1"}} in query_must - assert {"term": {"revoked": False}} in query_must \ No newline at end of file + query_must = opensearch_client.search.await_args.kwargs["body"]["query"]["bool"]["must"] + assert {"term": {"user_id": "user-1"}} in query_must + assert {"term": {"revoked": False}} in query_must