Skip to main content

rustical_caldav/principal/
service.rs

1use crate::calendar::CalendarResourceService;
2use crate::calendar::resource::CalendarResource;
3use crate::principal::PrincipalResource;
4use crate::{CalDavConfig, CalDavPrincipalUri, Error};
5use async_trait::async_trait;
6use axum::Router;
7use rustical_dav::resource::{AxumMethods, ResourceService};
8use rustical_dav_push::DavPushStore;
9use rustical_store::CalendarStore;
10use rustical_store::auth::{AuthenticationProvider, Principal};
11use std::sync::Arc;
12
13#[derive(Debug)]
14pub struct PrincipalResourceService<AP: AuthenticationProvider, DP: DavPushStore, CS: CalendarStore>
15{
16    pub(crate) auth_provider: Arc<AP>,
17    pub(crate) dav_push_store: Arc<DP>,
18    pub(crate) cal_store: Arc<CS>,
19    // If true only return the principal as the calendar home set, otherwise also groups
20    pub(crate) simplified_home_set: bool,
21    pub(crate) config: Arc<CalDavConfig>,
22}
23
24impl<AP: AuthenticationProvider, DP: DavPushStore, CS: CalendarStore> Clone
25    for PrincipalResourceService<AP, DP, CS>
26{
27    fn clone(&self) -> Self {
28        Self {
29            auth_provider: self.auth_provider.clone(),
30            dav_push_store: self.dav_push_store.clone(),
31            cal_store: self.cal_store.clone(),
32            simplified_home_set: self.simplified_home_set,
33            config: self.config.clone(),
34        }
35    }
36}
37
38#[async_trait]
39impl<AP: AuthenticationProvider, DP: DavPushStore, CS: CalendarStore> ResourceService
40    for PrincipalResourceService<AP, DP, CS>
41{
42    type PathComponents = (String,);
43    type MemberType = CalendarResource;
44    type Resource = PrincipalResource;
45    type Error = Error;
46    type Principal = Principal;
47    type PrincipalUri = CalDavPrincipalUri;
48
49    const DAV_HEADER: &str = "1, 3, access-control, calendar-access";
50
51    async fn get_resource(
52        &self,
53        (principal,): &Self::PathComponents,
54        _show_deleted: bool,
55    ) -> Result<Self::Resource, Self::Error> {
56        let user = self
57            .auth_provider
58            .get_principal(principal)
59            .await?
60            .ok_or(crate::Error::NotFound)?;
61        Ok(PrincipalResource {
62            members: self.auth_provider.list_members(&user.id).await?,
63            principal: user,
64            simplified_home_set: self.simplified_home_set,
65        })
66    }
67
68    async fn get_members(
69        &self,
70        (principal,): &Self::PathComponents,
71    ) -> Result<Vec<Self::MemberType>, Self::Error> {
72        let calendars = self.cal_store.get_calendars(principal).await?;
73
74        Ok(calendars
75            .into_iter()
76            .map(|cal| CalendarResource {
77                read_only: self.cal_store.is_read_only(&cal.id),
78                cal,
79            })
80            .collect())
81    }
82
83    fn axum_router<State: Send + Sync + Clone + 'static>(self) -> axum::Router<State> {
84        Router::new()
85            .nest(
86                "/{calendar_id}",
87                CalendarResourceService::new(
88                    self.cal_store.clone(),
89                    self.dav_push_store.clone(),
90                    self.config.clone(),
91                )
92                .axum_router(),
93            )
94            .route_service("/", self.axum_service())
95    }
96}
97
98impl<AP: AuthenticationProvider, DP: DavPushStore, CS: CalendarStore> AxumMethods
99    for PrincipalResourceService<AP, DP, CS>
100{
101}