wip decryption with attachments

This commit is contained in:
Thomas Ramé
2026-03-03 18:21:31 +01:00
parent 3f8e105035
commit 834ed4226f
7 changed files with 249 additions and 97 deletions
+8
View File
@@ -1002,6 +1002,14 @@ class RemoveEncryptionSerializer(serializers.Serializer):
"""
content = serializers.CharField(required=True)
attachmentKeyMapping = serializers.DictField(
child=serializers.CharField(),
required=False,
default=dict,
help_text="Mapping of old encrypted attachment key to new decrypted attachment key. "
"During decryption, encrypted attachments are re-uploaded decrypted under new keys. "
"This mapping tells the backend to remove the old keys and clean up.",
)
class ReactionSerializer(serializers.ModelSerializer):
+23
View File
@@ -2151,6 +2151,16 @@ class DocumentViewSet(
serializer.is_valid(raise_exception=True)
content = serializer.validated_data["content"]
attachment_key_mapping = serializer.validated_data.get("attachmentKeyMapping", {})
# Remove old encrypted attachment keys from the allowed list.
# The frontend uploaded decrypted copies under new keys and updated
# the Yjs content to reference them.
if attachment_key_mapping:
old_keys = set(attachment_key_mapping.keys())
document.attachments = [
k for k in (document.attachments or []) if k not in old_keys
]
# Update the document content and encryption status
document.content = content # This will be cached and saved to object storage
@@ -2162,6 +2172,19 @@ class DocumentViewSet(
encrypted_document_symmetric_key_for_user=None
)
# Clean up old S3 objects only after the DB transaction has committed
if attachment_key_mapping:
def _cleanup_old_attachments():
s3_client = default_storage.connection.meta.client
bucket_name = default_storage.bucket_name
for old_key in attachment_key_mapping:
try:
s3_client.delete_object(Bucket=bucket_name, Key=old_key)
except ClientError:
logger.warning("Failed to delete old attachment %s", old_key)
transaction.on_commit(_cleanup_old_attachments)
# Return the updated document
serializer = self.get_serializer(document)
return drf.response.Response(serializer.data, status=drf.status.HTTP_200_OK)