mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 17:52:24 +00:00
Make prefix a parameter to decrease chaos
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>(
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user