11import datetime
22from decimal import Decimal
33
4+ import pymongo
5+ from bson .binary import Binary
6+ from django .conf import settings
7+ from django .db import connections
8+
49from django_mongodb_backend .fields import EncryptedCharField
510
611from .models import (
3237from .test_base import EncryptionTestCase
3338
3439
35- class EncryptedEmbeddedModelTests (EncryptionTestCase ):
40+ class EncryptedFieldTests (EncryptionTestCase ):
41+ def assertEncrypted (self , model_instance , field_name ):
42+ """Check if the field value in the database is stored as Binary."""
43+ conn_params = connections ["encrypted" ].get_connection_params ()
44+ db_name = settings .DATABASES ["encrypted" ]["NAME" ]
45+
46+ if conn_params .pop ("auto_encryption_opts" , False ):
47+ with pymongo .MongoClient (** conn_params ) as new_connection :
48+ collection_name = model_instance ._meta .db_table
49+ collection = new_connection [db_name ][collection_name ]
50+ docs = collection .find ({field_name : {"$exists" : True }})
51+ for doc in docs :
52+ value = doc .get (field_name )
53+ if not isinstance (value , Binary ):
54+ return False
55+ return True
56+ return False
57+
58+
59+ class EncryptedEmbeddedModelTests (EncryptedFieldTests ):
3660 def setUp (self ):
3761 self .billing = Billing (cc_type = "Visa" , cc_number = "4111111111111111" )
3862 self .patient_record = PatientRecord (ssn = "123-45-6789" , billing = self .billing )
3963 self .patient = Patient .objects .create (
4064 patient_name = "John Doe" , patient_id = 123456789 , patient_record = self .patient_record
4165 )
4266
43- def test_patient (self ):
67+ def test_object (self ):
4468 patient = Patient .objects .get (id = self .patient .id )
4569 self .assertEqual (patient .patient_record .ssn , "123-45-6789" )
4670 self .assertEqual (patient .patient_record .billing .cc_type , "Visa" )
4771 self .assertEqual (patient .patient_record .billing .cc_number , "4111111111111111" )
4872
4973
50- class EncryptedEmbeddedModelArrayTests (EncryptionTestCase ):
74+ class EncryptedEmbeddedModelArrayTests (EncryptedFieldTests ):
5175 def setUp (self ):
5276 self .actor1 = Actor (name = "Actor One" )
5377 self .actor2 = Actor (name = "Actor Two" )
@@ -56,13 +80,14 @@ def setUp(self):
5680 cast = [self .actor1 , self .actor2 ],
5781 )
5882
59- def test_movie_actors (self ):
83+ def test_array (self ):
6084 self .assertEqual (len (self .movie .cast ), 2 )
6185 self .assertEqual (self .movie .cast [0 ].name , "Actor One" )
6286 self .assertEqual (self .movie .cast [1 ].name , "Actor Two" )
87+ self .assertEncrypted (self .movie , "cast" )
6388
6489
65- class EncryptedFieldTests (EncryptionTestCase ):
90+ class EncryptedFieldTests (EncryptedFieldTests ):
6691 def assertEquality (self , model_cls , val ):
6792 model_cls .objects .create (value = val )
6893 fetched = model_cls .objects .get (value = val )
@@ -80,28 +105,36 @@ def assertRange(self, model_cls, *, low, high, threshold):
80105 # Equality-only fields
81106 def test_binary (self ):
82107 self .assertEquality (BinaryModel , b"\x00 \x01 \x02 " )
108+ self .assertEncrypted (BinaryModel , "value" )
83109
84110 def test_boolean (self ):
85111 self .assertEquality (BooleanModel , True )
112+ self .assertEncrypted (BooleanModel , "value" )
86113
87114 def test_char (self ):
88115 self .assertEquality (CharModel , "hello" )
116+ self .assertEncrypted (CharModel , "value" )
89117
90118 def test_email (self ):
91119 self .assertEquality (EmailModel , "test@example.com" )
120+ self .assertEncrypted (EmailModel , "value" )
92121
93122 def test_ip (self ):
94123 self .assertEquality (GenericIPAddressModel , "192.168.0.1" )
124+ self .assertEncrypted (GenericIPAddressModel , "value" )
95125
96126 def test_text (self ):
97127 self .assertEquality (TextModel , "some text" )
128+ self .assertEncrypted (TextModel , "value" )
98129
99130 def test_url (self ):
100131 self .assertEquality (URLModel , "https://example.com" )
132+ self .assertEncrypted (URLModel , "value" )
101133
102134 # Range fields
103135 def test_big_integer (self ):
104136 self .assertRange (BigIntegerModel , low = 100 , high = 200 , threshold = 150 )
137+ self .assertEncrypted (BigIntegerModel , "value" )
105138
106139 def test_date (self ):
107140 self .assertRange (
@@ -110,6 +143,7 @@ def test_date(self):
110143 high = datetime .date (2024 , 6 , 10 ),
111144 threshold = datetime .date (2024 , 6 , 5 ),
112145 )
146+ self .assertEncrypted (DateModel , "value" )
113147
114148 def test_datetime (self ):
115149 self .assertRange (
@@ -118,6 +152,7 @@ def test_datetime(self):
118152 high = datetime .datetime (2024 , 6 , 2 , 12 , 0 ),
119153 threshold = datetime .datetime (2024 , 6 , 2 , 0 , 0 ),
120154 )
155+ self .assertEncrypted (DateTimeModel , "value" )
121156
122157 def test_decimal (self ):
123158 self .assertRange (
@@ -126,6 +161,7 @@ def test_decimal(self):
126161 high = Decimal ("200.50" ),
127162 threshold = Decimal ("150" ),
128163 )
164+ self .assertEncrypted (DecimalModel , "value" )
129165
130166 def test_duration (self ):
131167 self .assertRange (
@@ -134,24 +170,31 @@ def test_duration(self):
134170 high = datetime .timedelta (days = 10 ),
135171 threshold = datetime .timedelta (days = 5 ),
136172 )
173+ self .assertEncrypted (DurationModel , "value" )
137174
138175 def test_float (self ):
139176 self .assertRange (FloatModel , low = 1.23 , high = 4.56 , threshold = 3.0 )
177+ self .assertEncrypted (FloatModel , "value" )
140178
141179 def test_integer (self ):
142180 self .assertRange (IntegerModel , low = 5 , high = 10 , threshold = 7 )
181+ self .assertEncrypted (IntegerModel , "value" )
143182
144183 def test_positive_big_integer (self ):
145184 self .assertRange (PositiveBigIntegerModel , low = 100 , high = 500 , threshold = 200 )
185+ self .assertEncrypted (PositiveBigIntegerModel , "value" )
146186
147187 def test_positive_integer (self ):
148188 self .assertRange (PositiveIntegerModel , low = 10 , high = 20 , threshold = 15 )
189+ self .assertEncrypted (PositiveIntegerModel , "value" )
149190
150191 def test_positive_small_integer (self ):
151192 self .assertRange (PositiveSmallIntegerModel , low = 5 , high = 8 , threshold = 6 )
193+ self .assertEncrypted (PositiveSmallIntegerModel , "value" )
152194
153195 def test_small_integer (self ):
154196 self .assertRange (SmallIntegerModel , low = - 5 , high = 2 , threshold = 0 )
197+ self .assertEncrypted (SmallIntegerModel , "value" )
155198
156199 def test_time (self ):
157200 self .assertRange (
@@ -160,9 +203,10 @@ def test_time(self):
160203 high = datetime .time (15 , 0 ),
161204 threshold = datetime .time (12 , 0 ),
162205 )
206+ self .assertEncrypted (TimeModel , "value" )
163207
164208
165- class EncryptedFieldMixinTests (EncryptionTestCase ):
209+ class EncryptedFieldMixinTests (EncryptedFieldTests ):
166210 def test_null_true_raises_error (self ):
167211 with self .assertRaisesMessage (
168212 ValueError , "'null=True' is not supported for encrypted fields."
0 commit comments