/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use super::propfind::PrincipalPropFind; use crate::{ DavError, common::{ DavQuery, DavQueryResource, propfind::PropFindRequestHandler, uri::{DavUriResource, UriResource}, }, }; use common::{Server, auth::AccessToken}; use dav_proto::{ RequestHeaders, schema::{ property::{DavProperty, WebDavProperty}, request::{PrincipalMatch, PropFind}, response::MultiStatus, }, }; use http_proto::HttpResponse; use hyper::StatusCode; use store::roaring::RoaringBitmap; use types::collection::Collection; pub(crate) trait PrincipalMatching: Sync + Send { fn handle_principal_match( &self, access_token: &AccessToken, headers: &RequestHeaders<'_>, request: PrincipalMatch, ) -> impl Future> + Send; } impl PrincipalMatching for Server { async fn handle_principal_match( &self, access_token: &AccessToken, headers: &RequestHeaders<'_>, mut request: PrincipalMatch, ) -> crate::Result { let resource = self.validate_uri(access_token, headers.uri).await?; match resource.collection { Collection::AddressBook | Collection::Calendar | Collection::FileNode => { if request.properties.is_empty() { request .properties .push(DavProperty::WebDav(WebDavProperty::Owner)); } if let Some(account_id) = resource.account_id { return self .handle_dav_query( access_token, DavQuery { resource: DavQueryResource::Uri(UriResource { collection: resource.collection, account_id, resource: resource.resource, }), propfind: PropFind::Prop(request.properties), depth: usize::MAX, ret: headers.ret, depth_no_root: headers.depth_no_root, uri: headers.uri, sync_type: Default::default(), limit: Default::default(), vcard_version: Default::default(), expand: Default::default(), }, ) .await; } } Collection::Principal => {} _ => return Err(DavError::Code(StatusCode::METHOD_NOT_ALLOWED)), } let mut response = MultiStatus::new(Vec::with_capacity(16)); if request.properties.is_empty() { request .properties .push(DavProperty::WebDav(WebDavProperty::DisplayName)); } let request = PropFind::Prop(request.properties); self.prepare_principal_propfind_response( access_token, resource.collection, RoaringBitmap::from_iter(access_token.all_ids()).into_iter(), &request, &mut response, ) .await?; Ok(HttpResponse::new(StatusCode::MULTI_STATUS).with_xml_body(response.to_string())) } }