Skip to content

Commit 35abf00

Browse files
committed
feat: add EncryptedJSONField
1 parent b7f56a0 commit 35abf00

File tree

5 files changed

+49
-1
lines changed

5 files changed

+49
-1
lines changed

mirage/fields.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import json
12
from django.core import exceptions
23
from django.db import models
34
from .crypto import Crypto
45
from .exceptions import EncryptedFieldException
6+
from django.db.models.fields.json import KeyTransform
57

68

79
class EncryptedMixin(models.Field):
@@ -36,6 +38,24 @@ def get_internal_type(self):
3638
class EncryptedTextField(EncryptedMixin, models.TextField):
3739
internal_type = "TextField"
3840

41+
class EncryptedJSONField(EncryptedMixin, models.JSONField):
42+
internal_type = "TextField"
43+
44+
def from_db_value(self, value, expression, connection):
45+
if value is None:
46+
return value
47+
if isinstance(expression, KeyTransform) and not isinstance(value, str):
48+
return value
49+
try:
50+
return json.loads(self.crypto.decrypt(value), cls=self.decoder)
51+
except json.JSONDecodeError as e:
52+
return self.crypto.decrypt(value)
53+
54+
def get_prep_value(self, value):
55+
if value is None:
56+
return value
57+
return json.dumps(self.crypto.encrypt(json.dumps(value, cls=self.encoder)), cls=self.encoder)
58+
3959

4060
class EncryptedCharField(EncryptedMixin, models.CharField):
4161
prepared_max_length = 255

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
88
setup(
99
name='django-mirage-field',
10-
version='1.3.0',
10+
version='1.4.0',
1111
install_requires=[
1212
"cryptography",
1313
"tqdm",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 4.0 on 2022-03-14 02:41
2+
3+
from django.db import migrations
4+
import mirage.fields
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('apps', '0003_testmodel_url'),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name='testmodel',
16+
name='json',
17+
field=mirage.fields.EncryptedJSONField(default={}),
18+
),
19+
]

tests/apps/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from email.policy import default
12
from django.db import models
23
from mirage import fields
34

@@ -9,3 +10,4 @@ class TestModel(models.Model):
910
integer = fields.EncryptedIntegerField(blank=True, null=True)
1011
email = fields.EncryptedEmailField(blank=True, null=True)
1112
url = fields.EncryptedURLField(blank=True, null=True)
13+
json = fields.EncryptedJSONField(default={})

tests/test_field.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
from django.test import TestCase
23
from apps.models import TestModel
34

@@ -8,6 +9,7 @@ class TestField(TestCase):
89
INTEGER = 1234567890
910
1011
URL = 'https://yindongliang.com'
12+
JSON = {"hello": "world", "foo": "bar"}
1113

1214
@classmethod
1315
def setUpTestData(cls):
@@ -17,6 +19,7 @@ def setUpTestData(cls):
1719
obj.integer = cls.INTEGER
1820
obj.email = cls.EMAIL
1921
obj.url = cls.URL
22+
obj.json = cls.JSON
2023
obj.save()
2124

2225
def setUp(self):
@@ -41,3 +44,7 @@ def test_email_field(self):
4144
def test_url_field(self):
4245
self.assertEqual(self.obj.url, self.URL)
4346
self.assertEqual(type(self.obj.url), str)
47+
48+
def test_json_field(self):
49+
self.assertEqual(self.obj.json, self.JSON)
50+
self.assertEqual(type(self.obj.json), dict)

0 commit comments

Comments
 (0)