CalDAV/CardDAV review fixes, round 12
Look up one lent collection by id instead of loading all lent collections. Reword a test comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mserver/src/api/pim.rs
@@ -755,10 +755,8 @@ impl Cx<'_> {
return Ok(None);
};
Ok(db
.pim_shared_collections(self.me.id, kind)
.pim_shared_collection(self.me.id, kind, id)
.await?
.into_iter()
.find(|(c, ..)| c.id == id)
.map(|(c, owner, mode)| lent(c, &owner, mode)))
}
Mserver/src/api/pim_api.rs
@@ -530,10 +530,8 @@ pub(super) async fn reachable(
}
match state
.db
.pim_shared_collections(auth.user.id, kind)
.pim_shared_collection(auth.user.id, kind, id)
.await?
.into_iter()
.find(|(c, ..)| c.id == id)
{
Some((_, _, mode)) => Ok((owner, kind, c, mode != PimShareMode::Ro)),
None => Err(not_found()),
Mserver/src/api/pim_views.rs
@@ -354,10 +354,9 @@ pub(super) async fn may_answer(
}
Ok(state
.db
.pim_shared_collections(auth.user.id, PimKind::Calendar)
.pim_shared_collection(auth.user.id, PimKind::Calendar, collection_id)
.await?
.into_iter()
.any(|(c, _, mode)| c.id == collection_id && mode == PimShareMode::RwSchedule))
.is_some_and(|(_, _, mode)| mode == PimShareMode::RwSchedule))
}
#[derive(Deserialize)]
Mserver/src/db.rs
@@ -1722,22 +1722,24 @@ impl Db {
kind: PimKind,
) -> DbResult<Vec<(PimCollection, String, PimShareMode)>> {
self.rows(
&format!(
"SELECT {PIM_COLLECTION_COLS}, p.name, s.mode
FROM pim_shares s
JOIN pim_collections c ON c.id = s.collection_id
JOIN principals p ON p.id = c.principal_id
LEFT JOIN users u ON u.id = p.user_id
WHERE {VISIBLE} AND s.user_id = ?1 AND c.kind = ?2 ORDER BY c.id"
),
&pim_shared_sql("ORDER BY c.id"),
(user_id, pim_kind_str(kind)),
|r| {
Ok((
map_pim_collection(r)?,
r.get(10)?,
wire(r, 11, PimShareMode::from_wire)?,
))
},
map_shared,
)
.await
}
/// The collection `id` of `kind` as lent to `user_id`.
pub async fn pim_shared_collection(
&self,
user_id: i64,
kind: PimKind,
id: i64,
) -> DbResult<Option<(PimCollection, String, PimShareMode)>> {
self.row(
&pim_shared_sql("AND c.id = ?3"),
(user_id, pim_kind_str(kind), id),
map_shared,
)
.await
}
@@ -2401,6 +2403,26 @@ fn write_props(
Ok(())
}
/// Collections lent to `?1` of kind `?2`, with the owner's name and the mode.
fn pim_shared_sql(tail: &str) -> String {
format!(
"SELECT {PIM_COLLECTION_COLS}, p.name, s.mode
FROM pim_shares s
JOIN pim_collections c ON c.id = s.collection_id
JOIN principals p ON p.id = c.principal_id
LEFT JOIN users u ON u.id = p.user_id
WHERE {VISIBLE} AND s.user_id = ?1 AND c.kind = ?2 {tail}"
)
}
fn map_shared(r: &rusqlite::Row) -> DbResult<(PimCollection, String, PimShareMode)> {
Ok((
map_pim_collection(r)?,
r.get(10)?,
wire(r, 11, PimShareMode::from_wire)?,
))
}
fn map_pim_collection(r: &rusqlite::Row) -> DbResult<PimCollection> {
Ok(PimCollection {
id: r.get(0)?,
Mserver/tests/api/pim_clients.rs
@@ -173,7 +173,7 @@ async fn client_properties_are_stored() {
.await;
assert_eq!(find(&props(&r), "urn:x", "a").unwrap().0, 404);
// Unknown properties no longer fail a collection's PROPPATCH or MKCALENDAR.
// Unknown properties do not fail a collection's PROPPATCH or MKCALENDAR.
let cal = "/pim/calendars/alice/default/";
let patch = "<d:propertyupdate xmlns:d=\"DAV:\" xmlns:i=\"http://apple.com/ns/ical/\"><d:set><d:prop>\
<i:calendar-color>#ff0000</i:calendar-color><x:foo xmlns:x=\"urn:x\">bar</x:foo></d:prop></d:set></d:propertyupdate>";