Skip to content

Commit a8d2aa4

Browse files
committed
Code review fixes
1 parent 608dce3 commit a8d2aa4

File tree

4 files changed

+63
-76
lines changed

4 files changed

+63
-76
lines changed

docs/source/ref/models/fields.rst

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,6 @@ These indexes use 0-based indexing.
299299
As described above for :class:`EmbeddedModelField`,
300300
:djadmin:`makemigrations` does not yet detect changes to embedded models.
301301

302-
303302
``ObjectIdAutoField``
304303
---------------------
305304

@@ -322,33 +321,33 @@ Encrypted fields are used to store sensitive data with MongoDB's Queryable
322321
Encryption feature. They are subclasses of Django's built-in fields, and
323322
they encrypt the data before storing it in the database.
324323

325-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
326-
| Encrypted Field | Django Field |
327-
+=======================================+===============================================================================================================+
328-
| ``EncryptedBigIntegerField`` | `BigIntegerField <https://docs.djangoproject.com/en/stable/ref/models/fields/#bigintegerfield>`__ |
329-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
330-
| ``EncryptedBooleanField`` | `BooleanField <https://docs.djangoproject.com/en/stable/ref/models/fields/#booleanfield>`__ |
331-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
332-
| ``EncryptedCharField`` | `CharField <https://docs.djangoproject.com/en/stable/ref/models/fields/#charfield>`__ |
333-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
334-
| ``EncryptedDateField`` | `DateField <https://docs.djangoproject.com/en/stable/ref/models/fields/#datefield>`__ |
335-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
336-
| ``EncryptedDateTimeField`` | `DateTimeField <https://docs.djangoproject.com/en/stable/ref/models/fields/#datetimefield>`__ |
337-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
338-
| ``EncryptedDecimalField`` | `DecimalField <https://docs.djangoproject.com/en/stable/ref/models/fields/#decimalfield>`__ |
339-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
340-
| ``EncryptedFloatField`` | `FloatField <https://docs.djangoproject.com/en/stable/ref/models/fields/#floatfield>`__ |
341-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
342-
| ``EncryptedGenericIPAddressField`` | `GenericIPAddressField <https://docs.djangoproject.com/en/stable/ref/models/fields/#genericipaddressfield>`__ |
343-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
344-
| ``EncryptedIntegerField`` | `IntegerField <https://docs.djangoproject.com/en/stable/ref/models/fields/#integerfield>`__ |
345-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
346-
| ``EncryptedTextField`` | `TextField <https://docs.djangoproject.com/en/stable/ref/models/fields/#textfield>`__ |
347-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
348-
| ``EncryptedTimeField`` | `TimeField <https://docs.djangoproject.com/en/stable/ref/models/fields/#timefield>`__ |
349-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
350-
| ``EncryptedURLField`` | `URLField <https://docs.djangoproject.com/en/stable/ref/models/fields/#urlfield>`__ |
351-
+---------------------------------------+---------------------------------------------------------------------------------------------------------------+
324+
+---------------------------------------+--------------------------------------------------+
325+
| Encrypted Field | Django Field |
326+
+=======================================+==================================================+
327+
| ``EncryptedBigIntegerField`` | :class:`~django.db.models.BigIntegerField` |
328+
+---------------------------------------+--------------------------------------------------+
329+
| ``EncryptedBooleanField`` | :class:`~django.db.models.BooleanField` |
330+
+---------------------------------------+--------------------------------------------------+
331+
| ``EncryptedCharField`` | :class:`~django.db.models.CharField` |
332+
+---------------------------------------+--------------------------------------------------+
333+
| ``EncryptedDateField`` | :class:`~django.db.models.DateField` |
334+
+---------------------------------------+--------------------------------------------------+
335+
| ``EncryptedDateTimeField`` | :class:`~django.db.models.DateTimeField` |
336+
+---------------------------------------+--------------------------------------------------+
337+
| ``EncryptedDecimalField`` | :class:`~django.db.models.DecimalField` |
338+
+---------------------------------------+--------------------------------------------------+
339+
| ``EncryptedFloatField`` | :class:`~django.db.models.FloatField` |
340+
+---------------------------------------+--------------------------------------------------+
341+
| ``EncryptedGenericIPAddressField`` | :class:`~django.db.models.GenericIPAddressField` |
342+
+---------------------------------------+--------------------------------------------------+
343+
| ``EncryptedIntegerField`` | :class:`~django.db.models.IntegerField` |
344+
+---------------------------------------+--------------------------------------------------+
345+
| ``EncryptedTextField`` | :class:`~django.db.models.TextField` |
346+
+---------------------------------------+--------------------------------------------------+
347+
| ``EncryptedTimeField`` | :class:`~django.db.models.TimeField` |
348+
+---------------------------------------+--------------------------------------------------+
349+
| ``EncryptedURLField`` | :class:`~django.db.models.URLField` |
350+
+---------------------------------------+--------------------------------------------------+
352351

