1
1
import datetime
2
2
from decimal import Decimal
3
3
4
+ import pymongo
5
+ from bson .binary import Binary
6
+ from django .conf import settings
7
+ from django .db import connections
8
+
4
9
from django_mongodb_backend .fields import EncryptedCharField
5
10
6
11
from .models import (
32
37
from .test_base import EncryptionTestCase
33
38
34
39
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 ):
36
60
def setUp (self ):
37
61
self .billing = Billing (cc_type = "Visa" , cc_number = "4111111111111111" )
38
62
self .patient_record = PatientRecord (ssn = "123-45-6789" , billing = self .billing )
39
63
self .patient = Patient .objects .create (
40
64
patient_name = "John Doe" , patient_id = 123456789 , patient_record = self .patient_record
41
65
)
42
66
43
- def test_patient (self ):
67
+ def test_object (self ):
44
68
patient = Patient .objects .get (id = self .patient .id )
45
69
self .assertEqual (patient .patient_record .ssn , "123-45-6789" )
46
70
self .assertEqual (patient .patient_record .billing .cc_type , "Visa" )
47
71
self .assertEqual (patient .patient_record .billing .cc_number , "4111111111111111" )
48
72
49
73
50
- class EncryptedEmbeddedModelArrayTests (EncryptionTestCase ):
74
+ class EncryptedEmbeddedModelArrayTests (EncryptedFieldTests ):
51
75
def setUp (self ):
52
76
self .actor1 = Actor (name = "Actor One" )
53
77
self .actor2 = Actor (name = "Actor Two" )
@@ -56,13 +80,14 @@ def setUp(self):
56
80
cast = [self .actor1 , self .actor2 ],
57
81
)
58
82
59
- def test_movie_actors (self ):
83
+ def test_array (self ):
60
84
self .assertEqual (len (self .movie .cast ), 2 )
61
85
self .assertEqual (self .movie .cast [0 ].name , "Actor One" )
62
86
self .assertEqual (self .movie .cast [1 ].name , "Actor Two" )
87
+ self .assertEncrypted (self .movie , "cast" )
63
88
64
89
65
- class EncryptedFieldTests (EncryptionTestCase ):
90
+ class EncryptedFieldTests (EncryptedFieldTests ):
66
91
def assertEquality (self , model_cls , val ):
67
92
model_cls .objects .create (value = val )
68
93
fetched = model_cls .objects .get (value = val )
@@ -80,28 +105,36 @@ def assertRange(self, model_cls, *, low, high, threshold):
80
105
# Equality-only fields
81
106
def test_binary (self ):
82
107
self .assertEquality (BinaryModel , b"\x00 \x01 \x02 " )
108
+ self .assertEncrypted (BinaryModel , "value" )
83
109
84
110
def test_boolean (self ):
85
111
self .assertEquality (BooleanModel , True )
112
+ self .assertEncrypted (BooleanModel , "value" )
86
113
87
114
def test_char (self ):
88
115
self .assertEquality (CharModel , "hello" )
116
+ self .assertEncrypted (CharModel , "value" )
89
117
90
118
def test_email (self ):
91
119
self .
assertEquality (
EmailModel ,
"[email protected] " )
120
+ self .assertEncrypted (EmailModel , "value" )
92
121
93
122
def test_ip (self ):
94
123
self .assertEquality (GenericIPAddressModel , "192.168.0.1" )
124
+ self .assertEncrypted (GenericIPAddressModel , "value" )
95
125
96
126
def test_text (self ):
97
127
self .assertEquality (TextModel , "some text" )
128
+ self .assertEncrypted (TextModel , "value" )
98
129
99
130
def test_url (self ):
100
131
self .assertEquality (URLModel , "https://example.com" )
132
+ self .assertEncrypted (URLModel , "value" )
101
133
102
134
# Range fields
103
135
def test_big_integer (self ):
104
136
self .assertRange (BigIntegerModel , low = 100 , high = 200 , threshold = 150 )
137
+ self .assertEncrypted (BigIntegerModel , "value" )
105
138
106
139
def test_date (self ):
107
140
self .assertRange (
@@ -110,6 +143,7 @@ def test_date(self):
110
143
high = datetime .date (2024 , 6 , 10 ),
111
144
threshold = datetime .date (2024 , 6 , 5 ),
112
145
)
146
+ self .assertEncrypted (DateModel , "value" )
113
147
114
148
def test_datetime (self ):
115
149
self .assertRange (
@@ -118,6 +152,7 @@ def test_datetime(self):
118
152
high = datetime .datetime (2024 , 6 , 2 , 12 , 0 ),
119
153
threshold = datetime .datetime (2024 , 6 , 2 , 0 , 0 ),
120
154
)
155
+ self .assertEncrypted (DateTimeModel , "value" )
121
156
122
157
def test_decimal (self ):
123
158
self .assertRange (
@@ -126,6 +161,7 @@ def test_decimal(self):
126
161
high = Decimal ("200.50" ),
127
162
threshold = Decimal ("150" ),
128
163
)
164
+ self .assertEncrypted (DecimalModel , "value" )
129
165
130
166
def test_duration (self ):
131
167
self .assertRange (
@@ -134,24 +170,31 @@ def test_duration(self):
134
170
high = datetime .timedelta (days = 10 ),
135
171
threshold = datetime .timedelta (days = 5 ),
136
172
)
173
+ self .assertEncrypted (DurationModel , "value" )
137
174
138
175
def test_float (self ):
139
176
self .assertRange (FloatModel , low = 1.23 , high = 4.56 , threshold = 3.0 )
177
+ self .assertEncrypted (FloatModel , "value" )
140
178
141
179
def test_integer (self ):
142
180
self .assertRange (IntegerModel , low = 5 , high = 10 , threshold = 7 )
181
+ self .assertEncrypted (IntegerModel , "value" )
143
182
144
183
def test_positive_big_integer (self ):
145
184
self .assertRange (PositiveBigIntegerModel , low = 100 , high = 500 , threshold = 200 )
185
+ self .assertEncrypted (PositiveBigIntegerModel , "value" )
146
186
147
187
def test_positive_integer (self ):
148
188
self .assertRange (PositiveIntegerModel , low = 10 , high = 20 , threshold = 15 )
189
+ self .assertEncrypted (PositiveIntegerModel , "value" )
149
190
150
191
def test_positive_small_integer (self ):
151
192
self .assertRange (PositiveSmallIntegerModel , low = 5 , high = 8 , threshold = 6 )
193
+ self .assertEncrypted (PositiveSmallIntegerModel , "value" )
152
194
153
195
def test_small_integer (self ):
154
196
self .assertRange (SmallIntegerModel , low = - 5 , high = 2 , threshold = 0 )
197
+ self .assertEncrypted (SmallIntegerModel , "value" )
155
198
156
199
def test_time (self ):
157
200
self .assertRange (
@@ -160,9 +203,10 @@ def test_time(self):
160
203
high = datetime .time (15 , 0 ),
161
204
threshold = datetime .time (12 , 0 ),
162
205
)
206
+ self .assertEncrypted (TimeModel , "value" )
163
207
164
208
165
- class EncryptedFieldMixinTests (EncryptionTestCase ):
209
+ class EncryptedFieldMixinTests (EncryptedFieldTests ):
166
210
def test_null_true_raises_error (self ):
167
211
with self .assertRaisesMessage (
168
212
ValueError , "'null=True' is not supported for encrypted fields."
0 commit comments