from django.contrib.auth import get_user_model from django.test import TestCase from django.urls import reverse from django.utils import timezone from apps.users.models import APIToken class UserAPITokenViewsTests(TestCase): def setUp(self): self.user = get_user_model().objects.create_user( email="user@example.com", password="test-password", ) self.client.force_login(self.user) self.htmx_headers = {"HTTP_HX_REQUEST": "true"} def test_user_settings_renders_api_token_section(self): response = self.client.get(reverse("user_settings"), **self.htmx_headers) self.assertContains(response, "API Tokens") self.assertContains(response, reverse("user_api_token_add")) def test_can_create_api_token_from_ui(self): response = self.client.post( reverse("user_api_token_add"), {"name": "n8n", "expires_in_days": "30"}, **self.htmx_headers, ) self.assertEqual(response.status_code, 200) self.assertContains(response, "Copy this token now") self.assertEqual(APIToken.objects.filter(user=self.user, name="n8n").count(), 1) def test_can_revoke_own_api_token(self): token, _ = APIToken.objects.create_token(user=self.user, name="n8n") response = self.client.delete( reverse("user_api_token_revoke", kwargs={"token_id": token.id}), **self.htmx_headers, ) self.assertEqual(response.status_code, 200) token.refresh_from_db() self.assertIsNotNone(token.revoked_at) self.assertContains(response, "Revoked") def test_can_delete_revoked_api_token(self): token, _ = APIToken.objects.create_token(user=self.user, name="n8n") token.revoked_at = timezone.now() token.save(update_fields=["revoked_at"]) response = self.client.delete( reverse("user_api_token_delete", kwargs={"token_id": token.id}), **self.htmx_headers, ) self.assertEqual(response.status_code, 200) self.assertFalse(APIToken.objects.filter(id=token.id).exists()) def test_cannot_delete_other_users_api_token(self): other = get_user_model().objects.create_user( email="other@example.com", password="test-password" ) token, _ = APIToken.objects.create_token(user=other, name="theirs") response = self.client.delete( reverse("user_api_token_delete", kwargs={"token_id": token.id}), **self.htmx_headers, ) self.assertEqual(response.status_code, 404) self.assertTrue(APIToken.objects.filter(id=token.id).exists())