Skip to content

Commit f951b8c

Browse files
committed
write tests
1 parent f87d54e commit f951b8c

4 files changed

Lines changed: 212 additions & 0 deletions

File tree

api/tests/test_admin.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import pytest
2+
from django.contrib.admin import AdminSite
3+
from django.http import HttpRequest
4+
from model_bakery import baker
5+
from pytest_django.asserts import assertNumQueries
6+
7+
from api.admin import ApiClientAdmin
8+
from api.models import ApiClient
9+
10+
11+
@pytest.mark.django_db
12+
def test_reset_hmac_action():
13+
client_admin = ApiClientAdmin(ApiClient, AdminSite())
14+
api_clients = baker.make(ApiClient, _quantity=4, _bulk_create=True)
15+
old_hmac_keys = [c.hmac_key for c in api_clients]
16+
with assertNumQueries(2):
17+
qs = ApiClient.objects.filter(id__in=[c.id for c in api_clients[2:4]])
18+
client_admin.reset_hmac_key(HttpRequest(), qs)
19+
for c in api_clients:
20+
c.refresh_from_db()
21+
assert api_clients[0].hmac_key == old_hmac_keys[0]
22+
assert api_clients[1].hmac_key == old_hmac_keys[1]
23+
assert api_clients[2].hmac_key != old_hmac_keys[2]
24+
assert api_clients[3].hmac_key != old_hmac_keys[3]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import pytest
2+
from django.test import Client
3+
from django.urls import reverse
4+
from model_bakery import baker
5+
6+
from api.hashers import generate_key
7+
from api.models import ApiClient, ApiKey
8+
from api.schemas import ApiClientSchema
9+
10+
11+
@pytest.mark.django_db
12+
def test_api_client_controller(client: Client):
13+
key, hashed = generate_key()
14+
api_client = baker.make(ApiClient)
15+
baker.make(ApiKey, client=api_client, hashed_key=hashed)
16+
res = client.get(reverse("api:api-client-infos"), headers={"X-APIKey": key})
17+
assert res.status_code == 200
18+
assert res.json() == ApiClientSchema.from_orm(api_client).model_dump()

api/tests/test_client.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import pytest
2+
from django.contrib.auth.models import Permission
3+
from django.test import TestCase
4+
from model_bakery import baker
5+
6+
from api.models import ApiClient
7+
from core.models import Group
8+
9+
10+
class TestClientPermissions(TestCase):
11+
@classmethod
12+
def setUpTestData(cls):
13+
cls.api_client = baker.make(ApiClient)
14+
cls.perms = baker.make(Permission, _quantity=10, _bulk_create=True)
15+
cls.api_client.groups.set(
16+
[
17+
baker.make(Group, permissions=cls.perms[0:3]),
18+
baker.make(Group, permissions=cls.perms[3:5]),
19+
]
20+
)
21+
cls.api_client.client_permissions.set(
22+
[cls.perms[3], cls.perms[5], cls.perms[6], cls.perms[7]]
23+
)
24+
25+
def test_all_permissions(self):
26+
assert self.api_client.all_permissions == {
27+
f"{p.content_type.app_label}.{p.codename}" for p in self.perms[0:8]
28+
}
29+
30+
def test_has_perm(self):
31+
assert self.api_client.has_perm(
32+
f"{self.perms[1].content_type.app_label}.{self.perms[1].codename}"
33+
)
34+
assert not self.api_client.has_perm(
35+
f"{self.perms[9].content_type.app_label}.{self.perms[9].codename}"
36+
)
37+
38+
def test_has_perms(self):
39+
assert self.api_client.has_perms(
40+
[
41+
f"{self.perms[1].content_type.app_label}.{self.perms[1].codename}",
42+
f"{self.perms[2].content_type.app_label}.{self.perms[2].codename}",
43+
]
44+
)
45+
assert not self.api_client.has_perms(
46+
[
47+
f"{self.perms[1].content_type.app_label}.{self.perms[1].codename}",
48+
f"{self.perms[9].content_type.app_label}.{self.perms[9].codename}",
49+
],
50+
)
51+
52+
53+
@pytest.mark.django_db
54+
def test_reset_hmac_key():
55+
client = baker.make(ApiClient)
56+
original_key = client.hmac_key
57+
client.reset_hmac(commit=True)
58+
assert len(client.hmac_key) == len(original_key)
59+
assert client.hmac_key != original_key

