Refactoring: Lots of fixes still necessary to get it into a working state

This commit is contained in:
Lennart
2024-05-25 22:00:09 +02:00
parent 35acfe1575
commit 7a0a91f823
14 changed files with 470 additions and 223 deletions

View File

@@ -2,11 +2,9 @@ use actix_web::{web::Data, HttpRequest};
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use rustical_auth::AuthInfo;
use rustical_dav::dav_resource::{Resource, ResourceService};
use rustical_dav::error::Error;
use rustical_dav::{
resource::Resource,
xml_snippets::{HrefElement, TextNode},
};
use rustical_dav::xml_snippets::{HrefElement, TextNode};
use rustical_store::calendar::{Calendar, CalendarStore};
use serde::Serialize;
use std::sync::Arc;
@@ -15,10 +13,10 @@ use tokio::sync::RwLock;
pub struct CalendarResource<C: CalendarStore + ?Sized> {
pub cal_store: Arc<RwLock<C>>,
pub calendar: Calendar,
pub path: String,
pub prefix: String,
pub principal: String,
pub calendar_id: String,
}
#[derive(Serialize)]
@@ -159,51 +157,17 @@ pub enum CalendarPropResponse {
CurrentUserPrivilegeSet(UserPrivilegeSet),
}
#[async_trait(?Send)]
impl<C: CalendarStore + ?Sized> Resource for CalendarResource<C> {
type MemberType = Self;
type UriComponents = (String, String); // principal, calendar_id
pub struct CalendarFile {
pub calendar: Calendar,
pub principal: String,
pub prefix: String,
pub path: String,
}
impl Resource for CalendarFile {
type PropType = CalendarProp;
type PropResponse = CalendarPropResponse;
async fn acquire_from_request(
req: HttpRequest,
_auth_info: AuthInfo,
uri_components: Self::UriComponents,
prefix: String,
) -> Result<Self, Error> {
let cal_store = req
.app_data::<Data<RwLock<C>>>()
.ok_or(anyhow!("no calendar store in app_data!"))?
.clone()
.into_inner();
let (principal, cid) = uri_components;
// TODO: fix errors
let calendar = cal_store
.read()
.await
.get_calendar(&cid)
.await
.map_err(|_e| Error::NotFound)?;
Ok(Self {
cal_store,
calendar,
path: req.path().to_string(),
prefix,
principal,
})
}
fn get_path(&self) -> &str {
&self.path
}
async fn get_members(&self) -> Result<Vec<Self::MemberType>> {
// As of now the calendar resource has no members
Ok(vec![])
}
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse> {
match prop {
CalendarProp::Resourcetype => {
@@ -246,4 +210,61 @@ impl<C: CalendarStore + ?Sized> Resource for CalendarResource<C> {
),
}
}
fn get_path(&self) -> &str {
&self.path
}
}
#[async_trait(?Send)]
impl<C: CalendarStore + ?Sized> ResourceService for CalendarResource<C> {
type MemberType = CalendarFile;
type PathComponents = (String, String); // principal, calendar_id
type File = CalendarFile;
async fn get_file(&self) -> Result<Self::File> {
let calendar = self
.cal_store
.read()
.await
.get_calendar(&self.calendar_id)
.await
.map_err(|_e| Error::NotFound)?;
Ok(CalendarFile {
calendar,
prefix: self.prefix.to_owned(),
principal: self.principal.to_owned(),
path: self.path.to_owned(),
})
}
async fn get_members(
&self,
_auth_info: AuthInfo,
_path_components: Self::PathComponents,
) -> Result<Vec<Self::MemberType>> {
// As of now the calendar resource has no members
Ok(vec![])
}
async fn new(
req: HttpRequest,
auth_info: AuthInfo,
path_components: Self::PathComponents,
prefix: String,
) -> Result<Self, rustical_dav::error::Error> {
let cal_store = req
.app_data::<Data<RwLock<C>>>()
.ok_or(anyhow!("no calendar store in app_data!"))?
.clone()
.into_inner();
Ok(Self {
prefix,
path: req.path().to_owned(),
principal: auth_info.user_id,
calendar_id: path_components.1,
cal_store,
})
}
}

View File

@@ -2,8 +2,9 @@ use actix_web::{web::Data, HttpRequest};
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use rustical_auth::AuthInfo;
use rustical_dav::error::Error;
use rustical_dav::{resource::Resource, xml_snippets::TextNode};
use rustical_dav::dav_resource::Resource;
use rustical_dav::xml_snippets::TextNode;
use rustical_dav::{dav_resource::ResourceService, error::Error};
use rustical_store::calendar::CalendarStore;
use rustical_store::event::Event;
use serde::Serialize;
@@ -14,7 +15,8 @@ use tokio::sync::RwLock;
pub struct EventResource<C: CalendarStore + ?Sized> {
pub cal_store: Arc<RwLock<C>>,
pub path: String,
pub event: Event,
pub cid: String,
pub uid: String,
}
#[derive(EnumString, Debug, VariantNames, IntoStaticStr, Clone)]
@@ -33,42 +35,16 @@ pub enum PrincipalPropResponse {
Getcontenttype(TextNode),
}
#[async_trait(?Send)]
impl<C: CalendarStore + ?Sized> Resource for EventResource<C> {
type UriComponents = (String, String, String); // principal, calendar, event
type MemberType = Self;
pub struct EventFile {
pub event: Event,
}
impl Resource for EventFile {
type PropType = EventProp;
type PropResponse = PrincipalPropResponse;
fn get_path(&self) -> &str {
&self.path
}
async fn get_members(&self) -> Result<Vec<Self::MemberType>> {
Ok(vec![])
}
async fn acquire_from_request(
req: HttpRequest,
_auth_info: AuthInfo,
uri_components: Self::UriComponents,
_prefix: String,
) -> Result<Self, Error> {
let (_principal, cid, uid) = uri_components;
let cal_store = req
.app_data::<Data<RwLock<C>>>()
.ok_or(anyhow!("no calendar store in app_data!"))?
.clone()
.into_inner();
let event = cal_store.read().await.get_event(&cid, &uid).await?;
Ok(Self {
cal_store,
event,
path: req.path().to_string(),
})
"asd"
}
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse> {
@@ -77,7 +53,7 @@ impl<C: CalendarStore + ?Sized> Resource for EventResource<C> {
self.event.get_etag(),
)))),
EventProp::CalendarData => Ok(PrincipalPropResponse::CalendarData(TextNode(Some(
self.event.get_ics(),
self.event.get_ics().to_owned(),
)))),
EventProp::Getcontenttype => Ok(PrincipalPropResponse::Getcontenttype(TextNode(Some(
"text/calendar;charset=utf-8".to_owned(),
@@ -85,3 +61,52 @@ impl<C: CalendarStore + ?Sized> Resource for EventResource<C> {
}
}
}
#[async_trait(?Send)]
impl<C: CalendarStore + ?Sized> ResourceService for EventResource<C> {
type PathComponents = (String, String, String); // principal, calendar, event
type File = EventFile;
type MemberType = EventFile;
async fn get_members(
&self,
_auth_info: AuthInfo,
_path_components: Self::PathComponents,
) -> Result<Vec<Self::MemberType>> {
Ok(vec![])
}
async fn new(
req: HttpRequest,
_auth_info: AuthInfo,
path_components: Self::PathComponents,
_prefix: String,
) -> Result<Self, Error> {
let (_principal, cid, uid) = path_components;
let cal_store = req
.app_data::<Data<RwLock<C>>>()
.ok_or(anyhow!("no calendar store in app_data!"))?
.clone()
.into_inner();
// let event = cal_store.read().await.get_event(&cid, &uid).await?;
Ok(Self {
cal_store,
cid,
uid,
path: req.path().to_string(),
})
}
async fn get_file(&self) -> Result<Self::File> {
let event = self
.cal_store
.read()
.await
.get_event(&self.cid, &self.uid)
.await?;
Ok(EventFile { event })
}
}

View File

@@ -1,24 +1,32 @@
use actix_web::{web::Data, HttpRequest};
use std::sync::Arc;
use actix_web::web::Data;
use actix_web::HttpRequest;
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use rustical_auth::AuthInfo;
use rustical_dav::error::Error;
use rustical_dav::{resource::Resource, xml_snippets::HrefElement};
use rustical_dav::dav_resource::{Resource, ResourceService};
use rustical_dav::xml_snippets::HrefElement;
use rustical_store::calendar::CalendarStore;
use serde::Serialize;
use std::sync::Arc;
use strum::{EnumString, IntoStaticStr, VariantNames};
use tokio::sync::RwLock;
use super::calendar::CalendarResource;
use super::calendar::CalendarFile;
pub struct PrincipalCalendarsResource<C: CalendarStore + ?Sized> {
pub struct PrincipalResource<C: CalendarStore + ?Sized> {
prefix: String,
principal: String,
path: String,
cal_store: Arc<RwLock<C>>,
}
pub struct PrincipalFile {
prefix: String,
principal: String,
path: String,
}
#[derive(Serialize, Default)]
#[serde(rename_all = "kebab-case")]
pub struct Resourcetype {
@@ -51,55 +59,10 @@ pub enum PrincipalProp {
}
#[async_trait(?Send)]
impl<C: CalendarStore + ?Sized> Resource for PrincipalCalendarsResource<C> {
type UriComponents = ();
type MemberType = CalendarResource<C>;
impl Resource for PrincipalFile {
type PropType = PrincipalProp;
type PropResponse = PrincipalPropResponse;
fn get_path(&self) -> &str {
&self.path
}
async fn get_members(&self) -> Result<Vec<Self::MemberType>> {
let calendars = self
.cal_store
.read()
.await
.get_calendars(&self.principal)
.await?;
let mut out = Vec::new();
for calendar in calendars {
let path = format!("{}/{}", &self.path, &calendar.id);
out.push(CalendarResource {
cal_store: self.cal_store.clone(),
calendar,
path,
prefix: self.prefix.clone(),
principal: self.principal.clone(),
})
}
Ok(out)
}
async fn acquire_from_request(
req: HttpRequest,
auth_info: AuthInfo,
_uri_components: Self::UriComponents,
prefix: String,
) -> Result<Self, Error> {
let cal_store = req
.app_data::<Data<RwLock<C>>>()
.ok_or(anyhow!("no calendar store in app_data!"))?
.clone()
.into_inner();
Ok(Self {
cal_store,
prefix,
principal: auth_info.user_id,
path: req.path().to_string(),
})
}
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse> {
match prop {
PrincipalProp::Resourcetype => {
@@ -121,4 +84,65 @@ impl<C: CalendarStore + ?Sized> Resource for PrincipalCalendarsResource<C> {
}
}
}
fn get_path(&self) -> &str {
&self.path
}
}
#[async_trait(?Send)]
impl<C: CalendarStore + ?Sized> ResourceService for PrincipalResource<C> {
type PathComponents = (String,);
type MemberType = CalendarFile;
type File = PrincipalFile;
async fn new(
req: HttpRequest,
auth_info: AuthInfo,
_path_components: Self::PathComponents,
prefix: String,
) -> Result<Self, rustical_dav::error::Error> {
let cal_store = req
.app_data::<Data<RwLock<C>>>()
.ok_or(anyhow!("no calendar store in app_data!"))?
.clone()
.into_inner();
Ok(Self {
cal_store,
path: req.path().to_owned(),
principal: auth_info.user_id,
prefix,
})
}
async fn get_file(&self) -> Result<Self::File> {
Ok(PrincipalFile {
principal: self.principal.to_owned(),
prefix: self.prefix.to_owned(),
path: self.path.to_owned(),
})
}
async fn get_members(
&self,
_auth_info: AuthInfo,
_path_components: Self::PathComponents,
) -> Result<Vec<Self::MemberType>> {
let calendars = self
.cal_store
.read()
.await
.get_calendars(&self.principal)
.await?;
Ok(calendars
.into_iter()
.map(|cal| CalendarFile {
calendar: cal,
principal: self.principal.to_owned(),
prefix: self.prefix.to_owned(),
path: self.path.to_owned(),
})
.collect())
}
}

View File

@@ -2,8 +2,9 @@ use actix_web::HttpRequest;
use anyhow::Result;
use async_trait::async_trait;
use rustical_auth::AuthInfo;
use rustical_dav::dav_resource::{Resource, ResourceService};
use rustical_dav::error::Error;
use rustical_dav::{resource::Resource, xml_snippets::HrefElement};
use rustical_dav::xml_snippets::HrefElement;
use serde::Serialize;
use strum::{EnumString, IntoStaticStr, VariantNames};
@@ -33,34 +34,16 @@ pub enum RootPropResponse {
CurrentUserPrincipal(HrefElement),
}
#[async_trait(?Send)]
impl Resource for RootResource {
type UriComponents = ();
type MemberType = Self;
pub struct RootFile {
pub prefix: String,
pub principal: String,
pub path: String,
}
impl Resource for RootFile {
type PropType = RootProp;
type PropResponse = RootPropResponse;
fn get_path(&self) -> &str {
&self.path
}
async fn get_members(&self) -> Result<Vec<Self::MemberType>> {
Ok(vec![])
}
async fn acquire_from_request(
req: HttpRequest,
auth_info: AuthInfo,
_uri_components: Self::UriComponents,
prefix: String,
) -> Result<Self, Error> {
Ok(Self {
prefix,
principal: auth_info.user_id,
path: req.path().to_string(),
})
}
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse> {
match prop {
RootProp::Resourcetype => Ok(RootPropResponse::Resourcetype(Resourcetype::default())),
@@ -69,4 +52,44 @@ impl Resource for RootResource {
)),
}
}
fn get_path(&self) -> &str {
&self.path
}
}
#[async_trait(?Send)]
impl ResourceService for RootResource {
type PathComponents = ();
type MemberType = RootFile;
type File = RootFile;
async fn get_members(
&self,
_auth_info: AuthInfo,
_path_components: Self::PathComponents,
) -> Result<Vec<Self::MemberType>> {
Ok(vec![])
}
async fn new(
req: HttpRequest,
auth_info: AuthInfo,
_path_components: Self::PathComponents,
prefix: String,
) -> Result<Self, Error> {
Ok(Self {
prefix,
principal: auth_info.user_id,
path: req.path().to_string(),
})
}
async fn get_file(&self) -> Result<Self::File> {
Ok(RootFile {
path: self.path.to_owned(),
principal: self.principal.to_owned(),
prefix: self.prefix.to_owned(),
})
}
}