wip manage encrypted attachments

This commit is contained in:
Thomas Ramé
2026-03-03 10:09:12 +01:00
parent 54f2762e79
commit 431bec3970
6 changed files with 201 additions and 20 deletions
+17
View File
@@ -696,6 +696,7 @@ class FileUploadSerializer(serializers.Serializer):
"""Receive file upload requests."""
file = serializers.FileField()
is_encrypted = serializers.BooleanField(default=False, required=False)
def validate_file(self, file):
"""Add file size and type constraints as defined in settings."""
@@ -706,6 +707,22 @@ class FileUploadSerializer(serializers.Serializer):
f"File size exceeds the maximum limit of {max_size:d} MB."
)
# For encrypted files, the content is ciphertext so MIME detection
# is not possible. Trust the original filename extension.
if self.initial_data.get("is_encrypted") in ("true", "True", True):
extension = (
file.name.rpartition(".")[-1] if "." in file.name else None
)
if extension is None or len(extension) > 5:
raise serializers.ValidationError(
"Could not determine file extension."
)
self.context["expected_extension"] = extension
self.context["content_type"] = "application/octet-stream"
self.context["is_unsafe"] = False
self.context["file_name"] = file.name
return file
extension = file.name.rpartition(".")[-1] if "." in file.name else None
# Read the first few bytes to determine the MIME type accurately
+25 -2
View File
@@ -1480,18 +1480,39 @@ class DocumentViewSet(
serializer = serializers.FileUploadSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
is_file_encrypted = serializer.validated_data.get("is_encrypted", False)
# Encrypted attachments are only allowed on encrypted documents
if is_file_encrypted and not document.is_encrypted:
raise drf.exceptions.ValidationError({
"is_encrypted":
"Cannot upload encrypted attachments to a non-encrypted document."
})
# Generate a generic yet unique filename to store the image in object storage
file_id = uuid.uuid4()
ext = serializer.validated_data["expected_extension"]
# For encrypted files, set status to READY immediately since the server
# cannot inspect ciphertext for malware scanning.
initial_status = (
enums.DocumentAttachmentStatus.READY
if is_file_encrypted
else enums.DocumentAttachmentStatus.PROCESSING
)
# Prepare metadata for storage
extra_args = {
"Metadata": {
"owner": str(request.user.id),
"status": enums.DocumentAttachmentStatus.PROCESSING,
"status": initial_status,
},
"ContentType": serializer.validated_data["content_type"],
}
if is_file_encrypted:
extra_args["Metadata"]["is_encrypted"] = "true"
file_unsafe = ""
if serializer.validated_data["is_unsafe"]:
extra_args["Metadata"]["is_unsafe"] = "true"
@@ -1521,7 +1542,9 @@ class DocumentViewSet(
document.attachments.append(key)
document.save()
malware_detection.analyse_file(key, document_id=document.id)
# Only run malware scan for unencrypted files
if not is_file_encrypted:
malware_detection.analyse_file(key, document_id=document.id)
url = reverse(
"documents-media-check",