api/tests/test_third_party_auth.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
from unittest import mock
2+
from unittest.mock import Mock
3+
4+
from django.db.models import Max
5+
from django.test import TestCase
6+
from django.urls import reverse
7+
from model_bakery import baker
8+
from pytest_django.asserts import assertRedirects
9+
10+
from api.models import ApiClient, get_hmac_key
11+
from core.baker_recipes import subscriber_user
12+
from core.utils import hmac_hexdigest
13+
14+
15+
def mocked_post(*, ok: bool):
16+
class MockedResponse(Mock):
17+
@property
18+
def ok(self):
19+
return ok
20+
21+
def mocked():
22+
return MockedResponse()
23+
24+
return mocked
25+
26+
27+
class TestThirdPartyAuth(TestCase):
28+
@classmethod
29+
def setUpTestData(cls):
30+
cls.user = subscriber_user.make()
31+
cls.api_client = baker.make(ApiClient)
32+
33+
def setUp(self):
34+
self.query = {
35+
"client_id": self.api_client.id,
36+
"third_party_app": "app",
37+
"cgu_link": "https://foobar.fr/",
38+
"username": "bibou",
39+
"callback_url": "https://callback.fr/",
40+
}
41+
self.query["signature"] = hmac_hexdigest(self.api_client.hmac_key, self.query)
42+
self.callback_data = {"user_id": self.user.id}
43+
self.callback_data["signature"] = hmac_hexdigest(
44+
self.api_client.hmac_key, self.callback_data
45+
)
46+
47+
def test_auth_ok(self):
48+
self.client.force_login(self.user)
49+
res = self.client.get(reverse("api-link:third-party-auth", query=self.query))
50+
assert res.status_code == 200
51+
with mock.patch("requests.post", new_callable=mocked_post(ok=True)) as mocked:
52+
res = self.client.post(
53+
reverse("api-link:third-party-auth"),
54+
data={"cgu_accepted": True, "is_username_valid": True, **self.query},
55+
)
56+
mocked.assert_called_once_with(
57+
self.query["callback_url"], json=self.callback_data
58+
)
59+
assertRedirects(
60+
res,
61+
reverse("api-link:third-party-auth-result", kwargs={"result": "success"}),
62+
)
63+
64+
def test_callback_error(self):
65+
"""Test that the user see the failure page if the callback request failed."""
66+
self.client.force_login(self.user)
67+
with mock.patch("requests.post", new_callable=mocked_post(ok=False)) as mocked:
68+
res = self.client.post(
69+
reverse("api-link:third-party-auth"),
70+
data={"cgu_accepted": True, "is_username_valid": True, **self.query},
71+
)
72+
mocked.assert_called_once_with(
73+
self.query["callback_url"], json=self.callback_data
74+
)
75+
assertRedirects(
76+
res,
77+
reverse("api-link:third-party-auth-result", kwargs={"result": "failure"}),
78+
)
79+
80+
def test_wrong_signature(self):
81+
"""Test that a 403 is raised if the signature of the query is wrong."""
82+
self.client.force_login(subscriber_user.make())
83+
new_key = get_hmac_key()
84+
del self.query["signature"]
85+
self.query["signature"] = hmac_hexdigest(new_key, self.query)
86+
res = self.client.get(reverse("api-link:third-party-auth", query=self.query))
87+
assert res.status_code == 403
88+
89+
def test_cgu_not_accepted(self):
90+
self.client.force_login(self.user)
91+
res = self.client.get(reverse("api-link:third-party-auth", query=self.query))
92+
assert res.status_code == 200
93+
res = self.client.post(reverse("api-link:third-party-auth"), data=self.query)
94+
assert res.status_code == 200 # no redirect means invalid form
95+
res = self.client.post(
96+
reverse("api-link:third-party-auth"),
97+
data={"cgu_accepted": False, "is_username_valid": False, **self.query},
98+
)
99+
assert res.status_code == 200
100+
101+
def test_invalid_client(self):
102+
self.query["client_id"] = ApiClient.objects.aggregate(res=Max("id"))["res"] + 1
103+
res = self.client.get(reverse("api-link:third-party-auth", query=self.query))
104+
assert res.status_code == 403
105+
106+
def test_missing_parameter(self):
107+
"""Test that a 403 is raised if there is a missing parameter."""
108+
del self.query["username"]
109+
self.query["signature"] = hmac_hexdigest(self.api_client.hmac_key, self.query)
110+
res = self.client.get(reverse("api-link:third-party-auth", query=self.query))
111+
assert res.status_code == 403

0 commit comments

Comments
 (0)