diff --git a/crates/dav/src/common/acl.rs b/crates/dav/src/common/acl.rs index 192662cc..f5de25ab 100644 --- a/crates/dav/src/common/acl.rs +++ b/crates/dav/src/common/acl.rs @@ -315,10 +315,12 @@ impl DavAclHandler for Server { Privilege::Write => { acls.insert(Acl::Modify); acls.insert(Acl::Delete); + acls.insert(Acl::AddItems); acls.insert(Acl::ModifyItems); acls.insert(Acl::RemoveItems); } Privilege::WriteContent => { + acls.insert(Acl::AddItems); acls.insert(Acl::Modify); acls.insert(Acl::ModifyItems); } diff --git a/crates/dav/src/file/delete.rs b/crates/dav/src/file/delete.rs index d4d52d3f..c6bb4aff 100644 --- a/crates/dav/src/file/delete.rs +++ b/crates/dav/src/file/delete.rs @@ -66,7 +66,7 @@ impl FileDeleteRequestHandler for Server { // Validate ACLs if !access_token.is_member(account_id) { let permissions = resources.shared_containers(access_token, [Acl::Delete], false); - if permissions.len() != sorted_ids.len() as u64 + if permissions.len() < sorted_ids.len() as u64 || !sorted_ids.iter().all(|id| permissions.contains(*id)) { return Err(DavError::Code(StatusCode::FORBIDDEN)); diff --git a/crates/dav/src/file/update.rs b/crates/dav/src/file/update.rs index d2b35bc0..d6f5002e 100644 --- a/crates/dav/src/file/update.rs +++ b/crates/dav/src/file/update.rs @@ -265,7 +265,11 @@ impl FileUpdateRequestHandler for Server { created: now as i64, modified: now as i64, dead_properties: Default::default(), - acls: Default::default(), + acls: parent + .as_ref() + .and_then(|p| p.resource.acls()) + .map(|acls| acls.to_vec()) + .unwrap_or_default(), }; // Prepare write batch diff --git a/tests/src/webdav/acl.rs b/tests/src/webdav/acl.rs index 744c6131..214aa17a 100644 --- a/tests/src/webdav/acl.rs +++ b/tests/src/webdav/acl.rs @@ -35,6 +35,7 @@ pub async fn test(test: &WebDavTest) { let owner_file_content = resource_type.generate(); let owner_file_private = format!("{owner_folder_private}test-file-private"); let owner_file_content_private = resource_type.generate(); + let sharee_created_file = format!("{owner_folder}test-file-sharee"); for (folder, file, content) in [ (&owner_folder, &owner_file, &owner_file_content), ( @@ -204,6 +205,10 @@ pub async fn test(test: &WebDavTest) { .request("PUT", &owner_file, resource_type.generate()) .await .with_status(StatusCode::FORBIDDEN); + sharee_client + .request("PUT", &sharee_created_file, resource_type.generate()) + .await + .with_status(StatusCode::FORBIDDEN); // Test 9: Grant write access to the sharee owner_client @@ -279,6 +284,10 @@ pub async fn test(test: &WebDavTest) { .request("PUT", &owner_file, &owner_file_content) .await .with_status(StatusCode::NO_CONTENT); + sharee_client + .request("PUT", &sharee_created_file, resource_type.generate()) + .await + .with_status(StatusCode::CREATED); // Test 11: Grant delete access to the sharee and verify owner_client @@ -290,6 +299,14 @@ pub async fn test(test: &WebDavTest) { .acl(&owner_file, sharee_principal.as_str(), ["read", "write"]) .await .with_status(StatusCode::OK); + owner_client + .acl( + &sharee_created_file, + sharee_principal.as_str(), + ["read", "write"], + ) + .await + .with_status(StatusCode::OK); } sharee_client .request_with_headers( @@ -300,6 +317,10 @@ pub async fn test(test: &WebDavTest) { ) .await .with_status(StatusCode::NO_CONTENT); + sharee_client + .request("DELETE", &sharee_created_file, "") + .await + .with_status(StatusCode::NO_CONTENT); sharee_client .request("DELETE", &owner_folder, "") .await