Writing delegates may add at the top of a locked account's Files
A shared account refuses top-level folders, so an organize or full delegate couldn't add anything to a locked account with no folders. A delegate who may write now can, as the owner could; the reconcile after the create grants it the new folder. Read delegates still can't (AL-6, AL-7).
This commit is contained in:
@@ -840,6 +840,13 @@ impl AccessToken {
|
|||||||
|
|
||||||
/// inbuxa: AL-5: this account's delegation into a locked account, if it
|
/// inbuxa: AL-5: this account's delegation into a locked account, if it
|
||||||
/// has one that hasn't ended.
|
/// has one that hasn't ended.
|
||||||
|
/// inbuxa: AL-6, AL-7: a delegate at organize or full, who may add to
|
||||||
|
/// the locked account as its owner could, top-level folders included.
|
||||||
|
pub fn delegate_may_write(&self, account_id: u32) -> bool {
|
||||||
|
self.delegation(account_id)
|
||||||
|
.is_some_and(|d| d.access != inbuxa_features::lock::Access::Read)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn delegation(&self, account_id: u32) -> Option<&super::Delegation> {
|
pub fn delegation(&self, account_id: u32) -> Option<&super::Delegation> {
|
||||||
let now = now();
|
let now = now();
|
||||||
self.inner
|
self.inner
|
||||||
|
|||||||
@@ -226,9 +226,14 @@ impl FileNodeCopy for Server {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) =
|
// inbuxa: AL-7: a writing delegate may add at the top
|
||||||
validate_file_node_hierarchy(None, &file_node, is_shared, &cache, &created_folders)
|
if let Err(err) = validate_file_node_hierarchy(
|
||||||
{
|
None,
|
||||||
|
&file_node,
|
||||||
|
is_shared && !access_token.delegate_may_write(account_id),
|
||||||
|
&cache,
|
||||||
|
&created_folders,
|
||||||
|
) {
|
||||||
response.not_created.append(id, err);
|
response.not_created.append(id, err);
|
||||||
continue 'create;
|
continue 'create;
|
||||||
}
|
}
|
||||||
@@ -362,7 +367,7 @@ impl FileNodeCopy for Server {
|
|||||||
);
|
);
|
||||||
continue 'create;
|
continue 'create;
|
||||||
}
|
}
|
||||||
} else if is_shared {
|
} else if is_shared && !access_token.delegate_may_write(account_id) {
|
||||||
response.not_created.append(
|
response.not_created.append(
|
||||||
id,
|
id,
|
||||||
SetError::forbidden()
|
SetError::forbidden()
|
||||||
|
|||||||
@@ -149,9 +149,15 @@ impl FileNodeSet for Server {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Validate hierarchy
|
// Validate hierarchy
|
||||||
if let Err(err) =
|
// inbuxa: AL-7: a writing delegate may add at the top of a
|
||||||
validate_file_node_hierarchy(None, &file_node, is_shared, &cache, &created_folders)
|
// locked account, which may hold no folders at all
|
||||||
{
|
if let Err(err) = validate_file_node_hierarchy(
|
||||||
|
None,
|
||||||
|
&file_node,
|
||||||
|
is_shared && !access_token.delegate_may_write(account_id),
|
||||||
|
&cache,
|
||||||
|
&created_folders,
|
||||||
|
) {
|
||||||
response.not_created.append(id, err);
|
response.not_created.append(id, err);
|
||||||
continue 'create;
|
continue 'create;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,6 +193,15 @@ pub async fn test(test: &mut TestServer) {
|
|||||||
assert_eq!(name, method, "AL-7: {method} refused to the delegate: {response}");
|
assert_eq!(name, method, "AL-7: {method} refused to the delegate: {response}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AL-6: reading adds nothing, not even at the top of empty Files
|
||||||
|
let (_, response) = delegate
|
||||||
|
.call(
|
||||||
|
"FileNode/set",
|
||||||
|
json!({"accountId": owner_id, "create": {"f": {"name": "Notes", "parentId": null}}}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert!(response["created"].get("f").is_none(), "AL-6: a read delegate added a file: {response}");
|
||||||
|
|
||||||
// The delegate reads the mail that arrived
|
// The delegate reads the mail that arrived
|
||||||
let (_, found) = delegate
|
let (_, found) = delegate
|
||||||
.call(
|
.call(
|
||||||
@@ -236,6 +245,27 @@ pub async fn test(test: &mut TestServer) {
|
|||||||
"AL-5: {response}"
|
"AL-5: {response}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// AL-7: organize adds at the top of the locked account's Files, which
|
||||||
|
// held none, and sees what it made
|
||||||
|
let (_, response) = delegate
|
||||||
|
.call(
|
||||||
|
"FileNode/set",
|
||||||
|
json!({"accountId": owner_id, "create": {"f": {"name": "Handover notes", "parentId": null}}}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let folder_id = response["created"]["f"]["id"]
|
||||||
|
.as_str()
|
||||||
|
.unwrap_or_else(|| panic!("AL-7: organize couldn't add to empty Files: {response}"))
|
||||||
|
.to_string();
|
||||||
|
let (_, response) = delegate
|
||||||
|
.call("FileNode/get", json!({"accountId": owner_id, "ids": [folder_id]}))
|
||||||
|
.await;
|
||||||
|
assert_eq!(
|
||||||
|
response["list"].as_array().map(Vec::len),
|
||||||
|
Some(1),
|
||||||
|
"AL-7: the delegate can't see the folder it made: {response}"
|
||||||
|
);
|
||||||
|
|
||||||
// Test 12, AL-6, AL-7: organize makes folders it can see, moves mail,
|
// Test 12, AL-6, AL-7: organize makes folders it can see, moves mail,
|
||||||
// never deletes it
|
// never deletes it
|
||||||
let (_, mailboxes) = delegate
|
let (_, mailboxes) = delegate
|
||||||
|
|||||||
Reference in New Issue
Block a user