Skip to content

Commit 81cc887

Browse files
committed
Add query type classes and update test
Rather than require users to add JSON to their field definitions let's provide a Python API via QueryTypes class that outputs JSON with values provided in field definition. E.g. query_types = QueryTypes() query_types.equality.contention = 1 queries = [query_types.equality]
1 parent b2a0534 commit 81cc887

File tree

4 files changed

+65
-5
lines changed

4 files changed

+65
-5
lines changed

django_mongodb_backend/encryption.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,58 @@
1212
KMS_PROVIDER = "local" # e.g., "aws", "azure", "gcp", "kmip", or "local"
1313

1414

15+
class EqualityQuery:
16+
"""
17+
Represents an encrypted equality query for encrypted fields in MongoDB's
18+
Queryable Encryption.
19+
"""
20+
21+
def __init__(self, contention=None):
22+
self.queryType = "equality"
23+
self.contention = contention
24+
25+
def to_dict(self):
26+
query_type = {"queryType": self.queryType}
27+
if self.contention is not None:
28+
query_type["contention"] = self.contention
29+
return [query_type]
30+
31+
32+
class RangeQuery:
33+
"""Represents an encrypted range query configuration for encrypted fields in
34+
MongoDB's Queryable Encryption.
35+
"""
36+
37+
def __init__(self, sparsity=None, precision=None, trimFactor=None):
38+
self.queryType = "range"
39+
self.sparsity = sparsity
40+
self.precision = precision
41+
self.trimFactor = trimFactor
42+
43+
def to_dict(self):
44+
query_type = {"queryType": self.queryType}
45+
if self.sparsity is not None:
46+
query_type["sparsity"] = self.sparsity
47+
if self.precision is not None:
48+
query_type["precision"] = self.precision
49+
if self.trimFactor is not None:
50+
query_type["trimFactor"] = self.trimFactor
51+
return query_type
52+
53+
54+
class QueryTypes:
55+
"""
56+
Factory class for creating query type configurations for
57+
MongoDB Queryable Encryption.
58+
"""
59+
60+
def equality(self, *, contention=None):
61+
return EqualityQuery(contention=contention)
62+
63+
def range(self, *, sparsity=None, precision=None, trimFactor=None):
64+
return RangeQuery(sparsity=sparsity, precision=precision, trimFactor=trimFactor)
65+
66+
1567
def get_auto_encryption_opts(
1668
key_vault_namespace=None, crypt_shared_lib_path=None, kms_providers=None
1769
):

django_mongodb_backend/schema.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -446,15 +446,14 @@ def _create_collection(self, model):
446446
def _get_encrypted_fields_map(self, model):
447447
conn = self.connection
448448
fields = model._meta.fields
449+
449450
return {
450451
"fields": [
451452
{
452453
"path": field.column,
453454
"bsonType": field.db_type(conn),
454-
# Specify queries in the field definition as a list of query
455-
# types e.g. queries=["equality", "range"]
456455
**(
457-
{"queries": [{"queryType": query} for query in field.queries]}
456+
{"queries": field.queries[0].to_dict()}
458457
if getattr(field, "queries", None)
459458
else {}
460459
),

tests/encryption_/models.py

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

3+
from django_mongodb_backend.encryption import QueryTypes
34
from django_mongodb_backend.fields import EncryptedCharField
45
from django_mongodb_backend.models import EncryptedModel
56

7+
# Query types for encrypted fields with optional parameters
8+
query_types = QueryTypes()
9+
queries = [query_types.equality(contention=1), query_types.range(sparsity=2, precision=3)]
10+
611

712
class Person(EncryptedModel):
813
name = models.CharField("name", max_length=100)
9-
ssn = EncryptedCharField("ssn", max_length=11, queries=["equality"])
14+
ssn = EncryptedCharField("ssn", max_length=11, queries=queries)
1015

1116
class Meta:
1217
required_db_features = {"supports_queryable_encryption"}

tests/encryption_/tests.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ def test_encrypted_fields_map(self):
1515
""" """
1616
expected = {
1717
"fields": [
18-
{"path": "ssn", "bsonType": "string", "queries": [{"queryType": "equality"}]}
18+
{
19+
"path": "ssn",
20+
"bsonType": "string",
21+
"queries": [{"contention": 1, "queryType": "equality"}],
22+
}
1923
]
2024
}
2125
with connection.schema_editor() as editor:

0 commit comments

Comments
 (0)