from django.db import models from core.utils.crypto import encrypt_secret, decrypt_secret class EncryptedCharField(models.CharField): """CharField, который хранит значение в БД в зашифрованном виде (Fernet). Для приложения поле ведёт себя как обычная строка: чтение отдаёт открытый текст, запись сохраняет шифртекст. Шифрование выполняется на границе с БД, поэтому читатели (`cfg.password`, `cfg.token`) и админка изменений не требуют. Шифртекст длиннее исходного текста (~1.4×) плюс постоянный оверхед Fernet, поэтому колонку нужно объявлять с запасом по `max_length`. """ def get_db_prep_save(self, value, connection): value = super().get_db_prep_save(value, connection) if value in (None, ''): return value return encrypt_secret(value) def from_db_value(self, value, expression, connection): if value in (None, ''): return value try: return decrypt_secret(value) except Exception: # Значение записано до включения шифрования — вернуть как есть. return value