-
-
Notifications
You must be signed in to change notification settings - Fork 213
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
42ea374
commit 130a70d
Showing
5 changed files
with
331 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from django.test import TestCase | ||
from unittest.mock import patch | ||
from knox.settings import knox_settings | ||
from knox.crypto import create_token_string, make_hex_compatible, hash_token | ||
|
||
|
||
class CryptoUtilsTestCase(TestCase): | ||
def test_create_token_string(self): | ||
""" | ||
Verify token string creation has correct length and contains only hex characters. | ||
""" | ||
with patch('os.urandom') as mock_urandom: | ||
mock_urandom.return_value = b'abcdef1234567890' | ||
expected_length = knox_settings.AUTH_TOKEN_CHARACTER_LENGTH | ||
token = create_token_string() | ||
self.assertEqual(len(token), expected_length) | ||
hex_chars = set('0123456789abcdef') | ||
self.assertTrue(all(c in hex_chars for c in token.lower())) | ||
|
||
def test_make_hex_compatible_with_valid_input(self): | ||
""" | ||
Ensure standard strings are correctly converted to hex-compatible bytes. | ||
""" | ||
test_token = "test123" | ||
result = make_hex_compatible(test_token) | ||
self.assertIsInstance(result, bytes) | ||
expected = b'test123' | ||
self.assertEqual(result, expected) | ||
|
||
def test_make_hex_compatible_with_empty_string(self): | ||
""" | ||
Verify empty string input returns empty bytes. | ||
""" | ||
test_token = "" | ||
result = make_hex_compatible(test_token) | ||
self.assertEqual(result, b'') | ||
|
||
def test_make_hex_compatible_with_special_characters(self): | ||
""" | ||
Check hex compatibility conversion handles special characters correctly. | ||
""" | ||
test_token = "test@#$%" | ||
result = make_hex_compatible(test_token) | ||
self.assertIsInstance(result, bytes) | ||
expected = b'test@#$%' | ||
self.assertEqual(result, expected) | ||
|
||
def test_hash_token_with_valid_token(self): | ||
""" | ||
Verify hash output is correct length and contains valid hex characters. | ||
""" | ||
test_token = "abcdef1234567890" | ||
result = hash_token(test_token) | ||
self.assertIsInstance(result, str) | ||
self.assertEqual(len(result), 128) | ||
hex_chars = set('0123456789abcdef') | ||
self.assertTrue(all(c in hex_chars for c in result.lower())) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
from django.test import TestCase, override_settings | ||
from django.contrib.auth import get_user_model | ||
from django.utils import timezone | ||
from django.core.exceptions import ImproperlyConfigured | ||
from datetime import timedelta | ||
from freezegun import freeze_time | ||
|
||
from knox.settings import CONSTANTS, knox_settings | ||
from knox.models import AuthToken, get_token_model | ||
|
||
class AuthTokenTests(TestCase): | ||
""" | ||
Auth token model tests. | ||
""" | ||
|
||
def setUp(self): | ||
self.User = get_user_model() | ||
self.user = self.User.objects.create_user( | ||
username='testuser', | ||
password='testpass123' | ||
) | ||
|
||
def test_token_creation(self): | ||
""" | ||
Test that tokens are created correctly with expected format. | ||
""" | ||
token_creation = timezone.now() | ||
with freeze_time(token_creation): | ||
instance, token = AuthToken.objects.create(user=self.user) | ||
self.assertIsNotNone(token) | ||
self.assertTrue(token.startswith(knox_settings.TOKEN_PREFIX)) | ||
self.assertEqual( | ||
len(instance.token_key), | ||
CONSTANTS.TOKEN_KEY_LENGTH, | ||
) | ||
self.assertEqual(instance.user, self.user) | ||
self.assertEqual( | ||
instance.expiry, | ||
token_creation + timedelta(hours=10) | ||
) | ||
|
||
def test_token_creation_with_expiry(self): | ||
""" | ||
Test token creation with explicit expiry time. | ||
""" | ||
expiry_time = timedelta(hours=10) | ||
before_creation = timezone.now() | ||
instance, _ = AuthToken.objects.create( | ||
user=self.user, | ||
expiry=expiry_time | ||
) | ||
self.assertIsNotNone(instance.expiry) | ||
self.assertTrue(before_creation < instance.expiry) | ||
self.assertTrue( | ||
(instance.expiry - before_creation - expiry_time).total_seconds() < 1 | ||
) | ||
|
||
def test_token_string_representation(self): | ||
""" | ||
Test the string representation of AuthToken. | ||
""" | ||
instance, _ = AuthToken.objects.create(user=self.user) | ||
expected_str = f'{instance.digest} : {self.user}' | ||
self.assertEqual(str(instance), expected_str) | ||
|
||
def test_multiple_tokens_for_user(self): | ||
""" | ||
Test that a user can have multiple valid tokens. | ||
""" | ||
token1, _ = AuthToken.objects.create(user=self.user) | ||
token2, _ = AuthToken.objects.create(user=self.user) | ||
user_tokens = self.user.auth_token_set.all() | ||
self.assertEqual(user_tokens.count(), 2) | ||
self.assertNotEqual(token1.digest, token2.digest) | ||
|
||
def test_token_with_custom_prefix(self): | ||
""" | ||
Test token creation with custom prefix. | ||
""" | ||
custom_prefix = "TEST_" | ||
instance, token = AuthToken.objects.create( | ||
user=self.user, | ||
prefix=custom_prefix | ||
) | ||
self.assertTrue(token.startswith(custom_prefix)) | ||
self.assertTrue(instance.token_key.startswith(custom_prefix)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
from datetime import timedelta | ||
from unittest import mock | ||
import hashlib | ||
from django.test import override_settings | ||
from django.core.signals import setting_changed | ||
from django.conf import settings | ||
|
||
from knox.settings import ( | ||
CONSTANTS, | ||
knox_settings, | ||
reload_api_settings, | ||
IMPORT_STRINGS | ||
) | ||
|
||
class TestKnoxSettings: | ||
@override_settings(REST_KNOX={ | ||
'AUTH_TOKEN_CHARACTER_LENGTH': 32, | ||
'TOKEN_TTL': timedelta(hours=5), | ||
'AUTO_REFRESH': True, | ||
}) | ||
def test_override_settings(self): | ||
""" | ||
Test that settings can be overridden. | ||
""" | ||
assert knox_settings.AUTH_TOKEN_CHARACTER_LENGTH == 32 | ||
assert knox_settings.TOKEN_TTL == timedelta(hours=5) | ||
assert knox_settings.AUTO_REFRESH is True | ||
# Default values should remain unchanged | ||
assert knox_settings.AUTH_HEADER_PREFIX == 'Token' | ||
|
||
def test_constants_immutability(self): | ||
""" | ||
Test that CONSTANTS cannot be modified. | ||
""" | ||
with self.assertRaises(Exception): | ||
CONSTANTS.TOKEN_KEY_LENGTH = 20 | ||
|
||
with self.assertRaises(Exception): | ||
CONSTANTS.DIGEST_LENGTH = 256 | ||
|
||
def test_constants_values(self): | ||
""" | ||
Test that CONSTANTS have correct values. | ||
""" | ||
assert CONSTANTS.TOKEN_KEY_LENGTH == 15 | ||
assert CONSTANTS.DIGEST_LENGTH == 128 | ||
assert CONSTANTS.MAXIMUM_TOKEN_PREFIX_LENGTH == 10 | ||
|
||
def test_reload_api_settings(self): | ||
""" | ||
Test settings reload functionality. | ||
""" | ||
new_settings = { | ||
'TOKEN_TTL': timedelta(hours=2), | ||
'AUTH_HEADER_PREFIX': 'Bearer', | ||
} | ||
|
||
reload_api_settings( | ||
setting='REST_KNOX', | ||
value=new_settings | ||
) | ||
|
||
assert knox_settings.TOKEN_TTL == timedelta(hours=2) | ||
assert knox_settings.AUTH_HEADER_PREFIX == 'Bearer' | ||
|
||
def test_token_prefix_length_validation(self): | ||
""" | ||
Test that TOKEN_PREFIX length is validated. | ||
""" | ||
with self.assertRaises(ValueError, match="Illegal TOKEN_PREFIX length"): | ||
reload_api_settings( | ||
setting='REST_KNOX', | ||
value={'TOKEN_PREFIX': 'x' * 11} # Exceeds MAXIMUM_TOKEN_PREFIX_LENGTH | ||
) | ||
|
||
def test_import_strings(self): | ||
""" | ||
Test that import strings are properly handled. | ||
""" | ||
assert 'SECURE_HASH_ALGORITHM' in IMPORT_STRINGS | ||
assert 'USER_SERIALIZER' in IMPORT_STRINGS | ||
|
||
@override_settings(REST_KNOX={ | ||
'SECURE_HASH_ALGORITHM': 'hashlib.md5' | ||
}) | ||
def test_hash_algorithm_import(self): | ||
""" | ||
Test that hash algorithm is properly imported. | ||
""" | ||
assert knox_settings.SECURE_HASH_ALGORITHM == hashlib.md5 | ||
|
||
def test_setting_changed_signal(self): | ||
""" | ||
Test that setting_changed signal properly triggers reload. | ||
""" | ||
new_settings = { | ||
'TOKEN_TTL': timedelta(hours=3), | ||
} | ||
|
||
setting_changed.send( | ||
sender=None, | ||
setting='REST_KNOX', | ||
value=new_settings | ||
) | ||
|
||
assert knox_settings.TOKEN_TTL == timedelta(hours=3) | ||
|
||
@mock.patch('django.conf.settings') | ||
def test_custom_token_model(self, mock_settings): | ||
""" | ||
Test custom token model setting. | ||
""" | ||
custom_model = 'custom_app.CustomToken' | ||
mock_settings.KNOX_TOKEN_MODEL = custom_model | ||
|
||
# Reload settings | ||
reload_api_settings( | ||
setting='REST_KNOX', | ||
value={} | ||
) | ||
|
||
assert knox_settings.TOKEN_MODEL == custom_model |
Oops, something went wrong.