[Feature Request] A hook to transform a field before it's saved and after it's read (for field-level encryption) #14163
Unanswered
sashyo
asked this question in
Feature Requests
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Description
Paperless is the privacy-friendly choice, which is exactly why I'd like to go one step further: have some of the text stored encrypted at rest. A document's title, its OCR content, the correspondent, my notes. Right now that all sits in the database as plain text, so a stolen database file, an old backup, or the search index on disk gives someone the whole archive to read.
I can handle the encryption itself. What I can't do without forking is hook the values on the way in and out, because that means editing the model and serializer classes directly.
I'd like an opt-in way to say "run these fields through a transform on save and on read", without touching the models. Something like registering, at startup, which fields a transform owns and what it does (encrypt on write, decrypt on read for the current user). Under the hood it's the pre_save signal Paperless already uses on the write side, and the DRF serializers on the read side. With nothing registered it does nothing, so default behaviour is unchanged. Paperless wouldn't ship any crypto, just the hook. Encryption, tokenising, or hiding fields from users without a role could all build on it.
Other
One thing that makes this Paperless-specific and worth getting right: the OCR content is copied into the full-text index on disk. So the read-side opening has to happen on the way out of the API (in the serializer), not at the model or ORM layer. If you decrypt at the model level, the plaintext flows straight back into the index and now the index is a second copy in the clear. Seal on write, open only in the serializer, and both the database and the index stay ciphertext.
I've already built this on a fork to check it works: title, content, correspondent name and note text are stored encrypted, the search index holds only ciphertext, a granted user reads plaintext through the UI, an ungranted user (even a superuser) reads ciphertext, and revoking access turns reads off with no change to the app. The whole thing is a small pre_save receiver plus three serializer hooks plus a client for whatever does the encryption. The only reason it's a fork is that it edits the models and serializers.
Happy to open a draft PR with just the hook (no crypto, off by default) if you're open to it.
All reactions