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 let vapid_pubkey = self.dav_push_store.get_vapid_pubkey_b64().await?.clone();
73 Ok(CalendarResource {
74 cal: calendar,
75 read_only: self.cal_store.is_read_only(cal_id),
76 vapid_pubkey,
77 })
78 }
79
80 async fn get_members(
81 &self,
82 (principal, cal_id): &Self::PathComponents,
83 ) -> Result<Vec<Self::MemberType>, Self::Error> {
84 Ok(self
85 .cal_store
86 .get_objects(principal, cal_id)
87 .await?
88 .into_iter()
89 .map(|(object_id, object)| CalendarObjectResource {
90 object,
91 object_id,
92 principal: principal.to_owned(),
93 })
94 .collect())
95 }
96
97 async fn save_resource(
98 &self,
99 (principal, cal_id): &Self::PathComponents,
100 file: Self::Resource,
101 ) -> Result<(), Self::Error> {
102 self.cal_store
103 .update_calendar(principal, cal_id, file.into())
104 .await?;
105 Ok(())
106 }
107
108 async fn delete_resource(
109 &self,
110 (principal, cal_id): &Self::PathComponents,
111 use_trashbin: bool,
112 ) -> Result<(), Self::Error> {
113 self.cal_store
114 .delete_calendar(principal, cal_id, use_trashbin)
115 .await?;
116 Ok(())
117 }
118
119 fn axum_router<State: Send + Sync + Clone + 'static>(self) -> axum::Router<State> {
120 Router::new()
121 .nest(
122 "/{object_id}",
123 CalendarObjectResourceService::new(self.cal_store.clone(), self.config.clone())
124 .axum_router(),
125 )
126 .route_service("/", self.axum_service())
127 }
128}
129
130impl<C: CalendarStore, DP: DavPushStore> AxumMethods for CalendarResourceService<C, DP> {
131 fn report() -> Option<MethodFunction<Self>> {
132 Some(|state, req| {
133 let mut service = Handler::with_state(route_report_calendar::<C, DP>, state);
134 Box::pin(Service::call(&mut service, req))
135 })
136 }
137
138 fn get() -> Option<MethodFunction<Self>> {
139 Some(|state, req| {
140 let mut service = Handler::with_state(route_get::<C, DP>, state);
141 Box::pin(Service::call(&mut service, req))
142 })
143 }
144
145 fn post() -> Option<MethodFunction<Self>> {
146 Some(|state, req| {
147 let mut service = Handler::with_state(route_post::<C, DP>, state);
148 Box::pin(Service::call(&mut service, req))
149 })
150 }
151
152 fn import() -> Option<MethodFunction<Self>> {
153 Some(|state, req| {
154 let mut service = Handler::with_state(route_import::<C, DP>, state);
155 Box::pin(Service::call(&mut service, req))
156 })
157 }
158
159 fn mkcalendar() -> Option<MethodFunction<Self>> {
160 Some(|state, req| {
161 let mut service = Handler::with_state(route_mkcalendar::<C, DP>, state);
162 Box::pin(Service::<Request<Body>>::call(&mut service, req))
163 })
164 }
165
166 fn mkcol() -> Option<MethodFunction<Self>> {
167 Some(|state, req| {
168 let mut service = Handler::with_state(route_mkcalendar::<C, DP>, state);
169 Box::pin(Service::<Request<Body>>::call(&mut service, req))
170 })
171 }
172}