rustical_caldav/calendar/
service.rs1use crate::calendar::methods::get::route_get;
2use crate::calendar::methods::import::route_import;
3use crate::calendar::methods::mkcalendar::route_mkcalendar;
4use crate::calendar::methods::post::route_post;
5use crate::calendar::methods::report::route_report_calendar;
6use crate::calendar::resource::CalendarResource;
7use crate::calendar_object::CalendarObjectResourceService;
8use crate::calendar_object::resource::CalendarObjectResource;
9use crate::{CalDavConfig, CalDavPrincipalUri, Error};
10use async_trait::async_trait;
11use axum::Router;
12use axum::extract::Request;
13use axum::handler::Handler;
14use axum::response::Response;
15use futures_util::future::BoxFuture;
16use rustical_dav::resource::{AxumMethods, ResourceService};
17use rustical_store::auth::Principal;
18use rustical_store::{CalendarStore, SubscriptionStore};
19use std::convert::Infallible;
20use std::sync::Arc;
21use tower::Service;
22
23pub struct CalendarResourceService<C: CalendarStore, S: SubscriptionStore> {
24 pub(crate) cal_store: Arc<C>,
25 pub(crate) sub_store: Arc<S>,
26 pub(crate) config: Arc<CalDavConfig>,
27}
28
29impl<C: CalendarStore, S: SubscriptionStore> Clone for CalendarResourceService<C, S> {
30 fn clone(&self) -> Self {
31 Self {
32 cal_store: self.cal_store.clone(),
33 sub_store: self.sub_store.clone(),
34 config: self.config.clone(),
35 }
36 }
37}
38
39impl<C: CalendarStore, S: SubscriptionStore> CalendarResourceService<C, S> {
40 pub const fn new(cal_store: Arc<C>, sub_store: Arc<S>, config: Arc<CalDavConfig>) -> Self {
41 Self {
42 cal_store,
43 sub_store,
44 config,
45 }
46 }
47}
48
49#[async_trait]
50impl<C: CalendarStore, S: SubscriptionStore> ResourceService for CalendarResourceService<C, S> {
51 type MemberType = CalendarObjectResource;
52 type PathComponents = (String, String); type Resource = CalendarResource;
54 type Error = Error;
55 type Principal = Principal;
56 type PrincipalUri = CalDavPrincipalUri;
57
58 const DAV_HEADER: &str = "1, 3, access-control, calendar-access, webdav-push";
59
60 async fn get_resource(
61 &self,
62 (principal, cal_id): &Self::PathComponents,
63 show_deleted: bool,
64 ) -> Result<Self::Resource, Error> {
65 let calendar = self
66 .cal_store
67 .get_calendar(principal, cal_id, show_deleted)
68 .await?;
69 Ok(CalendarResource {
70 cal: calendar,
71 read_only: self.cal_store.is_read_only(cal_id),
72 })
73 }
74
75 async fn get_members(
76 &self,
77 (principal, cal_id): &Self::PathComponents,
78 ) -> Result<Vec<Self::MemberType>, Self::Error> {
79 Ok(self
80 .cal_store
81 .get_objects(principal, cal_id)
82 .await?
83 .into_iter()
84 .map(|(object_id, object)| CalendarObjectResource {
85 object,
86 object_id,
87 principal: principal.to_owned(),
88 })
89 .collect())
90 }
91
92 async fn save_resource(
93 &self,
94 (principal, cal_id): &Self::PathComponents,
95 file: Self::Resource,
96 ) -> Result<(), Self::Error> {
97 self.cal_store
98 .update_calendar(principal, cal_id, file.into())
99 .await?;
100 Ok(())
101 }
102
103 async fn delete_resource(
104 &self,
105 (principal, cal_id): &Self::PathComponents,
106 use_trashbin: bool,
107 ) -> Result<(), Self::Error> {
108 self.cal_store
109 .delete_calendar(principal, cal_id, use_trashbin)
110 .await?;
111 Ok(())
112 }
113
114 fn axum_router<State: Send + Sync + Clone + 'static>(self) -> axum::Router<State> {
115 Router::new()
116 .nest(
117 "/{object_id}",
118 CalendarObjectResourceService::new(self.cal_store.clone(), self.config.clone())
119 .axum_router(),
120 )
121 .route_service("/", self.axum_service())
122 }
123}
124
125impl<C: CalendarStore, S: SubscriptionStore> AxumMethods for CalendarResourceService<C, S> {
126 fn report() -> Option<fn(Self, Request) -> BoxFuture<'static, Result<Response, Infallible>>> {
127 Some(|state, req| {
128 let mut service = Handler::with_state(route_report_calendar::<C, S>, state);
129 Box::pin(Service::call(&mut service, req))
130 })
131 }
132
133 fn get() -> Option<fn(Self, Request) -> BoxFuture<'static, Result<Response, Infallible>>> {
134 Some(|state, req| {
135 let mut service = Handler::with_state(route_get::<C, S>, state);
136 Box::pin(Service::call(&mut service, req))
137 })
138 }
139
140 fn post() -> Option<fn(Self, Request) -> BoxFuture<'static, Result<Response, Infallible>>> {
141 Some(|state, req| {
142 let mut service = Handler::with_state(route_post::<C, S>, state);
143 Box::pin(Service::call(&mut service, req))
144 })
145 }
146
147 fn import() -> Option<rustical_dav::resource::MethodFunction<Self>> {
148 Some(|state, req| {
149 let mut service = Handler::with_state(route_import::<C, S>, state);
150 Box::pin(Service::call(&mut service, req))
151 })
152 }
153
154 fn mkcalendar() -> Option<fn(Self, Request) -> BoxFuture<'static, Result<Response, Infallible>>>
155 {
156 Some(|state, req| {
157 let mut service = Handler::with_state(route_mkcalendar::<C, S>, state);
158 Box::pin(Service::call(&mut service, req))
159 })
160 }
161
162 fn mkcol() -> Option<fn(Self, Request) -> BoxFuture<'static, Result<Response, Infallible>>> {
163 Some(|state, req| {
164 let mut service = Handler::with_state(route_mkcalendar::<C, S>, state);
165 Box::pin(Service::call(&mut service, req))
166 })
167 }
168}