Fix EncryptedIntegerField and testcase

This commit is contained in:
naohide anahara 2022-05-07 08:23:24 +09:00
parent 025afa1987
commit 8c6563c0f3
2 changed files with 60 additions and 6 deletions

View file

@ -1,13 +1,13 @@
import base64 import base64
from django.utils import timezone
import warnings
from cryptography.fernet import Fernet, MultiFernet, InvalidToken from cryptography.fernet import Fernet, MultiFernet, InvalidToken
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from django.conf import settings from django.conf import settings
from django.core import validators
from django.db import models from django.db import models
from django.db.backends.base.operations import BaseDatabaseOperations
from django.utils.functional import cached_property from django.utils.functional import cached_property
@ -105,7 +105,38 @@ class EncryptedDateTimeField(EncryptedFieldMixin, models.DateTimeField):
class EncryptedIntegerField(EncryptedFieldMixin, models.IntegerField): class EncryptedIntegerField(EncryptedFieldMixin, models.IntegerField):
@cached_property @cached_property
def validators(self): def validators(self):
return [*self.default_validators, *self._validators] # These validators can't be added at field initialization time since
# they're based on values retrieved from `connection`.
validators_ = [*self.default_validators, *self._validators]
internal_type = models.IntegerField().get_internal_type()
min_value, max_value = BaseDatabaseOperations.integer_field_ranges[internal_type]
if min_value is not None and not any(
(
isinstance(validator, validators.MinValueValidator)
and (
validator.limit_value()
if callable(validator.limit_value)
else validator.limit_value
)
>= min_value
)
for validator in validators_
):
validators_.append(validators.MinValueValidator(min_value))
if max_value is not None and not any(
(
isinstance(validator, validators.MaxValueValidator)
and (
validator.limit_value()
if callable(validator.limit_value)
else validator.limit_value
)
<= max_value
)
for validator in validators_
):
validators_.append(validators.MaxValueValidator(max_value))
return validators_
class EncryptedDateField(EncryptedFieldMixin, models.DateField): class EncryptedDateField(EncryptedFieldMixin, models.DateField):

View file

@ -23,6 +23,7 @@ class FieldTest(TestCase):
model = TestModel() model = TestModel()
model.char = plaintext model.char = plaintext
model.full_clean()
model.save() model.save()
ciphertext = self.get_db_value("char", model.id) ciphertext = self.get_db_value("char", model.id)
@ -38,6 +39,7 @@ class FieldTest(TestCase):
model = TestModel() model = TestModel()
model.text = plaintext model.text = plaintext
model.full_clean()
model.save() model.save()
ciphertext = self.get_db_value("text", model.id) ciphertext = self.get_db_value("text", model.id)
@ -53,6 +55,7 @@ class FieldTest(TestCase):
model = TestModel() model = TestModel()
model.datetime = plaintext model.datetime = plaintext
model.full_clean()
model.save() model.save()
ciphertext = self.get_db_value("datetime", model.id) ciphertext = self.get_db_value("datetime", model.id)
@ -67,6 +70,7 @@ class FieldTest(TestCase):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
model.datetime = plaintext model.datetime = plaintext
model.full_clean()
model.save() model.save()
def test_integer_field_encrypted(self): def test_integer_field_encrypted(self):
@ -74,6 +78,7 @@ class FieldTest(TestCase):
model = TestModel() model = TestModel()
model.integer = plaintext model.integer = plaintext
model.full_clean()
model.save() model.save()
ciphertext = self.get_db_value("integer", model.id) ciphertext = self.get_db_value("integer", model.id)
@ -84,10 +89,19 @@ class FieldTest(TestCase):
fresh_model = TestModel.objects.get(id=model.id) fresh_model = TestModel.objects.get(id=model.id)
self.assertEqual(fresh_model.integer, plaintext) self.assertEqual(fresh_model.integer, plaintext)
# "IntegerField": (-2147483648, 2147483647)
plaintext = 2147483648
with self.assertRaises(ValidationError):
model.integer = plaintext
model.full_clean()
model.save()
plaintext = "text" plaintext = "text"
with self.assertRaises(ValueError): with self.assertRaises(TypeError):
model.integer = plaintext model.integer = plaintext
model.full_clean()
model.save() model.save()
def test_date_field_encrypted(self): def test_date_field_encrypted(self):
@ -95,6 +109,7 @@ class FieldTest(TestCase):
model = TestModel() model = TestModel()
model.date = plaintext model.date = plaintext
model.full_clean()
model.save() model.save()
ciphertext = self.get_db_value("date", model.id) ciphertext = self.get_db_value("date", model.id)
@ -107,6 +122,7 @@ class FieldTest(TestCase):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
model.date = plaintext model.date = plaintext
model.full_clean()
model.save() model.save()
def test_float_field_encrypted(self): def test_float_field_encrypted(self):
@ -114,6 +130,7 @@ class FieldTest(TestCase):
model = TestModel() model = TestModel()
model.floating = plaintext model.floating = plaintext
model.full_clean()
model.save() model.save()
ciphertext = self.get_db_value("floating", model.id) ciphertext = self.get_db_value("floating", model.id)
@ -128,6 +145,7 @@ class FieldTest(TestCase):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
model.floating = plaintext model.floating = plaintext
model.full_clean()
model.save() model.save()
def test_email_field_encrypted(self): def test_email_field_encrypted(self):
@ -135,6 +153,7 @@ class FieldTest(TestCase):
model = TestModel() model = TestModel()
model.email = plaintext model.email = plaintext
model.full_clean()
model.save() model.save()
ciphertext = self.get_db_value("email", model.id) ciphertext = self.get_db_value("email", model.id)
@ -147,14 +166,17 @@ class FieldTest(TestCase):
plaintext = "text" plaintext = "text"
model.email = plaintext with self.assertRaises(ValidationError):
model.save() model.email = plaintext
model.full_clean()
model.save()
def test_boolean_field_encrypted(self): def test_boolean_field_encrypted(self):
plaintext = True plaintext = True
model = TestModel() model = TestModel()
model.boolean = plaintext model.boolean = plaintext
model.full_clean()
model.save() model.save()
ciphertext = self.get_db_value("boolean", model.id) ciphertext = self.get_db_value("boolean", model.id)
@ -174,6 +196,7 @@ class FieldTest(TestCase):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
model.boolean = plaintext model.boolean = plaintext
model.full_clean()
model.save() model.save()