import pickle from base64 import b64encode, b64decode from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): pass public_key = models.TextField() private_key = models.TextField() def save(self, *args, **kwargs): if hasattr(self, '_phe_public_key') and hasattr(self, '_phe_private_key'): self.phe_public_key = b64encode(pickle.dumps(self._phe_public_key)).decode('utf-8') self.phe_private_key = b64encode(pickle.dumps(self._phe_private_key)).decode('utf-8') super().save(*args, **kwargs) @property def deserialized_public_key(self): return pickle.loads(b64decode(self.phe_public_key)) @property def deserialized_private_key(self): return pickle.loads(b64decode(self.phe_private_key)) class Meta: permissions = [ ("can_create_users", "Can create new users"), ] class AttributeType(models.Model): DATATYPE_CHOICES = [ ('string', 'String'), ('boolean', 'Boolean'), ('integer', 'Integer'), ] is_secret = models.BooleanField(default=False) datatype = models.CharField(max_length=15) significant_digits = models.PositiveIntegerField(null=True, blank=True) name = models.CharField(max_length=40) def save(self, *args, **kwargs): if self.datatype.startswith('float'): if self.significant_digits is None: raise ValueError('significant_digits must be set for float datatype') self.datatype = f'float_{self.significant_digits}' elif self.significant_digits is not None: raise ValueError('significant_digits must be None for non-float datatype') super().save(*args, **kwargs) class Attribute(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) attribute_type = models.ForeignKey(AttributeType, on_delete=models.CASCADE) value = models.IntegerField() # assuming value is always stored as an integer class Rule(models.Model): TYPE_CHOICES = [ ('and', 'AND'), ('or', 'OR'), ] rule_type = models.CharField(max_length=3, choices=TYPE_CHOICES) attributes = models.ManyToManyField(Attribute) class File(models.Model): owner = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255) file = models.FileField(upload_to='uploads/') # assuming you are using FileField to store the file rules = models.ManyToManyField(Rule)