Legal holds (phase 3) #70

Merged
jcoffey-dev merged 8 commits from feature/legal-hold into main 2026-09-28 03:00:43 +00:00
3 changed files with 54 additions and 1 deletions
Showing only changes of commit 3217aae4e8 - Show all commits
@@ -139,6 +139,27 @@ impl Element for LegalHoldValue {
} }
} }
/// The get call's own argument: only the active holds covering an account,
/// through any route (LH-2), for the console's Held badge (LH-14).
#[derive(Debug, Clone, Default)]
pub struct LegalHoldGetArguments {
pub covering_account: Option<Id>,
}
impl<'de> DeserializeArguments<'de> for LegalHoldGetArguments {
fn deserialize_argument<A>(&mut self, key: &str, map: &mut A) -> Result<(), A::Error>
where
A: serde::de::MapAccess<'de>,
{
if key == "coveringAccount" {
self.covering_account = map.next_value()?;
} else {
let _ = map.next_value::<serde::de::IgnoredAny>()?;
}
Ok(())
}
}
/// The set call's own arguments: why (AU-12). /// The set call's own arguments: why (AU-12).
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct LegalHoldSetArguments { pub struct LegalHoldSetArguments {
@@ -170,7 +191,7 @@ impl JmapObject for LegalHold {
type Comparator = (); type Comparator = ();
type GetArguments = (); type GetArguments = LegalHoldGetArguments;
type SetArguments<'de> = LegalHoldSetArguments; type SetArguments<'de> = LegalHoldSetArguments;
+19
View File
@@ -131,6 +131,25 @@ pub async fn get(
} else { } else {
Default::default() Default::default()
}; };
// LH-14: the holds on one account, whether it's live or deleted and kept
if let Some(account) = request.arguments.covering_account.take() {
let account_id = account.document_id();
let covering = match server.member_of(account_id).await {
Some(member) => hold::covering(data, &member).await?,
None => match inbuxa_features::undelete::data::kept_account(data, account_id).await? {
Some(kept) => {
hold::covering(data, &common::hold::kept_member(account_id, &kept)).await?
}
None => Vec::new(),
},
};
for current in covering {
response
.list
.push(to_value(&current, &properties, summaries.get(&current.id)));
}
return Ok(response);
}
match ids { match ids {
None => { None => {
for current in hold::all(data).await? { for current in hold::all(data).await? {
+13
View File
@@ -422,6 +422,19 @@ pub async fn test(test: &mut TestServer) {
assert_eq!(summary["accountsCovered"], 1, "LH-9: {response}"); assert_eq!(summary["accountsCovered"], 1, "LH-9: {response}");
assert_eq!(summary["itemsHeld"], 1, "LH-9: {response}"); assert_eq!(summary["itemsHeld"], 1, "LH-9: {response}");
assert!(summary["sizeHeld"].as_u64().is_some_and(|s| s > 0), "LH-9: {response}"); assert!(summary["sizeHeld"].as_u64().is_some_and(|s| s > 0), "LH-9: {response}");
// LH-14: the holds on one account, for the console's Held badge
let (_, response) = admin
.hold_call(
"inbuxa:LegalHold/get",
json!({"coveringAccount": frozen.id_string(), "properties": ["name"]}),
)
.await;
let mut names = response["list"]
.as_array()
.map(|l| l.iter().filter_map(|h| h["name"].as_str()).collect::<Vec<_>>())
.unwrap_or_default();
names.sort_unstable();
assert_eq!(names, vec!["Matter 7001", "Matter 7002"], "LH-14: {response}");
let (_, response) = frozen let (_, response) = frozen
.hold_call("x:ArchivedItem/set", json!({"destroy": [item_id]})) .hold_call("x:ArchivedItem/set", json!({"destroy": [item_id]}))