|
1 | 1 | import importlib
|
2 | 2 | from datetime import datetime, time
|
3 |
| -from io import StringIO |
4 | 3 | from unittest.mock import patch
|
5 | 4 |
|
6 | 5 | import pymongo
|
7 |
| -from bson import json_util |
8 | 6 | from bson.binary import Binary
|
9 | 7 | from django.conf import settings
|
10 |
| -from django.core.management import call_command |
11 | 8 | from django.db import connections, models
|
12 | 9 | from django.test import TransactionTestCase, modify_settings, override_settings
|
13 | 10 |
|
|
23 | 20 | )
|
24 | 21 | from .routers import TestEncryptedRouter
|
25 | 22 |
|
26 |
| -EXPECTED_ENCRYPTED_FIELDS_MAP = { |
27 |
| - "encryption__billing": { |
28 |
| - "fields": [ |
29 |
| - { |
30 |
| - "bsonType": "string", |
31 |
| - "path": "cc_type", |
32 |
| - "queries": {"queryType": "equality"}, |
33 |
| - # "keyId": Binary(b" \x901\x89\x1f\xafAX\x9b*\xb1\xc7\xc5\xfdl\xa4", 4), |
34 |
| - }, |
35 |
| - { |
36 |
| - "bsonType": "long", |
37 |
| - "path": "cc_number", |
38 |
| - "queries": {"queryType": "equality"}, |
39 |
| - # "keyId": Binary(b"\x97\xb4\x9d\xb8\xd5\xa6Ay\x85\xfe\x00\xc0\xd4{\xa2\xff", 4), |
40 |
| - }, |
41 |
| - { |
42 |
| - "bsonType": "decimal", |
43 |
| - "path": "account_balance", |
44 |
| - "queries": {"queryType": "range"}, |
45 |
| - # "keyId": Binary(b"\xcc\x01-s\xea\xd9B\x8d\x80\xd7\xf8!n\xc6\xf5U", 4), |
46 |
| - }, |
47 |
| - ] |
48 |
| - }, |
49 |
| - "encryption__patientrecord": { |
50 |
| - "fields": [ |
51 |
| - { |
52 |
| - "bsonType": "string", |
53 |
| - "path": "ssn", |
54 |
| - "queries": {"queryType": "equality"}, |
55 |
| - # "keyId": Binary(b"\x14F\x89\xde\x8d\x04K7\xa9\x9a\xaf_\xca\x8a\xfb&", 4), |
56 |
| - }, |
57 |
| - { |
58 |
| - "bsonType": "date", |
59 |
| - "path": "birth_date", |
60 |
| - "queries": {"queryType": "range"}, |
61 |
| - # "keyId": Binary(b"@\xdd\xb4\xd2%\xc2B\x94\xb5\x07\xbc(ER[s", 4), |
62 |
| - }, |
63 |
| - { |
64 |
| - "bsonType": "binData", |
65 |
| - "path": "profile_picture", |
66 |
| - "queries": {"queryType": "equality"}, |
67 |
| - # "keyId": Binary(b"Q\xa2\xebc!\xecD,\x8b\xe4$\xb6ul9\x9a", 4), |
68 |
| - }, |
69 |
| - { |
70 |
| - "bsonType": "int", |
71 |
| - "path": "patient_age", |
72 |
| - "queries": {"queryType": "range"}, |
73 |
| - # "keyId": Binary(b"\ro\x80\x1e\x8e1K\xde\xbc_\xc3bi\x95\xa6j", 4), |
74 |
| - }, |
75 |
| - { |
76 |
| - "bsonType": "double", |
77 |
| - "path": "weight", |
78 |
| - "queries": {"queryType": "range"}, |
79 |
| - # "keyId": Binary(b"\x9b\xfd:n\xe1\xd0N\xdd\xb3\xe7e)\x06\xea\x8a\x1d", 4), |
80 |
| - }, |
81 |
| - ] |
82 |
| - }, |
83 |
| - "encryption__patient": { |
84 |
| - "fields": [ |
85 |
| - { |
86 |
| - "bsonType": "int", |
87 |
| - "path": "patient_id", |
88 |
| - "queries": {"queryType": "equality"}, |
89 |
| - # "keyId": Binary(b"\x8ft\x16:\x8a\x91D\xc7\x8a\xdf\xe5O\n[\xfd\\", 4), |
90 |
| - }, |
91 |
| - { |
92 |
| - "bsonType": "string", |
93 |
| - "path": "patient_name", |
94 |
| - # "keyId": Binary(b"<\x9b\xba\xeb:\xa4@m\x93\x0e\x0c\xcaN\x03\xfb\x05", 4), |
95 |
| - }, |
96 |
| - { |
97 |
| - "bsonType": "string", |
98 |
| - "path": "patient_notes", |
99 |
| - "queries": {"queryType": "equality"}, |
100 |
| - # "keyId": Binary(b"\x01\xe7\xd1isnB$\xa9(gwO\xca\x10\xbd", 4), |
101 |
| - }, |
102 |
| - { |
103 |
| - "bsonType": "date", |
104 |
| - "path": "registration_date", |
105 |
| - "queries": {"queryType": "equality"}, |
106 |
| - # "keyId": Binary(b"F\xfb\xae\x82\xd5\x9a@\xee\xbfJ\xaf#\x9c:-I", 4), |
107 |
| - }, |
108 |
| - { |
109 |
| - "bsonType": "bool", |
110 |
| - "path": "is_active", |
111 |
| - "queries": {"queryType": "equality"}, |
112 |
| - # "keyId": Binary(b"\xb2\xb5\xc4K53A\xda\xb9V\xa6\xa9\x97\x94\xea;", 4), |
113 |
| - }, |
114 |
| - {"bsonType": "string", "path": "email", "queries": {"queryType": "equality"}}, |
115 |
| - ] |
116 |
| - }, |
117 |
| - "encryption__patientportaluser": { |
118 |
| - "fields": [ |
119 |
| - {"bsonType": "string", "path": "ip_address", "queries": {"queryType": "equality"}}, |
120 |
| - {"bsonType": "string", "path": "url", "queries": {"queryType": "equality"}}, |
121 |
| - ] |
122 |
| - }, |
123 |
| - "encryption__encryptednumbers": { |
124 |
| - "fields": [ |
125 |
| - {"bsonType": "int", "path": "pos_bigint", "queries": {"queryType": "equality"}}, |
126 |
| - {"bsonType": "int", "path": "pos_smallint", "queries": {"queryType": "equality"}}, |
127 |
| - {"bsonType": "int", "path": "smallint", "queries": {"queryType": "equality"}}, |
128 |
| - ] |
129 |
| - }, |
130 |
| - "encryption__appointment": { |
131 |
| - "fields": [{"bsonType": "date", "path": "time", "queries": {"queryType": "equality"}}] |
132 |
| - }, |
133 |
| -} |
134 |
| - |
135 | 23 |
|
136 | 24 | class EncryptedDurationField(EncryptedFieldMixin, models.DurationField):
|
137 | 25 | """
|
@@ -166,38 +54,36 @@ class EncryptedFieldTests(TransactionTestCase):
|
166 | 54 | available_apps = ["django_mongodb_backend", "encryption_"]
|
167 | 55 |
|
168 | 56 | def setUp(self):
|
169 |
| - self.appointment = Appointment(time="8:00") |
170 |
| - self.appointment.save() |
| 57 | + self.appointment = Appointment.objects.create(time="8:00") |
171 | 58 |
|
172 |
| - self.billing = Billing(cc_type="Visa", cc_number=1234567890123456, account_balance=100.50) |
173 |
| - self.billing.save() |
| 59 | + self.billing = Billing.objects.create( |
| 60 | + cc_type="Visa", cc_number=1234567890123456, account_balance=100.50 |
| 61 | + ) |
174 | 62 |
|
175 |
| - self.portal_user = PatientPortalUser( |
| 63 | + self.portal_user = PatientPortalUser.objects.create( |
176 | 64 | ip_address="127.0.0.1",
|
177 | 65 | url="https://example.com",
|
178 | 66 | )
|
179 |
| - self.portal_user.save() |
180 | 67 |
|
181 |
| - self.patientrecord = PatientRecord( |
| 68 | + self.patientrecord = PatientRecord.objects.create( |
182 | 69 | ssn="123-45-6789",
|
183 | 70 | birth_date="1970-01-01",
|
184 | 71 | profile_picture=b"image data",
|
185 | 72 | weight=175.5,
|
186 | 73 | patient_age=47,
|
187 | 74 | )
|
188 |
| - self.patientrecord.save() |
189 | 75 |
|
190 |
| - self.patient = Patient( |
| 76 | + self.patient = Patient.objects.create( |
191 | 77 | patient_id=1,
|
192 | 78 | patient_name="John Doe",
|
193 | 79 | patient_notes="patient notes " * 25,
|
194 | 80 | registration_date=datetime(2023, 10, 1, 12, 0, 0),
|
195 | 81 | is_active=True,
|
196 | 82 |
|
197 | 83 | )
|
198 |
| - self.patient.save() |
199 | 84 |
|
200 |
| - # TODO: Embed billing and patient_record models in patient model then add tests |
| 85 | + # TODO: Embed billing and patient_record models in patient model |
| 86 | + # then add tests |
201 | 87 |
|
202 | 88 | @classmethod
|
203 | 89 | def setUpClass(cls):
|
@@ -284,25 +170,6 @@ def test_get_encrypted_fields_map(self):
|
284 | 170 | expected_encrypted_fields_map[db_table],
|
285 | 171 | )
|
286 | 172 |
|
287 |
| - def test_show_schema_map(self): |
288 |
| - self.maxDiff = None |
289 |
| - out = StringIO() |
290 |
| - call_command( |
291 |
| - "showschemamap", |
292 |
| - "--database", |
293 |
| - "encrypted", |
294 |
| - verbosity=0, |
295 |
| - stdout=out, |
296 |
| - ) |
297 |
| - # Remove keyIds since they are different for each run. |
298 |
| - output_json = json_util.loads(out.getvalue()) |
299 |
| - for table in output_json: |
300 |
| - for field in output_json[table]["fields"]: |
301 |
| - del field["keyId"] |
302 |
| - # TODO: probably we don't need to test the entire mapping, otherwise it |
303 |
| - # requires updates every time a new model or field is added! |
304 |
| - self.assertEqual(EXPECTED_ENCRYPTED_FIELDS_MAP, output_json) |
305 |
| - |
306 | 173 | def test_set_encrypted_fields_map_in_client(self):
|
307 | 174 | # TODO: Create new client with and without schema map provided then
|
308 | 175 | # sync database to ensure encrypted collections are created in both
|
@@ -373,9 +240,10 @@ def test_patient(self):
|
373 | 240 | records = connections["encrypted"].database.encryption__patientrecord.find()
|
374 | 241 | self.assertTrue("__safeContent__" in records[0])
|
375 | 242 |
|
376 |
| - |
377 |
| -class EncryptedNumberFieldTests(EncryptedFieldTests): |
378 |
| - def test_create_and_query(self): |
| 243 | + def test_numeric_fields(self): |
| 244 | + """ |
| 245 | + Fields that have not been tested elsewhere. |
| 246 | + """ |
379 | 247 | EncryptedNumbers.objects.create(
|
380 | 248 | pos_bigint=1000000,
|
381 | 249 | # FIXME: pymongo.errors.EncryptionError: Cannot encrypt element of type int
|
|
0 commit comments