Make prefix a parameter to decrease chaos

This commit is contained in:
Lennart
2024-05-25 22:19:38 +02:00
parent d0f652a951
commit 38f5338ceb
7 changed files with 24 additions and 37 deletions

View File

@@ -14,7 +14,6 @@ use tokio::sync::RwLock;
pub struct CalendarResource<C: CalendarStore + ?Sized> { pub struct CalendarResource<C: CalendarStore + ?Sized> {
pub cal_store: Arc<RwLock<C>>, pub cal_store: Arc<RwLock<C>>,
pub path: String, pub path: String,
pub prefix: String,
pub principal: String, pub principal: String,
pub calendar_id: String, pub calendar_id: String,
} }
@@ -160,7 +159,6 @@ pub enum CalendarPropResponse {
pub struct CalendarFile { pub struct CalendarFile {
pub calendar: Calendar, pub calendar: Calendar,
pub principal: String, pub principal: String,
pub prefix: String,
pub path: String, pub path: String,
} }
@@ -168,17 +166,17 @@ impl Resource for CalendarFile {
type PropType = CalendarProp; type PropType = CalendarProp;
type PropResponse = CalendarPropResponse; type PropResponse = CalendarPropResponse;
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse> { fn get_prop(&self, prefix: &str, prop: Self::PropType) -> Result<Self::PropResponse> {
match prop { match prop {
CalendarProp::Resourcetype => { CalendarProp::Resourcetype => {
Ok(CalendarPropResponse::Resourcetype(Resourcetype::default())) Ok(CalendarPropResponse::Resourcetype(Resourcetype::default()))
} }
CalendarProp::CurrentUserPrincipal => Ok(CalendarPropResponse::CurrentUserPrincipal( CalendarProp::CurrentUserPrincipal => Ok(CalendarPropResponse::CurrentUserPrincipal(
HrefElement::new(format!("{}/{}/", self.prefix, self.principal)), HrefElement::new(format!("{}/{}/", prefix, self.principal)),
)), )),
CalendarProp::Owner => Ok(CalendarPropResponse::Owner(HrefElement::new(format!( CalendarProp::Owner => Ok(CalendarPropResponse::Owner(HrefElement::new(format!(
"{}/{}/", "{}/{}/",
self.prefix, self.principal prefix, self.principal
)))), )))),
CalendarProp::Displayname => Ok(CalendarPropResponse::Displayname(TextNode( CalendarProp::Displayname => Ok(CalendarPropResponse::Displayname(TextNode(
self.calendar.name.clone(), self.calendar.name.clone(),
@@ -232,7 +230,6 @@ impl<C: CalendarStore + ?Sized> ResourceService for CalendarResource<C> {
.map_err(|_e| Error::NotFound)?; .map_err(|_e| Error::NotFound)?;
Ok(CalendarFile { Ok(CalendarFile {
calendar, calendar,
prefix: self.prefix.to_owned(),
principal: self.principal.to_owned(), principal: self.principal.to_owned(),
path: self.path.to_owned(), path: self.path.to_owned(),
}) })
@@ -247,7 +244,6 @@ impl<C: CalendarStore + ?Sized> ResourceService for CalendarResource<C> {
req: HttpRequest, req: HttpRequest,
auth_info: AuthInfo, auth_info: AuthInfo,
path_components: Self::PathComponents, path_components: Self::PathComponents,
prefix: String,
) -> Result<Self, rustical_dav::error::Error> { ) -> Result<Self, rustical_dav::error::Error> {
let cal_store = req let cal_store = req
.app_data::<Data<RwLock<C>>>() .app_data::<Data<RwLock<C>>>()
@@ -256,7 +252,6 @@ impl<C: CalendarStore + ?Sized> ResourceService for CalendarResource<C> {
.into_inner(); .into_inner();
Ok(Self { Ok(Self {
prefix,
path: req.path().to_owned(), path: req.path().to_owned(),
principal: auth_info.user_id, principal: auth_info.user_id,
calendar_id: path_components.1, calendar_id: path_components.1,

View File

@@ -47,7 +47,7 @@ impl Resource for EventFile {
"asd" "asd"
} }
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse> { fn get_prop(&self, _prefix: &str, prop: Self::PropType) -> Result<Self::PropResponse> {
match prop { match prop {
EventProp::Getetag => Ok(PrincipalPropResponse::Getetag(TextNode(Some( EventProp::Getetag => Ok(PrincipalPropResponse::Getetag(TextNode(Some(
self.event.get_etag(), self.event.get_etag(),
@@ -76,7 +76,6 @@ impl<C: CalendarStore + ?Sized> ResourceService for EventResource<C> {
req: HttpRequest, req: HttpRequest,
_auth_info: AuthInfo, _auth_info: AuthInfo,
path_components: Self::PathComponents, path_components: Self::PathComponents,
_prefix: String,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let (_principal, cid, uid) = path_components; let (_principal, cid, uid) = path_components;

View File

@@ -15,14 +15,12 @@ use tokio::sync::RwLock;
use super::calendar::CalendarFile; use super::calendar::CalendarFile;
pub struct PrincipalResource<C: CalendarStore + ?Sized> { pub struct PrincipalResource<C: CalendarStore + ?Sized> {
prefix: String,
principal: String, principal: String,
path: String, path: String,
cal_store: Arc<RwLock<C>>, cal_store: Arc<RwLock<C>>,
} }
pub struct PrincipalFile { pub struct PrincipalFile {
prefix: String,
principal: String, principal: String,
path: String, path: String,
} }
@@ -63,23 +61,23 @@ impl Resource for PrincipalFile {
type PropType = PrincipalProp; type PropType = PrincipalProp;
type PropResponse = PrincipalPropResponse; type PropResponse = PrincipalPropResponse;
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse> { fn get_prop(&self, prefix: &str, prop: Self::PropType) -> Result<Self::PropResponse> {
match prop { match prop {
PrincipalProp::Resourcetype => { PrincipalProp::Resourcetype => {
Ok(PrincipalPropResponse::Resourcetype(Resourcetype::default())) Ok(PrincipalPropResponse::Resourcetype(Resourcetype::default()))
} }
PrincipalProp::CurrentUserPrincipal => Ok(PrincipalPropResponse::CurrentUserPrincipal( PrincipalProp::CurrentUserPrincipal => Ok(PrincipalPropResponse::CurrentUserPrincipal(
HrefElement::new(format!("{}/{}/", self.prefix, self.principal)), HrefElement::new(format!("{}/{}/", prefix, self.principal)),
)), )),
PrincipalProp::PrincipalUrl => Ok(PrincipalPropResponse::PrincipalUrl( PrincipalProp::PrincipalUrl => Ok(PrincipalPropResponse::PrincipalUrl(
HrefElement::new(format!("{}/{}/", self.prefix, self.principal)), HrefElement::new(format!("{}/{}/", prefix, self.principal)),
)), )),
PrincipalProp::CalendarHomeSet => Ok(PrincipalPropResponse::CalendarHomeSet( PrincipalProp::CalendarHomeSet => Ok(PrincipalPropResponse::CalendarHomeSet(
HrefElement::new(format!("{}/{}/", self.prefix, self.principal)), HrefElement::new(format!("{}/{}/", prefix, self.principal)),
)), )),
PrincipalProp::CalendarUserAddressSet => { PrincipalProp::CalendarUserAddressSet => {
Ok(PrincipalPropResponse::CalendarUserAddressSet( Ok(PrincipalPropResponse::CalendarUserAddressSet(
HrefElement::new(format!("{}/{}/", self.prefix, self.principal)), HrefElement::new(format!("{}/{}/", prefix, self.principal)),
)) ))
} }
} }
@@ -100,7 +98,6 @@ impl<C: CalendarStore + ?Sized> ResourceService for PrincipalResource<C> {
req: HttpRequest, req: HttpRequest,
auth_info: AuthInfo, auth_info: AuthInfo,
_path_components: Self::PathComponents, _path_components: Self::PathComponents,
prefix: String,
) -> Result<Self, rustical_dav::error::Error> { ) -> Result<Self, rustical_dav::error::Error> {
let cal_store = req let cal_store = req
.app_data::<Data<RwLock<C>>>() .app_data::<Data<RwLock<C>>>()
@@ -112,14 +109,12 @@ impl<C: CalendarStore + ?Sized> ResourceService for PrincipalResource<C> {
cal_store, cal_store,
path: req.path().to_owned(), path: req.path().to_owned(),
principal: auth_info.user_id, principal: auth_info.user_id,
prefix,
}) })
} }
async fn get_file(&self) -> Result<Self::File> { async fn get_file(&self) -> Result<Self::File> {
Ok(PrincipalFile { Ok(PrincipalFile {
principal: self.principal.to_owned(), principal: self.principal.to_owned(),
prefix: self.prefix.to_owned(),
path: self.path.to_owned(), path: self.path.to_owned(),
}) })
} }
@@ -136,7 +131,6 @@ impl<C: CalendarStore + ?Sized> ResourceService for PrincipalResource<C> {
.map(|cal| CalendarFile { .map(|cal| CalendarFile {
calendar: cal, calendar: cal,
principal: self.principal.to_owned(), principal: self.principal.to_owned(),
prefix: self.prefix.to_owned(),
path: self.path.to_owned(), path: self.path.to_owned(),
}) })
.collect()) .collect())

View File

@@ -9,7 +9,6 @@ use serde::Serialize;
use strum::{EnumString, IntoStaticStr, VariantNames}; use strum::{EnumString, IntoStaticStr, VariantNames};
pub struct RootResource { pub struct RootResource {
prefix: String,
principal: String, principal: String,
path: String, path: String,
} }
@@ -35,7 +34,6 @@ pub enum RootPropResponse {
} }
pub struct RootFile { pub struct RootFile {
pub prefix: String,
pub principal: String, pub principal: String,
pub path: String, pub path: String,
} }
@@ -44,11 +42,11 @@ impl Resource for RootFile {
type PropType = RootProp; type PropType = RootProp;
type PropResponse = RootPropResponse; type PropResponse = RootPropResponse;
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse> { fn get_prop(&self, prefix: &str, prop: Self::PropType) -> Result<Self::PropResponse> {
match prop { match prop {
RootProp::Resourcetype => Ok(RootPropResponse::Resourcetype(Resourcetype::default())), RootProp::Resourcetype => Ok(RootPropResponse::Resourcetype(Resourcetype::default())),
RootProp::CurrentUserPrincipal => Ok(RootPropResponse::CurrentUserPrincipal( RootProp::CurrentUserPrincipal => Ok(RootPropResponse::CurrentUserPrincipal(
HrefElement::new(format!("{}/{}/", self.prefix, self.principal)), HrefElement::new(format!("{}/{}/", prefix, self.principal)),
)), )),
} }
} }
@@ -72,10 +70,8 @@ impl ResourceService for RootResource {
req: HttpRequest, req: HttpRequest,
auth_info: AuthInfo, auth_info: AuthInfo,
_path_components: Self::PathComponents, _path_components: Self::PathComponents,
prefix: String,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
Ok(Self { Ok(Self {
prefix,
principal: auth_info.user_id, principal: auth_info.user_id,
path: req.path().to_string(), path: req.path().to_string(),
}) })
@@ -85,7 +81,6 @@ impl ResourceService for RootResource {
Ok(RootFile { Ok(RootFile {
path: self.path.to_owned(), path: self.path.to_owned(),
principal: self.principal.to_owned(), principal: self.principal.to_owned(),
prefix: self.prefix.to_owned(),
}) })
} }
} }

View File

@@ -9,6 +9,7 @@ use roxmltree::{Node, NodeType};
use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
use rustical_dav::dav_resource::HandlePropfind; use rustical_dav::dav_resource::HandlePropfind;
use rustical_dav::namespace::Namespace; use rustical_dav::namespace::Namespace;
use rustical_dav::propfind::ServicePrefix;
use rustical_dav::xml_snippets::generate_multistatus; use rustical_dav::xml_snippets::generate_multistatus;
use rustical_store::calendar::{Calendar, CalendarStore}; use rustical_store::calendar::{Calendar, CalendarStore};
use rustical_store::event::Event; use rustical_store::event::Event;
@@ -39,6 +40,7 @@ async fn handle_report_calendar_query<C: CalendarStore + ?Sized>(
_request: HttpRequest, _request: HttpRequest,
events: Vec<Event>, events: Vec<Event>,
_cal_store: Arc<RwLock<C>>, _cal_store: Arc<RwLock<C>>,
prefix: &str,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let prop_node = query_node let prop_node = query_node
.children() .children()
@@ -62,7 +64,7 @@ async fn handle_report_calendar_query<C: CalendarStore + ?Sized>(
.collect(); .collect();
let mut event_responses = Vec::new(); let mut event_responses = Vec::new();
for event_file in event_files { for event_file in event_files {
event_responses.push(event_file.propfind(props.clone()).await?); event_responses.push(event_file.propfind(prefix, props.clone()).await?);
} }
// let event_results: Result<Vec<_>, _> = event_files // let event_results: Result<Vec<_>, _> = event_files
// .iter() // .iter()
@@ -90,9 +92,11 @@ pub async fn route_report_calendar<A: CheckAuthentication, C: CalendarStore + ?S
path: Path<(String, String)>, path: Path<(String, String)>,
request: HttpRequest, request: HttpRequest,
_auth: AuthInfoExtractor<A>, _auth: AuthInfoExtractor<A>,
prefix: Data<ServicePrefix>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
// TODO: Check authorization // TODO: Check authorization
let (_principal, cid) = path.into_inner(); let (_principal, cid) = path.into_inner();
let prefix = &prefix.0;
let doc = roxmltree::Document::parse(&body).map_err(|_e| Error::BadRequest)?; let doc = roxmltree::Document::parse(&body).map_err(|_e| Error::BadRequest)?;
let query_node = doc.root_element(); let query_node = doc.root_element();
@@ -104,7 +108,7 @@ pub async fn route_report_calendar<A: CheckAuthentication, C: CalendarStore + ?S
"calendar-multiget" => {} "calendar-multiget" => {}
_ => return Err(Error::BadRequest), _ => return Err(Error::BadRequest),
}; };
handle_report_calendar_query(query_node, request, events, context.store.clone()).await handle_report_calendar_query(query_node, request, events, context.store.clone(), prefix).await
} }
pub async fn handle_mkcol_calendar_set<C: CalendarStore + ?Sized>( pub async fn handle_mkcol_calendar_set<C: CalendarStore + ?Sized>(

View File

@@ -17,7 +17,7 @@ pub trait Resource {
Self::PropType::VARIANTS Self::PropType::VARIANTS
} }
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse>; fn get_prop(&self, prefix: &str, prop: Self::PropType) -> Result<Self::PropResponse>;
fn get_path(&self) -> &str; fn get_path(&self) -> &str;
} }
@@ -36,7 +36,6 @@ pub trait ResourceService: Sized {
req: HttpRequest, req: HttpRequest,
auth_info: AuthInfo, auth_info: AuthInfo,
path_components: Self::PathComponents, path_components: Self::PathComponents,
prefix: String,
) -> Result<Self, Error>; ) -> Result<Self, Error>;
async fn get_file(&self) -> Result<Self::File>; async fn get_file(&self) -> Result<Self::File>;
@@ -73,13 +72,14 @@ enum PropstatType<T1: Serialize, T2: Serialize> {
#[async_trait(?Send)] #[async_trait(?Send)]
pub trait HandlePropfind { pub trait HandlePropfind {
async fn propfind(&self, props: Vec<&str>) -> Result<impl Serialize>; async fn propfind(&self, prefix: &str, props: Vec<&str>) -> Result<impl Serialize>;
} }
#[async_trait(?Send)] #[async_trait(?Send)]
impl<R: Resource> HandlePropfind for R { impl<R: Resource> HandlePropfind for R {
async fn propfind( async fn propfind(
&self, &self,
prefix: &str,
props: Vec<&str>, props: Vec<&str>,
) -> Result<PropstatResponseElement<PropWrapper<Vec<R::PropResponse>>, TagList>> { ) -> Result<PropstatResponseElement<PropWrapper<Vec<R::PropResponse>>, TagList>> {
let mut props = props.into_iter().unique().collect_vec(); let mut props = props.into_iter().unique().collect_vec();
@@ -95,7 +95,7 @@ impl<R: Resource> HandlePropfind for R {
let mut prop_responses = Vec::new(); let mut prop_responses = Vec::new();
for prop in props { for prop in props {
if let Ok(valid_prop) = R::PropType::from_str(prop) { if let Ok(valid_prop) = R::PropType::from_str(prop) {
match self.get_prop(valid_prop.clone()) { match self.get_prop(prefix, valid_prop.clone()) {
Ok(response) => { Ok(response) => {
prop_responses.push(response); prop_responses.push(response);
} }

View File

@@ -87,15 +87,15 @@ pub async fn handle_propfind<
let prefix = prefix.0.to_owned(); let prefix = prefix.0.to_owned();
let path_components = path.into_inner(); let path_components = path.into_inner();
let resource_service = R::new(req, auth_info.clone(), path_components.clone(), prefix).await?; let resource_service = R::new(req, auth_info.clone(), path_components.clone()).await?;
let resource = resource_service.get_file().await?; let resource = resource_service.get_file().await?;
let response = resource.propfind(props.clone()).await?; let response = resource.propfind(&prefix, props.clone()).await?;
let mut member_responses = Vec::new(); let mut member_responses = Vec::new();
if depth != Depth::Zero { if depth != Depth::Zero {
for member in resource_service.get_members(auth_info).await? { for member in resource_service.get_members(auth_info).await? {
member_responses.push(member.propfind(props.clone()).await?); member_responses.push(member.propfind(&prefix, props.clone()).await?);
} }
} }