erikvw/django-crypto-fields

View on GitHub
django_crypto_fields/models.py

Summary

Maintainability
A
0 mins
Test Coverage
from django.db import models
from django_audit_fields.models import AuditUuidModelMixin

from .fields import BaseField


class CryptoMixin(models.Model):
    """Model mixin for a user model that need to list it's
    encrypted fields.
    """

    @classmethod
    def encrypted_fields(cls):
        return [fld.name for fld in cls._meta.fields if isinstance(fld, BaseField)]

    class Meta:
        abstract = True


class CryptModelManager(models.Manager):
    def get_by_natural_key(self, value_as_hash, algorithm, mode):
        return self.get(hash=value_as_hash, algorithm=algorithm, mode=mode)


class Crypt(AuditUuidModelMixin, models.Model):
    """A secrets lookup model searchable by hash."""

    hash = models.CharField(verbose_name="Hash", max_length=128, db_index=True)

    # causes problems with Postgres!!
    secret = models.BinaryField(verbose_name="Secret")

    algorithm = models.CharField(max_length=25, db_index=True, null=True)

    mode = models.CharField(max_length=25, db_index=True, null=True)

    cipher_mode = models.IntegerField(
        null=True, help_text="pycryptodomex AES cipher mode (e.g. MODE_CBC)"
    )

    objects = CryptModelManager()

    def natural_key(self):
        return (
            self.hash,
            self.algorithm,
            self.mode,
        )

    class Meta:
        verbose_name = "Crypt"
        unique_together = (("hash", "algorithm", "mode"),)
        indexes = [models.Index(fields=["hash", "algorithm", "mode"])]