Skip to content

Commit b4d4ff4

Browse files
committed
introduce ApiKey module alongside with types
1 parent 1ab4cb4 commit b4d4ff4

File tree

5 files changed

+129
-0
lines changed

5 files changed

+129
-0
lines changed

tests/test_api_keys.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import pytest
2+
3+
from tests.utils.fixtures.mock_api_key import MockApiKey
4+
from tests.utils.syncify import syncify
5+
from workos.api_key import ApiKey, AsyncApiKey
6+
from workos.exceptions import AuthenticationException
7+
8+
9+
@pytest.mark.sync_and_async(ApiKey, AsyncApiKey)
10+
class TestApiKey:
11+
@pytest.fixture
12+
def mock_api_key_details(self):
13+
api_key_details = MockApiKey()
14+
return api_key_details.model_dump()
15+
16+
def test_validate_api_key_with_valid_key(
17+
self,
18+
module_instance,
19+
mock_api_key_details,
20+
capture_and_mock_http_client_request,
21+
):
22+
request_kwargs = capture_and_mock_http_client_request(
23+
module_instance._http_client, mock_api_key_details, 200
24+
)
25+
26+
api_key_details = syncify(module_instance.validate_api_key())
27+
28+
assert request_kwargs["url"].endswith("/api_keys/validate")
29+
assert request_kwargs["method"] == "post"
30+
assert api_key_details.id == mock_api_key_details["id"]
31+
assert api_key_details.name == mock_api_key_details["name"]
32+
assert api_key_details.object == "api_key"
33+
34+
def test_validate_api_key_with_invalid_key(
35+
self,
36+
module_instance,
37+
mock_http_client_with_response,
38+
):
39+
mock_http_client_with_response(
40+
module_instance._http_client,
41+
{"message": "Invalid API key", "error": "invalid_api_key"},
42+
401,
43+
)
44+
45+
with pytest.raises(AuthenticationException):
46+
syncify(module_instance.validate_api_key())
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import datetime
2+
3+
from workos.types.api_keys import ApiKey
4+
5+
6+
class MockApiKey(ApiKey):
7+
def __init__(self, id="api_key_01234567890"):
8+
now = datetime.datetime.now().isoformat()
9+
super().__init__(
10+
object="api_key",
11+
id=id,
12+
name="Development API Key",
13+
last_used_at=now,
14+
created_at=now,
15+
updated_at=now,
16+
)

workos/api_key.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from typing import Protocol
2+
3+
from workos.types.api_keys import ApiKey
4+
from workos.typing.sync_or_async import SyncOrAsync
5+
from workos.utils.http_client import AsyncHTTPClient, SyncHTTPClient
6+
from workos.utils.request_helper import REQUEST_METHOD_POST
7+
8+
9+
class ApiKeyModule(Protocol):
10+
def validate_api_key(self) -> SyncOrAsync[ApiKey]:
11+
"""Validates the configured API key.
12+
13+
Returns:
14+
ApiKey: The validated API key details containing
15+
information about the key's name and usage
16+
17+
Raises:
18+
AuthenticationException: If the API key is invalid or
19+
unauthorized (401)
20+
NotFoundException: If the API key is not found (404)
21+
ServerException: If the API server encounters an error
22+
(5xx)
23+
"""
24+
...
25+
26+
27+
class ApiKey(ApiKeyModule):
28+
_http_client: SyncHTTPClient
29+
30+
def __init__(self, http_client: SyncHTTPClient):
31+
self._http_client = http_client
32+
33+
def validate_api_key(self) -> ApiKey:
34+
response = self._http_client.request(
35+
"api_keys/validate",
36+
method=REQUEST_METHOD_POST,
37+
)
38+
39+
return ApiKey.model_validate(response)
40+
41+
42+
class AsyncApiKey(ApiKeyModule):
43+
_http_client: AsyncHTTPClient
44+
45+
def __init__(self, http_client: AsyncHTTPClient):
46+
self._http_client = http_client
47+
48+
async def validate_api_key(self) -> ApiKey:
49+
response = await self._http_client.request(
50+
"api_keys/validate",
51+
method=REQUEST_METHOD_POST,
52+
)
53+
54+
return ApiKey.model_validate(response)

workos/types/api_key/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .api_key import ApiKey as ApiKey # noqa: F401

workos/types/api_key/api_key.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from typing import Literal
2+
3+
from workos.types.workos_model import WorkOSModel
4+
5+
6+
class ApiKey(WorkOSModel):
7+
object: Literal["api_key"]
8+
id: str
9+
name: str
10+
last_used_at: str | None = None
11+
created_at: str
12+
updated_at: str

0 commit comments

Comments
 (0)