Skip to content

Commit 9740656

Browse files
committed
Add fields and corresponding tests
- EncryptedArrayField - EncryptedObjectIdField - EncryptedUUIDField
1 parent 3c55716 commit 9740656

File tree

6 files changed

+74
-11
lines changed

6 files changed

+74
-11
lines changed

.github/workflows/mongodb_settings.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434

3535

3636
class EncryptedRouter:
37+
# def db_for_read(self, model, **hints):
38+
# if model_has_encrypted_fields(model):
39+
# return "encrypted"
40+
# return "default"
41+
# db_for_write = db_for_read
42+
3743
def allow_migrate(self, db, app_label, model_name=None, **hints):
3844
# The encryption_ app's models are only created in the encrypted
3945
# database.

django_mongodb_backend/features.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ def _supports_transactions(self):
639639
@cached_property
640640
def supports_queryable_encryption(self):
641641
"""
642-
Queryable Encryption requires a MongoDB 7.0 or later replica set or sharded
642+
Queryable Encryption requires a MongoDB 8.0 or later replica set or sharded
643643
cluster, as well as MongoDB Atlas or Enterprise.
644644
"""
645645
self.connection.ensure_connection()

django_mongodb_backend/fields/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .embedded_model import EmbeddedModelField
55
from .embedded_model_array import EmbeddedModelArrayField
66
from .encryption import (
7+
EncryptedArrayField,
78
EncryptedBigIntegerField,
89
EncryptedBinaryField,
910
EncryptedBooleanField,
@@ -19,13 +20,15 @@
1920
EncryptedFloatField,
2021
EncryptedGenericIPAddressField,
2122
EncryptedIntegerField,
23+
EncryptedObjectIdField,
2224
EncryptedPositiveBigIntegerField,
2325
EncryptedPositiveIntegerField,
2426
EncryptedPositiveSmallIntegerField,
2527
EncryptedSmallIntegerField,
2628
EncryptedTextField,
2729
EncryptedTimeField,
2830
EncryptedURLField,
31+
EncryptedUUIDField,
2932
)
3033
from .json import register_json_field
3134
from .objectid import ObjectIdField
@@ -36,6 +39,7 @@
3639
"ArrayField",
3740
"EmbeddedModelArrayField",
3841
"EmbeddedModelField",
42+
"EncryptedArrayField",
3943
"EncryptedBigIntegerField",
4044
"EncryptedBinaryField",
4145
"EncryptedBooleanField",
@@ -51,13 +55,15 @@
5155
"EncryptedFloatField",
5256
"EncryptedGenericIPAddressField",
5357
"EncryptedIntegerField",
58+
"EncryptedObjectIdField",
5459
"EncryptedPositiveBigIntegerField",
5560
"EncryptedPositiveIntegerField",
5661
"EncryptedPositiveSmallIntegerField",
5762
"EncryptedSmallIntegerField",
5863
"EncryptedTextField",
5964
"EncryptedTimeField",
6065
"EncryptedURLField",
66+
"EncryptedUUIDField",
6167
"ObjectIdAutoField",
6268
"ObjectIdField",
6369
"PolymorphicEmbeddedModelArrayField",

django_mongodb_backend/fields/encryption.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
from django.db import models
22

3-
from django_mongodb_backend.fields import EmbeddedModelArrayField, EmbeddedModelField
3+
from django_mongodb_backend.fields import ArrayField, EmbeddedModelArrayField, EmbeddedModelField
4+
from django_mongodb_backend.fields.objectid import ObjectIdField
5+
6+
7+
class EncryptedArrayField(ArrayField):
8+
encrypted = True
49

510

611
class EncryptedEmbeddedModelArrayField(EmbeddedModelArrayField):
@@ -83,6 +88,10 @@ class EncryptedIntegerField(EncryptedFieldMixin, models.IntegerField):
8388
pass
8489

8590

91+
class EncryptedObjectIdField(EncryptedFieldMixin, ObjectIdField):
92+
pass
93+
94+
8695
class EncryptedPositiveBigIntegerField(EncryptedFieldMixin, models.PositiveBigIntegerField):
8796
pass
8897

@@ -109,3 +118,7 @@ class EncryptedTimeField(EncryptedFieldMixin, models.TimeField):
109118

110119
class EncryptedURLField(EncryptedFieldMixin, models.URLField):
111120
pass
121+
122+
123+
class EncryptedUUIDField(EncryptedFieldMixin, models.UUIDField):
124+
pass

tests/encryption_/models.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django_mongodb_backend.fields import (
44
EmbeddedModelField,
5+
EncryptedArrayField,
56
EncryptedBigIntegerField,
67
EncryptedBinaryField,
78
EncryptedBooleanField,
@@ -16,13 +17,15 @@
1617
EncryptedFloatField,
1718
EncryptedGenericIPAddressField,
1819
EncryptedIntegerField,
20+
EncryptedObjectIdField,
1921
EncryptedPositiveBigIntegerField,
2022
EncryptedPositiveIntegerField,
2123
EncryptedPositiveSmallIntegerField,
2224
EncryptedSmallIntegerField,
2325
EncryptedTextField,
2426
EncryptedTimeField,
2527
EncryptedURLField,
28+
EncryptedUUIDField,
2629
)
2730
from django_mongodb_backend.models import EmbeddedModel
2831

