Skip to content

Commit

Permalink
✨ [#3328] Implement zgw_consumers.Service auth types in factory
Browse files Browse the repository at this point in the history
  • Loading branch information
sergei-maertens committed Sep 18, 2023
1 parent a331389 commit fcd47bd
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 1 deletion.
39 changes: 39 additions & 0 deletions src/zgw_consumers_ext/api_client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from dataclasses import dataclass
from typing import Any

from requests.auth import AuthBase
from requests.models import PreparedRequest
from zds_client import ClientAuth
from zgw_consumers.constants import AuthTypes
from zgw_consumers.models import Service


Expand Down Expand Up @@ -29,4 +33,39 @@ def get_client_session_kwargs(self) -> dict[str, Any]:
else client_cert_path
)

match self.service.auth_type:
case AuthTypes.api_key:
kwargs["auth"] = APIKeyAuth(
header=self.service.header_key, key=self.service.header_value
)
case AuthTypes.zgw:
kwargs["auth"] = ZGWAuth(service=self.service)

return kwargs


@dataclass
class APIKeyAuth(AuthBase):
header: str
key: str

def __call__(self, request: PreparedRequest):
request.headers[self.header] = self.key
return request


@dataclass
class ZGWAuth(AuthBase):
service: Service

def __post_init__(self):
self.auth = ClientAuth(
client_id=self.service.client_id,
secret=self.service.secret,
user_id=self.service.user_id,
user_representation=self.service.user_representation,
)

def __call__(self, request: PreparedRequest):
request.headers.update(self.auth.credentials())
return request
2 changes: 1 addition & 1 deletion src/zgw_consumers_ext/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def generate(self, extra_kwargs=None):

class ServiceFactory(factory.django.DjangoModelFactory):
label = factory.Sequence(lambda n: f"API-{n}")
api_root = UriPathFaker()
api_root = UriPathFaker() # FIXME: this should be a fully qualified URL

class Meta:
model = "zgw_consumers.Service"
Expand Down
47 changes: 47 additions & 0 deletions src/zgw_consumers_ext/tests/test_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.core.files import File
from django.test import TestCase

import requests_mock
from privates.test import temp_private_root
from simple_certmanager.constants import CertificateTypes
from simple_certmanager.models import Certificate
Expand Down Expand Up @@ -98,3 +99,49 @@ def test_no_auth(self):
client = APIClient.configure_from(factory)

self.assertIsNone(client.auth)

def test_api_key_auth(self):
service = ServiceFactory.build(
api_root="https://example.com/",
auth_type=AuthTypes.api_key,
header_key="Some-Auth-Header",
header_value="some-api-key",
)
factory = ServiceClientFactory(service)
client = APIClient.configure_from(factory)

with self.subTest("client.auth configuration"):
self.assertIsNotNone(client.auth)

with self.subTest("dummy API call"):
with requests_mock.Mocker() as m, client:
m.get("https://example.com/foo")

client.get("foo")

headers = m.last_request.headers
self.assertIn("Some-Auth-Header", headers)
self.assertEqual(headers["Some-Auth-Header"], "some-api-key")

def test_zgw_auth(self):
service = ServiceFactory.build(
api_root="https://example.com/",
auth_type=AuthTypes.zgw,
client_id="my-client-id",
secret="my-secret",
)
factory = ServiceClientFactory(service)
client = APIClient.configure_from(factory)

with self.subTest("client.auth configuration"):
self.assertIsNotNone(client.auth)

with self.subTest("dummy API call"):
with requests_mock.Mocker() as m, client:
m.get("https://example.com/foo")

client.get("foo")

headers = m.last_request.headers
self.assertIn("Authorization", headers)
self.assertTrue(headers["Authorization"].startswith("Bearer "))

0 comments on commit fcd47bd

Please sign in to comment.