mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-09-06 03:54:22 +08:00
Return all shared resources in calendar-home-set and addressbook-home-set (closes #1796)
This commit is contained in:
parent
20bab962d4
commit
a203ce732f
3 changed files with 109 additions and 71 deletions
|
@ -22,7 +22,10 @@ use crate::{
|
|||
},
|
||||
common::{DavQueryResource, acl::current_user_privilege_set, uri::DavUriResource},
|
||||
file::{FILE_CONTAINER_PROPS, FILE_ITEM_PROPS},
|
||||
principal::{CurrentUserPrincipal, propfind::PrincipalPropFind},
|
||||
principal::{
|
||||
CurrentUserPrincipal,
|
||||
propfind::{PrincipalPropFind, build_home_set},
|
||||
},
|
||||
};
|
||||
use calcard::common::timezone::Tz;
|
||||
use common::{
|
||||
|
@ -47,10 +50,10 @@ use dav_proto::{
|
|||
},
|
||||
};
|
||||
use directory::{Permission, Type, backend::internal::manage::ManageDirectory};
|
||||
use groupware::calendar::SCHEDULE_INBOX_ID;
|
||||
use groupware::{
|
||||
DavCalendarResource, DavResourceName, cache::GroupwareCache, calendar::ArchivedTimezone,
|
||||
};
|
||||
use groupware::{RFC_3986, calendar::SCHEDULE_INBOX_ID};
|
||||
use http_proto::HttpResponse;
|
||||
use hyper::StatusCode;
|
||||
use jmap_proto::types::{
|
||||
|
@ -246,11 +249,13 @@ impl PropFindRequestHandler for Server {
|
|||
// Add container info
|
||||
if !headers.depth_no_root {
|
||||
add_base_collection_response(
|
||||
self,
|
||||
&request,
|
||||
resource.collection,
|
||||
access_token,
|
||||
&mut response,
|
||||
);
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if return_children {
|
||||
|
@ -386,11 +391,13 @@ impl PropFindRequestHandler for Server {
|
|||
// Add container info
|
||||
if !query.depth_no_root {
|
||||
add_base_collection_response(
|
||||
self,
|
||||
&query.propfind,
|
||||
parent_collection,
|
||||
access_token,
|
||||
&mut response,
|
||||
);
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
discover_root_paths(
|
||||
|
@ -1686,12 +1693,13 @@ impl SyncTokenUrn for DavResources {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_base_collection_response(
|
||||
async fn add_base_collection_response(
|
||||
server: &Server,
|
||||
request: &PropFind,
|
||||
collection: Collection,
|
||||
access_token: &AccessToken,
|
||||
response: &mut MultiStatus,
|
||||
) {
|
||||
) -> trc::Result<()> {
|
||||
let properties = match request {
|
||||
PropFind::PropName => {
|
||||
response.add_response(Response::new_propstat(
|
||||
|
@ -1706,7 +1714,7 @@ fn add_base_collection_response(
|
|||
)),
|
||||
])],
|
||||
));
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
PropFind::AllProp(_) => [
|
||||
DavProperty::WebDav(WebDavProperty::ResourceType),
|
||||
|
@ -1735,25 +1743,31 @@ fn add_base_collection_response(
|
|||
));
|
||||
}
|
||||
DavProperty::Principal(PrincipalProperty::CalendarHomeSet) => {
|
||||
fields.push(DavPropertyValue::new(
|
||||
prop.clone(),
|
||||
vec![Href(format!(
|
||||
"{}/{}/",
|
||||
DavResourceName::Cal.base_path(),
|
||||
percent_encoding::utf8_percent_encode(&access_token.name, RFC_3986),
|
||||
))],
|
||||
));
|
||||
let hrefs = build_home_set(
|
||||
server,
|
||||
access_token,
|
||||
&access_token.name,
|
||||
access_token.primary_id,
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
|
||||
fields.push(DavPropertyValue::new(prop.clone(), hrefs));
|
||||
response.set_namespace(Namespace::CalDav);
|
||||
}
|
||||
DavProperty::Principal(PrincipalProperty::AddressbookHomeSet) => {
|
||||
fields.push(DavPropertyValue::new(
|
||||
prop.clone(),
|
||||
vec![Href(format!(
|
||||
"{}/{}/",
|
||||
DavResourceName::Card.base_path(),
|
||||
percent_encoding::utf8_percent_encode(&access_token.name, RFC_3986),
|
||||
))],
|
||||
));
|
||||
let hrefs = build_home_set(
|
||||
server,
|
||||
access_token,
|
||||
&access_token.name,
|
||||
access_token.primary_id,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
|
||||
fields.push(DavPropertyValue::new(prop.clone(), hrefs));
|
||||
response.set_namespace(Namespace::CardDav);
|
||||
}
|
||||
DavProperty::WebDav(WebDavProperty::SupportedReportSet) => {
|
||||
|
@ -1787,4 +1801,6 @@ fn add_base_collection_response(
|
|||
DavResourceName::from(collection).collection_path(),
|
||||
prop_stat,
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -270,54 +270,28 @@ impl PrincipalPropFind for Server {
|
|||
))],
|
||||
));
|
||||
}
|
||||
PrincipalProperty::CalendarHomeSet
|
||||
| PrincipalProperty::AddressbookHomeSet => {
|
||||
let mut hrefs = Vec::new();
|
||||
let (collection, resource_name, namespace) =
|
||||
if principal_property == &PrincipalProperty::CalendarHomeSet {
|
||||
(
|
||||
Collection::Calendar,
|
||||
DavResourceName::Cal,
|
||||
Namespace::CalDav,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
Collection::AddressBook,
|
||||
DavResourceName::Card,
|
||||
Namespace::CardDav,
|
||||
)
|
||||
};
|
||||
|
||||
hrefs.push(Href(format!(
|
||||
"{}/{}/",
|
||||
resource_name.base_path(),
|
||||
percent_encoding::utf8_percent_encode(&name, RFC_3986),
|
||||
)));
|
||||
|
||||
if account_id == access_token.primary_id() {
|
||||
for account_id in access_token.all_ids_by_collection(collection) {
|
||||
if account_id != access_token.primary_id() {
|
||||
let other_name = self
|
||||
.store()
|
||||
.get_principal_name(account_id)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
.unwrap_or_else(|| format!("_{account_id}"));
|
||||
|
||||
hrefs.push(Href(format!(
|
||||
"{}/{}/",
|
||||
resource_name.base_path(),
|
||||
percent_encoding::utf8_percent_encode(
|
||||
&other_name,
|
||||
RFC_3986
|
||||
),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
PrincipalProperty::CalendarHomeSet => {
|
||||
let hrefs =
|
||||
build_home_set(self, access_token, name.as_ref(), account_id, true)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
|
||||
fields.push(DavPropertyValue::new(property.clone(), hrefs));
|
||||
response.set_namespace(namespace);
|
||||
response.set_namespace(Namespace::CalDav);
|
||||
}
|
||||
PrincipalProperty::AddressbookHomeSet => {
|
||||
let hrefs = build_home_set(
|
||||
self,
|
||||
access_token,
|
||||
name.as_ref(),
|
||||
account_id,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
|
||||
fields.push(DavPropertyValue::new(property.clone(), hrefs));
|
||||
response.set_namespace(Namespace::CardDav);
|
||||
}
|
||||
|
||||
PrincipalProperty::PrincipalAddress => {
|
||||
|
@ -435,6 +409,48 @@ impl PrincipalPropFind for Server {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn build_home_set(
|
||||
server: &Server,
|
||||
access_token: &AccessToken,
|
||||
name: &str,
|
||||
account_id: u32,
|
||||
is_calendar: bool,
|
||||
) -> trc::Result<Vec<Href>> {
|
||||
let (collection, resource_name) = if is_calendar {
|
||||
(Collection::Calendar, DavResourceName::Cal)
|
||||
} else {
|
||||
(Collection::AddressBook, DavResourceName::Card)
|
||||
};
|
||||
|
||||
let mut hrefs = Vec::new();
|
||||
hrefs.push(Href(format!(
|
||||
"{}/{}/",
|
||||
resource_name.base_path(),
|
||||
percent_encoding::utf8_percent_encode(name, RFC_3986),
|
||||
)));
|
||||
|
||||
if account_id == access_token.primary_id() {
|
||||
for account_id in access_token.all_ids_by_collection(collection) {
|
||||
if account_id != access_token.primary_id() {
|
||||
let other_name = server
|
||||
.store()
|
||||
.get_principal_name(account_id)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
.unwrap_or_else(|| format!("_{account_id}"));
|
||||
|
||||
hrefs.push(Href(format!(
|
||||
"{}/{}/",
|
||||
resource_name.base_path(),
|
||||
percent_encoding::utf8_percent_encode(&other_name, RFC_3986),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(hrefs)
|
||||
}
|
||||
|
||||
fn all_props(collection: Collection, all_props: Option<&[DavProperty]>) -> Vec<DavProperty> {
|
||||
if collection == Collection::Principal {
|
||||
vec![
|
||||
|
|
|
@ -209,13 +209,19 @@ pub async fn test(test: &WebDavTest) {
|
|||
.with_status(StatusCode::OK);
|
||||
props
|
||||
.get(DavProperty::Principal(PrincipalProperty::CalendarHomeSet))
|
||||
.with_values([format!("D:href:{}/jane/", DavResourceName::Cal.base_path()).as_str()])
|
||||
.with_values([
|
||||
format!("D:href:{}/jane/", DavResourceName::Cal.base_path()).as_str(),
|
||||
format!("D:href:{}/support/", DavResourceName::Cal.base_path()).as_str(),
|
||||
])
|
||||
.with_status(StatusCode::OK);
|
||||
props
|
||||
.get(DavProperty::Principal(
|
||||
PrincipalProperty::AddressbookHomeSet,
|
||||
))
|
||||
.with_values([format!("D:href:{}/jane/", DavResourceName::Card.base_path()).as_str()])
|
||||
.with_values([
|
||||
format!("D:href:{}/jane/", DavResourceName::Card.base_path()).as_str(),
|
||||
format!("D:href:{}/support/", DavResourceName::Card.base_path()).as_str(),
|
||||
])
|
||||
.with_status(StatusCode::OK);
|
||||
|
||||
for (account, _, name, _) in TEST_USERS
|
||||
|
|
Loading…
Add table
Reference in a new issue