353352
.. _encrypted-model-unsupported-fields:
354353

@@ -357,8 +356,8 @@ Unsupported fields
357356

358357
The following fields are supported by Django MongoDB Backend but not by Queryable Encryption.
359358

360-
+---------------------------------------+--------------------------------------------------------------------------------------------------------+
361-
| ``EncryptedDurationField`` | `DurationField <https://docs.djangoproject.com/en/stable/ref/models/fields/#durationfield>`__ |
362-
+---------------------------------------+--------------------------------------------------------------------------------------------------------+
363-
| ``EncryptedSlugField`` | `SlugField <https://docs.djangoproject.com/en/stable/ref/models/fields/#slugfield>`__ |
364-
+---------------------------------------+--------------------------------------------------------------------------------------------------------+
359+
+---------------------------------------+--------------------------------------------------+
360+
| ``EncryptedDurationField`` | :class:`~django.db.models.DurationField` |
361+
+---------------------------------------+--------------------------------------------------+
362+
| ``EncryptedSlugField`` | :class:`~django.db.models.SlugField` |
363+
+---------------------------------------+--------------------------------------------------+

tests/backend_/test_features.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,19 @@ def mocked_command(command):
4646
self.assertIs(connection.features.supports_transactions, False)
4747

4848

49-
# FIXME: On evergreen.
50-
# class SupportsQueryableEncryptionTests(TestCase):
51-
# def setUp(self):
52-
# # Clear the cached property.
53-
# connection.features.__dict__.pop("supports_queryable_encryption", None)
54-
#
55-
# def tearDown(self):
56-
# del connection.features.supports_queryable_encryption
57-
#
58-
# def test_supports_queryable_encryption(self):
59-
# def mocked_command(command):
60-
# if command == "buildInfo":
61-
# return {"modules": ["enterprise"]}
62-
# raise Exception("Unexpected command")
63-
#
64-
# with patch("pymongo.synchronous.database.Database.command", wraps=mocked_command):
65-
# self.assertIs(connection.features.supports_queryable_encryption, True)
49+
class SupportsQueryableEncryptionTests(TestCase):
50+
def setUp(self):
51+
# Clear the cached property.
52+
connection.features.__dict__.pop("supports_queryable_encryption", None)
53+
54+
def tearDown(self):
55+
del connection.features.supports_queryable_encryption
56+
57+
def test_supports_queryable_encryption(self):
58+
def mocked_command(command):
59+
if command == "buildInfo":
60+
return {"modules": ["enterprise"]}
61+
raise Exception("Unexpected command")
62+
63+
with patch("pymongo.synchronous.database.Database.command", wraps=mocked_command):
64+
self.assertIs(connection.features.supports_queryable_encryption, True)

tests/encryption_/models.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,26 @@
2121
class Appointment(EncryptedModel):
2222
time = EncryptedTimeField(queries=EqualityQuery())
2323

