import logging import os from django.conf import settings from django.contrib.auth.models import User from django.db import models from django.utils.translation import gettext_lazy from core.fields import IntegerField from core.utils import dtnow from storage.enums import CrcType from storage.services import verify_file_from_json, get_json_crc _log = logging.getLogger(__name__) MEDIA_ROOT = settings.MEDIA_ROOT def get_storage_path(instance, file_name): """ Get file name for storage :param instance: DataStorage record to save :param file_name: Original file name :return: String with filename """ path_no_ext, ext = os.path.splitext(file_name) return '{0}/{1}/{2}/{3}_{4}{5}'.format( instance.user, instance.type, instance.format, path_no_ext, instance.created.strftime('%Y%m%d%H%M%S'), ext ) class DataStorage(models.Model): """ One record in storage """ class Type(models.IntegerChoices): UNKNOWN = 0, gettext_lazy('Unknown') DB_DUMP = 1, gettext_lazy('DB dump') CSV_EXPORT = 2, gettext_lazy('CSV export') JSON_EXPORT = 3, gettext_lazy('JSON export') CLAMAV = 4, gettext_lazy('ClamAV updates') FIREWALL = 5, gettext_lazy('Firewall') class Format(models.IntegerChoices): UNKNOWN = 0, gettext_lazy('Unknown') PLAIN = 1, gettext_lazy('Plain') JSON = 2, gettext_lazy('JSON') CSV = 3, gettext_lazy('CSV') ZIP = 4, gettext_lazy('ZIP') TAR = 5, gettext_lazy('TAR') XML = 6, gettext_lazy('XML') type = IntegerField(choices=Type.choices, verbose_name=gettext_lazy('Type'), help_text=gettext_lazy('Type of storage record'), default=Type.UNKNOWN) format = IntegerField(choices=Format.choices, verbose_name=gettext_lazy('Format'), help_text=gettext_lazy('Format of storage record'), default=Format.UNKNOWN) created = models.DateTimeField(auto_now_add=True, verbose_name=gettext_lazy('Created'), help_text=gettext_lazy('Date and time, when record was created')) last_access = models.DateTimeField(auto_now=True, verbose_name=gettext_lazy('Last access'), help_text=gettext_lazy('Date and time, when record was downloaded last time')) user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=gettext_lazy('User'), help_text=gettext_lazy('User, who own this record')) size = IntegerField(verbose_name=gettext_lazy('Size'), help_text=gettext_lazy('Size of record in MB'), min_value=0) crc = models.JSONField(verbose_name=gettext_lazy('CRC'), help_text=gettext_lazy('Checksum of record'), blank=True, null=True) description = models.TextField(null=True, blank=True, verbose_name=gettext_lazy('Description'), help_text=gettext_lazy('Description')) free_date = models.DateField(verbose_name=gettext_lazy('Remove date'), help_text=gettext_lazy('When record will be removed'), blank=True, null=True) file = models.FileField(upload_to=get_storage_path, verbose_name=gettext_lazy('File'), help_text=gettext_lazy('Actual file name')) def get_full_path(self): return os.path.join(MEDIA_ROOT, self.file.name) def update_crc(self): self.crc = get_json_crc(self.get_full_path(), CrcType.SHA512) self.save() def verify_file(self): try: return verify_file_from_json(self.get_full_path(), self.crc) except KeyError: return False except TypeError: _log.error(f"Can't calculate crc for {self.file} crc is {self.crc}") return False except Exception as e: _log.error(e) return False def save(self, *args, **kwargs): self.last_access = dtnow() super().save(*args, **kwargs)