fix(webdav): make PATCH's concurrency guard a real compare-and-swap
The app-level ETag re-check before the write still left a gap between the check and the actual UPDATE for a concurrent writer to land in. Push the check into the write path itself: swap_blob_hash now takes an expected_hash and only applies the SET under the same FOR UPDATE row lock it already held, closing the race instead of just narrowing it. Adds ErrorKind::PreconditionFailed (412) for the CAS-miss path; PUT/WOPI/chunked-upload keep blind-overwrite semantics by passing None
This commit is contained in:
@@ -466,6 +466,10 @@ async fn handle_assemble(
|
||||
// AuthZ audit #2 (2026-07-12): route DomainError through
|
||||
// `AppError::from` so authz denials keep the graduated 403/404
|
||||
// shape instead of collapsing into 500.
|
||||
//
|
||||
// No client-supplied ETag to enforce here (NC chunked MOVE has no
|
||||
// If-Match semantics) — `expected_hash: None`, same as every other
|
||||
// plain-write callsite; only PATCH's CAS passes `Some(&hash)`.
|
||||
let dto = match upload_service
|
||||
.update_file_streaming_with_perms(
|
||||
&internal_path,
|
||||
@@ -474,6 +478,7 @@ async fn handle_assemble(
|
||||
&content_type,
|
||||
oc_mtime,
|
||||
user.id,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user