from django.contrib.auth.hashers import make_password from rest_framework import status from infrasynth.security.auth.middleware import JWTAuthenticationMiddleware from infrasynth.security.models import APIKey class TestAPIKeyViewSet: def test_create_returns_full_key_once(self, authenticated_client): resp = authenticated_client.post( "/api/auth/api-keys/", {"name": "CI Key", "scopes": ["read:users"]}, format="json", ) assert resp.status_code == status.HTTP_201_CREATED data = resp.json() assert "key" in data assert "prefix" in data assert data["key"].startswith(data["prefix"] + ".") def test_created_key_authenticates(self, authenticated_client): resp = authenticated_client.post( "/api/auth/api-keys/", {"name": "CI Key", "scopes": ["read:users"]}, format="json", ) full_key = resp.json()["key"] from rest_framework.test import APIClient client = APIClient() client.credentials(HTTP_X_API_KEY=full_key) check = client.get("/api/auth/check/") assert check.status_code == status.HTTP_200_OK def test_list_keys(self, authenticated_client, user): APIKey.objects.create( name="Old Key", prefix="prefix01", key_hash=make_password("secret"), created_by=user, ) resp = authenticated_client.get("/api/auth/api-keys/") assert resp.status_code == status.HTTP_200_OK assert resp.json()["count"] == 1 def test_list_never_exposes_hash(self, authenticated_client, user): APIKey.objects.create( name="Old Key", prefix="prefix01", key_hash=make_password("secret"), created_by=user, ) resp = authenticated_client.get("/api/auth/api-keys/") result = resp.json()["results"][0] assert "key" not in result assert "key_hash" not in result assert result["prefix"] == "prefix01" def test_delete_key(self, authenticated_client, user): key = APIKey.objects.create( name="Old Key", prefix="prefix01", key_hash=make_password("secret"), created_by=user, ) resp = authenticated_client.delete(f"/api/auth/api-keys/{key.pk}/") assert resp.status_code == status.HTTP_204_NO_CONTENT assert not APIKey.objects.filter(pk=key.pk).exists() def test_requires_auth(self, api_client): resp = api_client.get("/api/auth/api-keys/") assert resp.status_code == status.HTTP_401_UNAUTHORIZED class TestJWTAuthenticationMiddleware: def test_ignores_anonymous_requests(self, rf, db): request = rf.get("/api/features/active/") request.user = type("Anon", (), {"is_anonymous": True})() JWTAuthenticationMiddleware(get_response=lambda r: None).process_request(request) assert request.user.is_anonymous def test_populates_user_from_cookie(self, rf, user): from rest_framework_simplejwt.tokens import RefreshToken from infrasynth.shared.crypto import encrypt request = rf.get("/api/features/active/") request.COOKIES["access_token"] = encrypt(str(RefreshToken.for_user(user).access_token)) request.user = type("Anon", (), {"is_anonymous": True})() JWTAuthenticationMiddleware(get_response=lambda r: None).process_request(request) assert request.user == user