|
| 1 | +from django.contrib.auth import get_user_model |
| 2 | +from django.test import TestCase |
| 3 | + |
| 4 | +from oidc_provider.admin import ClientForm |
| 5 | +from oidc_provider.models import Client |
| 6 | +from oidc_provider.models import ResponseType |
| 7 | +from oidc_provider.tests.app.utils import create_fake_user |
| 8 | + |
| 9 | +User = get_user_model() |
| 10 | + |
| 11 | + |
| 12 | +class ClientFormTest(TestCase): |
| 13 | + """ |
| 14 | + Test cases for ClientForm in admin. |
| 15 | + """ |
| 16 | + |
| 17 | + def setUp(self): |
| 18 | + self.user = create_fake_user() |
| 19 | + self.code_response_type, _ = ResponseType.objects.get_or_create( |
| 20 | + value="code", defaults={"description": "code (Authorization Code Flow)"} |
| 21 | + ) |
| 22 | + |
| 23 | + def test_creates_client_without_client_id_generates_random_one(self): |
| 24 | + """Test that creating a client without client_id generates a random 6-digit one.""" |
| 25 | + form_data = { |
| 26 | + "name": "Test Client", |
| 27 | + "owner": self.user.pk, |
| 28 | + "client_type": "public", |
| 29 | + "response_types": [self.code_response_type.pk], |
| 30 | + "_redirect_uris": "http://example.com/callback", |
| 31 | + } |
| 32 | + |
| 33 | + form = ClientForm(data=form_data) |
| 34 | + self.assertTrue(form.is_valid(), f"Form errors: {form.errors}") |
| 35 | + |
| 36 | + # The form should generate a client_id |
| 37 | + client_id = form.clean_client_id() |
| 38 | + self.assertIsNotNone(client_id) |
| 39 | + self.assertEqual(len(client_id), 6) |
| 40 | + self.assertTrue(client_id.isdigit()) |
| 41 | + self.assertTrue(1 <= int(client_id) <= 999999) |
| 42 | + |
| 43 | + def test_creates_client_with_custom_client_id_preserves_it(self): |
| 44 | + """Test that providing a custom client_id preserves it for new clients.""" |
| 45 | + # Create and save a client first |
| 46 | + client = Client.objects.create( |
| 47 | + name="Existing Client", |
| 48 | + owner=self.user, |
| 49 | + client_type="public", |
| 50 | + client_id="custom-client-123", |
| 51 | + ) |
| 52 | + client.response_types.add(self.code_response_type) |
| 53 | + |
| 54 | + form_data = { |
| 55 | + "name": "Existing Client Updated", |
| 56 | + "owner": self.user.pk, |
| 57 | + "client_type": "public", |
| 58 | + "response_types": [self.code_response_type.pk], |
| 59 | + "_redirect_uris": "http://example.com/callback", |
| 60 | + "client_id": "custom-client-123", |
| 61 | + } |
| 62 | + |
| 63 | + # Test updating existing client |
| 64 | + form = ClientForm(data=form_data, instance=client) |
| 65 | + self.assertTrue(form.is_valid(), f"Form errors: {form.errors}") |
| 66 | + |
| 67 | + # Should return the sanitized version of existing client_id |
| 68 | + client_id = form.clean_client_id() |
| 69 | + self.assertEqual(client_id, "custom-client-123") |
| 70 | + |
| 71 | + def test_sanitizes_existing_client_id_with_control_characters(self): |
| 72 | + """Test that existing client_id with control characters gets sanitized.""" |
| 73 | + # Create a client with problematic client_id |
| 74 | + client = Client.objects.create( |
| 75 | + name="Problematic Client", |
| 76 | + owner=self.user, |
| 77 | + client_type="public", |
| 78 | + client_id="normalclient", # Start with normal client_id |
| 79 | + ) |
| 80 | + client.response_types.add(self.code_response_type) |
| 81 | + |
| 82 | + # Manually set problematic client_id to test sanitization |
| 83 | + client.client_id = "client\x00\x01test" # Contains null byte and control char |
| 84 | + |
| 85 | + form_data = { |
| 86 | + "name": "Problematic Client", |
| 87 | + "owner": self.user.pk, |
| 88 | + "client_type": "public", |
| 89 | + "response_types": [self.code_response_type.pk], |
| 90 | + "_redirect_uris": "http://example.com/callback", |
| 91 | + } |
| 92 | + |
| 93 | + form = ClientForm(data=form_data, instance=client) |
| 94 | + self.assertTrue(form.is_valid(), f"Form errors: {form.errors}") |
| 95 | + |
| 96 | + # Should return sanitized client_id |
| 97 | + client_id = form.clean_client_id() |
| 98 | + self.assertEqual(client_id, "clienttest") # Control characters removed |
0 commit comments