use crate::Error; use crate::header::Depth; use crate::privileges::UserPrivilege; use crate::resource::PrincipalUri; use crate::resource::Resource; use crate::resource::ResourceService; use crate::xml::MultistatusElement; use crate::xml::PropfindElement; use crate::xml::PropfindType; use axum::extract::{Extension, OriginalUri, Path, State}; use rustical_xml::PropName; use rustical_xml::XmlDocument; pub(crate) async fn axum_route_propfind( Path(path): Path, State(resource_service): State, depth: Depth, principal: R::Principal, uri: OriginalUri, Extension(puri): Extension, body: String, ) -> Result< MultistatusElement<::Prop, ::Prop>, R::Error, > { route_propfind::( &path, uri.path(), &body, &principal, &depth, &resource_service, &puri, ) .await } pub(crate) async fn route_propfind( path_components: &R::PathComponents, path: &str, body: &str, principal: &R::Principal, depth: &Depth, resource_service: &R, puri: &impl PrincipalUri, ) -> Result< MultistatusElement<::Prop, ::Prop>, R::Error, > { let resource = resource_service.get_resource(path_components).await?; let privileges = resource.get_user_privileges(principal)?; if !privileges.has(&UserPrivilege::Read) { return Err(Error::Unauthorized.into()); } // A request body is optional. If empty we MUST return all props let propfind_self: PropfindElement<<::Prop as PropName>::Names> = if !body.is_empty() { PropfindElement::parse_str(body).map_err(Error::XmlError)? } else { PropfindElement { prop: PropfindType::Allprop, } }; let propfind_member: PropfindElement<<::Prop as PropName>::Names> = if !body.is_empty() { PropfindElement::parse_str(body).map_err(Error::XmlError)? } else { PropfindElement { prop: PropfindType::Allprop, } }; let mut member_responses = Vec::new(); if depth != &Depth::Zero { for (subpath, member) in resource_service.get_members(path_components).await? { member_responses.push(member.propfind_typed( &format!("{}/{}", path.trim_end_matches('/'), subpath), &propfind_member.prop, puri, principal, )?); } } let response = resource.propfind_typed(path, &propfind_self.prop, puri, principal)?; Ok(MultistatusElement { responses: vec![response], member_responses, ..Default::default() }) }