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