from django.contrib.auth.forms import gettext as _ from django.db import models from app.utils.models import BaseModel from users.models import UserSettings from simple_history.models import HistoricalRecords class ItemBase(BaseModel): class Meta: abstract = True class Serialization(BaseModel.Serialization): excluded_fields = BaseModel.Serialization.excluded_fields + ["author"] excluded_fields_edit = BaseModel.Serialization.excluded_fields_edit + ["author"] author = models.ForeignKey(UserSettings, on_delete=models.PROTECT) history = HistoricalRecords(inherit=True, user_model=UserSettings) @property def _history_user(self): return self.author @_history_user.setter def _history_user(self, value): self.author = value class ItemType(ItemBase): pass class ItemRelation(ItemBase): parent = models.ForeignKey("items.Item", on_delete=models.CASCADE, related_name="children") child = models.ForeignKey("items.Item", on_delete=models.CASCADE, related_name="parents") properties = models.ManyToManyField("items.Property", through="items.RelationProperty", related_name="relations") class Item(ItemBase): name = models.TextField(max_length=2048) description = models.TextField(max_length=2048) type = models.ForeignKey(ItemType, on_delete=models.PROTECT) relations = models.ManyToManyField( "items.Item", through=ItemRelation, ) properties = models.ManyToManyField( "items.Property", through="LinkedProperty", related_name="items", ) class PropertyType(models.TextChoices): TEXT = "text", _("Text") DATE = "date", _("Date") DATETIME = "datetime", _("Date & time") TIME = "time", _("Time") DURATION = "duration", _("Duration") UUID = "uuid", _("UUID") NUMBER = "number", _("Number") FLOAT = "float", _("Float") BOOLEAN = "boolean", _("Boolean") EMAIL = "email", _("Email") IPV4 = "ipv4", _("IPv4 address") IPV6 = "ipv6", _("IPv6 address") JSON = "json", _("JSON") # TODO: Add more property types (location, etc) class Property(ItemBase): type = models.CharField(max_length=32, choices=PropertyType.choices, default=PropertyType.TEXT) class BaseLinkedProperty(ItemBase): class Meta: abstract = True class Serialization(ItemBase.Serialization): dynamic_field_type = ItemBase.Serialization.dynamic_field_type + ["value"] class Encryption(ItemBase.Encryption): fields = ItemBase.Encryption.fields + ["value"] property = models.ForeignKey(Property, on_delete=models.PROTECT) # Value is encrypted too value = models.TextField(max_length=2048) class LinkedProperty(BaseLinkedProperty): item = models.ForeignKey(Item, on_delete=models.CASCADE, null=True, related_name="linked_properties") class RelationProperty(BaseLinkedProperty): relation = models.ForeignKey( ItemRelation, on_delete=models.CASCADE, null=True, related_name="relation_properties", )