Delegates reach the whole locked account
ci / fork-checks (pull_request) Successful in 14s
ci / build (pull_request) Canceled after 5m27s

A delegate's token listed the locked account only for kinds of data it
held grants on, so one with no files (or no calendar) was refused to the
delegate outright: "You do not have access to account". The token now
lists the locked account for mail, calendars, contacts and files alike,
so an empty kind reads as empty. What the delegate may see or change is
still each container's grant (AL-7).
This commit is contained in:
2026-09-27 17:58:50 -07:00
parent 7720a57ac9
commit d4d127fa7d
2 changed files with 37 additions and 0 deletions
+14
View File
@@ -36,6 +36,9 @@ const USING: &[&str] = &[
"urn:ietf:params:jmap:core",
"urn:ietf:params:jmap:mail",
"urn:ietf:params:jmap:submission",
"urn:ietf:params:jmap:calendars",
"urn:ietf:params:jmap:contacts",
"urn:ietf:params:jmap:filenode",
"urn:inbuxa:jmap",
];
@@ -179,6 +182,17 @@ pub async fn test(test: &mut TestServer) {
assert_eq!(delegation["access"], "read", "AL-7");
assert_eq!(delegation["sendAs"], false, "AL-7");
// AL-7: the whole account, not only mail: even a kind the owner holds
// none of (no files here) reads as empty rather than refused
for (method, arguments) in [
("FileNode/query", json!({"accountId": owner_id})),
("Calendar/get", json!({"accountId": owner_id, "ids": null})),
("AddressBook/get", json!({"accountId": owner_id, "ids": null})),
] {
let (name, response) = delegate.call(method, arguments).await;
assert_eq!(name, method, "AL-7: {method} refused to the delegate: {response}");
}
// The delegate reads the mail that arrived
let (_, found) = delegate
.call(