Hey there, I have my own custom encrypted JSON that looks like this:
class EncryptedJSONField(models.JSONField):
def to_python(self, value):
return value
def get_db_prep_save(self, value, connection):
value = super().get_db_prep_value(value, connection, prepared=False)
if value is None:
return value
parsed_value = json.loads(value)
for key in parsed_value:
parsed_value[key] = signing.dumps(parsed_value[key])
return json.dumps(parsed_value)
def from_db_value(self, value, *args, **kwargs):
if value is None:
return value
parsed_value = json.loads(value)
for key in parsed_value:
parsed_value[key] = decrypt_value(parsed_value[key])
return parsed_value
After upgrading from Django 4.1 to 4.2 it doesn’t work the same, it looks like it encrypting my value twice. I thought my issue might be similar to this one: #34539 (`get_prep_value` no longer called for JSONField) – Django - but that was fixed in 4.2.2 and doesn’t fix my issue.
I first had to change 1 thing
value = super().get_db_prep_value(value, connection, prepared=False)
This now returns a <psycopg2._json.Json
object, where it returned a string
before. So I changed parsed_value = json.loads(value)
to parsed_value = value.adapted
to convert it to a python object.
So my get_db_prep_save
looks like this now:
def get_db_prep_save(self, value, connection):
value = super().get_db_prep_value(value, connection, prepared=False)
if value is None:
return value
parsed_value = value.adapted
for key in parsed_value:
parsed_value[key] = signing.dumps(parsed_value[key])
return json.dumps(parsed_value)
But after I do that, it seems like the it’s encrypting twice. Here is an example model:
class Authentication(models.Model):
details = EncryptedJSONField(blank=True, null=True)
And here is a simple test that works on 4.1.13
but fails on 4.2.11
def test_encrypted_field(self):
details = {"username": "foo", "password": "bar"}
authentication = Authentication.objects.create(details=details)
assert authentication.details["password"] == "bar"
The error is AssertionError: assert 'IkltSmhjaUk6...mtQzkCHT6NQK4' == 'bar'
(Which is the value if I run it through signing.dumps twice) Does anyone have an idea on how to fix this?