🐛(backend) fix WOPI PutFile to check stored file size

When a file is created from a template, it has content from the start.
The PutFile operation needs to check the stored file size rather than
the request content length to correctly handle lock-free updates.
This ensures the empty file check works correctly for template-created
files.
This commit is contained in:
Nathan Vasse
2026-02-23 14:57:55 +01:00
parent f43c8a49bd
commit e4d06905e4
3 changed files with 8 additions and 6 deletions
+1
View File
@@ -15,6 +15,7 @@ and this project adheres to
### Fixed
- ✨(frontend) sync backend user language to browser on load
- 🐛(backend) fix WOPI PutFile to check stored file size
## [v0.13.0] - 2026-02-18
@@ -352,6 +352,7 @@ def test_put_file_content_with_no_lock_header_and_body_size_greater_than_0():
update_upload_state=models.ItemUploadStateChoices.READY,
link_reach=models.LinkReachChoices.RESTRICTED,
link_role=models.LinkRoleChoices.EDITOR,
size=100,
)
user = factories.UserFactory()
factories.UserItemAccessFactory(
@@ -374,7 +375,8 @@ def test_put_file_content_with_no_lock_header_and_body_size_greater_than_0():
assert response.headers.get("X-WOPI-Lock") == ""
def test_put_file_content_with_no_lock_header_and_body_size_0():
@pytest.mark.parametrize("data", [b"", b"new content"])
def test_put_file_content_with_no_lock_header_and_body_size_0(data):
"""User can put file content when not providing a lock header and the body size is 0."""
folder = factories.ItemFactory(
type=models.ItemTypeChoices.FOLDER,
@@ -386,6 +388,7 @@ def test_put_file_content_with_no_lock_header_and_body_size_0():
update_upload_state=models.ItemUploadStateChoices.READY,
link_reach=models.LinkReachChoices.RESTRICTED,
link_role=models.LinkRoleChoices.EDITOR,
size=0,
)
user = factories.UserFactory()
factories.UserItemAccessFactory(
@@ -397,7 +400,7 @@ def test_put_file_content_with_no_lock_header_and_body_size_0():
client = APIClient()
response = client.post(
f"/api/v1.0/wopi/files/{item.id}/contents/",
data=b"",
data=data,
content_type="text/plain",
HTTP_AUTHORIZATION=f"Bearer {access_token}",
headers={
@@ -413,5 +416,5 @@ def test_put_file_content_with_no_lock_header_and_body_size_0():
Bucket=default_storage.bucket_name,
Key=item.file_key,
)
assert file["Body"].read() == b""
assert file["Body"].read() == data
assert response.headers.get("X-WOPI-ItemVersion") == file["VersionId"]
+1 -3
View File
@@ -143,7 +143,6 @@ class WopiViewSet(viewsets.ViewSet):
Implementation of the Wopi PutFile file operation
https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/rest/files/putfile
"""
if request.META.get(HTTP_X_WOPI_OVERRIDE) != "PUT":
return Response(status=404)
@@ -154,7 +153,6 @@ class WopiViewSet(viewsets.ViewSet):
return Response(status=401)
lock_value = request.META.get(HTTP_X_WOPI_LOCK)
if lock_value:
lock_service = LockService(item)
current_lock_value = lock_service.get_lock(default="")
@@ -162,7 +160,7 @@ class WopiViewSet(viewsets.ViewSet):
return Response(status=409, headers={X_WOPI_LOCK: current_lock_value})
else:
# Check if the body is 0 bytes
body_size = int(request.META.get("CONTENT_LENGTH") or 0)
body_size = item.size or 0
if body_size > 0:
return Response(status=409, headers={X_WOPI_LOCK: ""})