This commit is contained in:
j3d1 2026-08-16 23:52:58 +02:00
parent 3b494dfa37
commit 0f51f6e33f
14 changed files with 534 additions and 356 deletions

View file

@ -1,4 +1,7 @@
from types import SimpleNamespace
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
from django.db import models, IntegrityError
from django.db.models import Model
@ -40,6 +43,18 @@ class FileManager(models.Manager):
else:
raise ValueError('data must be a base64 encoded string or file and hash must be provided')
if not self.filter(hash=kwargs['hash']).exists():
# The upload path is derived entirely from the hash (hash_upload, above), and hash
# is DB-unique - so if no File row owns this hash yet, anything already sitting at
# its computed path is necessarily a stale orphan (e.g. left behind by a bug in
# cleanup code that deleted a File row without removing its stored bytes, or a
# crashed upload). Clear it before saving instead of letting Django's storage layer
# invent an alternate filename to avoid the "collision" - a suffixed name would
# silently break every part of the app that derives this file's URL purely from its
# hash (media serving, thumbnail generation, item/avatar attachment), and no future
# caller could ever discover it again.
expected_path = hash_upload(SimpleNamespace(hash=kwargs['hash']), '')
if default_storage.exists(expected_path):
default_storage.delete(expected_path)
return super().create(**kwargs)
else:
raise IntegrityError('File with this hash already exists')