Functionality for renaming attached files

This commit is contained in:
Oliver 2021-08-16 10:41:02 +10:00
parent ff8dcabb12
commit 3dcf1746e6

View File

@ -5,8 +5,10 @@ Generic models which provide extra functionality over base Django model types.
from __future__ import unicode_literals from __future__ import unicode_literals
import os import os
import logging
from django.db import models from django.db import models
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -21,6 +23,9 @@ from mptt.exceptions import InvalidMove
from .validators import validate_tree_name from .validators import validate_tree_name
logger = logging.getLogger('inventree')
def rename_attachment(instance, filename): def rename_attachment(instance, filename):
""" """
Function for renaming an attachment file. Function for renaming an attachment file.
@ -55,20 +60,6 @@ class InvenTreeAttachment(models.Model):
return "attachments" return "attachments"
def get_filename(self):
return os.path.basename(self.attachment.name)
def rename(self, filename):
"""
Rename this attachment with the provided filename.
- Filename cannot be empty
- Filename must have an extension
- Filename will have random data appended if a file exists with the same name
"""
pass
def __str__(self): def __str__(self):
return os.path.basename(self.attachment.name) return os.path.basename(self.attachment.name)
@ -91,6 +82,72 @@ class InvenTreeAttachment(models.Model):
def basename(self): def basename(self):
return os.path.basename(self.attachment.name) return os.path.basename(self.attachment.name)
@basename.setter
def basename(self, fn):
"""
Function to rename the attachment file.
- Filename cannot be empty
- Filename cannot contain illegal characters
- Filename must specify an extension
- Filename cannot match an existing file
"""
fn = fn.strip()
if len(fn) == 0:
raise ValidationError(_('Filename must not be empty'))
attachment_dir = os.path.join(
settings.MEDIA_ROOT,
self.getSubdir()
)
old_file = os.path.join(
settings.MEDIA_ROOT,
self.attachment.name
)
new_file = os.path.join(
settings.MEDIA_ROOT,
self.getSubdir(),
fn
)
new_file = os.path.abspath(new_file)
# Check that there are no directory tricks going on...
if not os.path.dirname(new_file) == attachment_dir:
logger.error(f"Attempted to rename attachment outside valid directory: '{new_file}'")
raise ValidationError(_("Invalid attachment directory"))
# Ignore further checks if the filename is not actually being renamed
if new_file == old_file:
return
forbidden = ["'", '"', "#", "@", "!", "&", "^", "<", ">", ":", ";", "/", "\\", "|", "?", "*", "%", "~", "`"]
for c in forbidden:
if c in fn:
raise ValidationError(_(f"Filename contains illegal character '{c}'"))
if len(fn.split('.')) < 2:
raise ValidationError(_("Filename missing extension"))
if not os.path.exists(old_file):
logger.error(f"Trying to rename attachment '{old_file}' which does not exist")
return
if os.path.exists(new_file):
raise ValidationError(_("Attachment with this filename already exists"))
try:
os.rename(old_file, new_file)
self.attachment.name = os.path.join(self.getSubdir(), fn)
self.save()
except:
raise ValidationError(_("Error renaming file"))
class Meta: class Meta:
abstract = True abstract = True