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