24+
class Meta:
25+
required_db_features = {"supports_queryable_encryption"}
26+
2427

2528
class Billing(EncryptedModel):
2629
cc_type = EncryptedCharField(max_length=20, queries=EqualityQuery())
2730
cc_number = EncryptedBigIntegerField(queries=EqualityQuery())
2831
account_balance = EncryptedDecimalField(max_digits=10, decimal_places=2, queries=RangeQuery())
2932

3033
class Meta:
31-
db_table = "billing"
34+
required_db_features = {"supports_queryable_encryption"}
3235

3336

3437
class PatientPortalUser(EncryptedModel):
3538
ip_address = EncryptedGenericIPAddressField(queries=EqualityQuery())
3639
url = EncryptedURLField(queries=EqualityQuery())
3740

41+
class Meta:
42+
required_db_features = {"supports_queryable_encryption"}
43+
3844

3945
class PatientRecord(EncryptedModel):
4046
ssn = EncryptedCharField(max_length=11, queries=EqualityQuery())
@@ -47,7 +53,7 @@ class PatientRecord(EncryptedModel):
4753
# billing =
4854

4955
class Meta:
50-
db_table = "patientrecord"
56+
required_db_features = {"supports_queryable_encryption"}
5157

5258

5359
class Patient(EncryptedModel):
@@ -61,8 +67,5 @@ class Patient(EncryptedModel):
6167
# TODO: Embed PatientRecord model
6268
# patient_record =
6369

64-
+ class Meta:
65-
+ required_db_features = {"supports_queryable_encryption"}
66-
+
6770
class Meta:
68-
db_table = "patient"
71+
required_db_features = {"supports_queryable_encryption"}

tests/encryption_/tests.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from .routers import TestEncryptedRouter
2626

2727
EXPECTED_ENCRYPTED_FIELDS_MAP = {
28-
"billing": {
28+
"encryption__billing": {
2929
"fields": [
3030
{
3131
"bsonType": "string",
@@ -47,7 +47,7 @@
4747
},
4848
]
4949
},
50-
"patientrecord": {
50+
"encryption__patientrecord": {
5151
"fields": [
5252
{
5353
"bsonType": "string",
@@ -81,7 +81,7 @@
8181
},
8282
]
8383
},
84-
"patient": {
84+
"encryption__patient": {
8585
"fields": [
8686
{
8787
"bsonType": "int",
@@ -327,7 +327,7 @@ def test_patientrecord(self):
327327
# get_new_connection will return the encrypted connection
328328
# from the connection pool.
329329
connection = pymongo.MongoClient(**conn_params)
330-
patientrecords = connection["test_other"].patientrecord.find()
330+
patientrecords = connection["test_other"].encryption__patientrecord.find()
331331
ssn = patientrecords[0]["ssn"]
332332
self.assertTrue(isinstance(ssn, Binary))
333333
connection.close()
@@ -349,25 +349,11 @@ def test_patient(self):
349349
)
350350

351351
# Test decrypted patient record in encrypted database.
352-
patients = connections["other"].database.patient.find()
352+
patients = connections["other"].database.encryption__patient.find()
353353
self.assertEqual(len(list(patients)), 1)
354-
records = connections["other"].database.patientrecord.find()
354+
records = connections["other"].database.encryption__patientrecord.find()
355355
self.assertTrue("__safeContent__" in records[0])
356356

357-
def test_no_auto_encryption_opts(self):
358-
"""
359-
Ensure that the encrypted fields map is not set in the client
360-
when auto_encryption_opts is not set.
361-
"""
362-
Patient.objects.using("default").create(
363-
patient_id=2,
364-
patient_name="John Doe 2",
365-
patient_notes="patient notes " * 20,
366-
registration_date=datetime(2024, 10, 1, 12, 0, 0),
367-
is_active=True,
368-
369-
).save()
370-
371357

372358
class KMSCredentialsTests(TestCase):
373359
def test_env(self):

0 commit comments

Comments
 (0)