@@ -33,6 +36,14 @@ class Meta:
3336
required_db_features = {"supports_queryable_encryption"}
3437

3538

39+
# Array models
40+
class ArrayModel(EncryptedTestModel):
41+
values = EncryptedArrayField(
42+
models.IntegerField(),
43+
size=5,
44+
)
45+
46+
3647
# Embedded models
3748
class Patient(EncryptedTestModel):
3849
patient_name = models.CharField(max_length=255)
@@ -91,6 +102,10 @@ class GenericIPAddressModel(EncryptedTestModel):
91102
value = EncryptedGenericIPAddressField(queries={"queryType": "equality"})
92103

93104

105+
class ObjectIdModel(EncryptedTestModel):
106+
value = EncryptedObjectIdField(queries={"queryType": "equality"})
107+
108+
94109
class TextModel(EncryptedTestModel):
95110
value = EncryptedTextField(queries={"queryType": "equality"})
96111

@@ -99,6 +114,10 @@ class URLModel(EncryptedTestModel):
99114
value = EncryptedURLField(max_length=500, queries={"queryType": "equality"})
100115

101116

117+
class UUIDModel(EncryptedTestModel):
118+
value = EncryptedUUIDField(queries={"queryType": "equality"})
119+
120+
102121
# Range-queryable field models
103122
class BigIntegerModel(EncryptedTestModel):
104123
value = EncryptedBigIntegerField(queries={"queryType": "range"})

tests/encryption_/test_fields.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import datetime
2+
import uuid
23
from decimal import Decimal
34

5+
from bson import ObjectId
6+
47
from django_mongodb_backend.fields import EncryptedCharField
58

69
from .models import (
710
Actor,
11+
ArrayModel,
812
BigIntegerModel,
913
Billing,
1014
BinaryModel,
@@ -19,6 +23,7 @@
1923
GenericIPAddressModel,
2024
IntegerModel,
2125
Movie,
26+
ObjectIdModel,
2227
Patient,
2328
PatientRecord,
2429
PositiveBigIntegerModel,
@@ -28,10 +33,21 @@
2833
TextModel,
2934
TimeModel,
3035
URLModel,
36+
UUIDModel,
3137
)
3238
from .test_base import EncryptionTestCase
3339

3440

41+
class ArrayModelTests(EncryptionTestCase):
42+
def setUp(self):
43+
self.array_model = ArrayModel.objects.create(values=[1, 2, 3, 4, 5])
44+
45+
def test_array(self):
46+
array_model = ArrayModel.objects.get(id=self.array_model.id)
47+
self.assertEqual(array_model.values, [1, 2, 3, 4, 5])
48+
# self.assertEncrypted(self.array_model, "values")
49+
50+
3551
class EmbeddedModelTests(EncryptionTestCase):
3652
def setUp(self):
3753
self.billing = Billing(cc_type="Visa", cc_number="4111111111111111")
@@ -61,15 +77,6 @@ def test_array(self):
6177
self.assertEqual(len(movie.cast), 2)
6278
self.assertEqual(movie.cast[0].name, "Actor One")
6379
self.assertEqual(movie.cast[1].name, "Actor Two")
64-
65-
# ======================================================================
66-
# ERROR: test_array (encryption_.test_fields.EmbeddedModelArrayTests.test_array)
67-
# ----------------------------------------------------------------------
68-
# Traceback (most recent call last):
69-
# …
70-
# self.assertIsInstance(data[field], Binary)
71-
# ~~~~^^^^^^^
72-
# TypeError: 'NoneType' object is not subscriptable
7380
# self.assertEncrypted(self.movie, "cast")
7481

7582

@@ -104,6 +111,9 @@ def test_email(self):
104111
def test_ip(self):
105112
self.assertEquality(GenericIPAddressModel, "192.168.0.1")
106113

114+
def test_objectid(self):
115+
self.assertEquality(ObjectIdModel, ObjectId())
116+
107117
def test_text(self):
108118
self.assertEquality(TextModel, "some text")
109119

@@ -205,3 +215,12 @@ def test_deconstruct_preserves_queries_and_rewrites_path(self):
205215
self.assertEqual(new_field.queries, field.queries)
206216
self.assertIsNot(new_field, field)
207217
self.assertEqual(new_field.max_length, field.max_length)
218+
219+
220+
class UUIDFieldTests(EncryptionTestCase):
221+
def test_uuid_field(self):
222+
test_uuid = uuid.uuid4()
223+
UUIDModel.objects.create(value=test_uuid)
224+
fetched = UUIDModel.objects.get(value=test_uuid)
225+
self.assertEqual(fetched.value, test_uuid)
226+
# self.assertEncrypted(fetched, "value")

0 commit comments

Comments
 (0)