use crate::{ CalDavPrincipalUri, Error, calendar_object::{ methods::{get_event, put_event}, resource::CalendarObjectResource, }, }; use async_trait::async_trait; use axum::{extract::Request, handler::Handler, response::Response}; use futures_util::future::BoxFuture; use rustical_dav::resource::{AxumMethods, ResourceService}; use rustical_store::{CalendarStore, auth::Principal}; use serde::{Deserialize, Deserializer}; use std::{convert::Infallible, sync::Arc}; use tower::Service; #[derive(Debug, Clone, Deserialize)] pub struct CalendarObjectPathComponents { pub principal: String, pub calendar_id: String, #[serde(deserialize_with = "deserialize_ics_name")] pub object_id: String, } pub struct CalendarObjectResourceService { pub(crate) cal_store: Arc, } impl Clone for CalendarObjectResourceService { fn clone(&self) -> Self { Self { cal_store: self.cal_store.clone(), } } } impl CalendarObjectResourceService { pub fn new(cal_store: Arc) -> Self { Self { cal_store } } } #[async_trait] impl ResourceService for CalendarObjectResourceService { type PathComponents = CalendarObjectPathComponents; type Resource = CalendarObjectResource; type MemberType = CalendarObjectResource; type Error = Error; type Principal = Principal; type PrincipalUri = CalDavPrincipalUri; const DAV_HEADER: &str = "1, 3, access-control, calendar-access"; async fn get_resource( &self, CalendarObjectPathComponents { principal, calendar_id, object_id, }: &Self::PathComponents, show_deleted: bool, ) -> Result { let object = self .cal_store .get_object(principal, calendar_id, object_id, show_deleted) .await?; Ok(CalendarObjectResource { object, principal: principal.to_owned(), }) } async fn delete_resource( &self, CalendarObjectPathComponents { principal, calendar_id, object_id, }: &Self::PathComponents, use_trashbin: bool, ) -> Result<(), Self::Error> { self.cal_store .delete_object(principal, calendar_id, object_id, use_trashbin) .await?; Ok(()) } } impl AxumMethods for CalendarObjectResourceService { fn get() -> Option BoxFuture<'static, Result>> { Some(|state, req| { let mut service = Handler::with_state(get_event::, state); Box::pin(Service::call(&mut service, req)) }) } fn put() -> Option BoxFuture<'static, Result>> { Some(|state, req| { let mut service = Handler::with_state(put_event::, state); Box::pin(Service::call(&mut service, req)) }) } } fn deserialize_ics_name<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let name: String = Deserialize::deserialize(deserializer)?; if let Some(object_id) = name.strip_suffix(".ics") { Ok(object_id.to_owned()) } else { Err(serde::de::Error::custom("Missing .ics extension")) } }