rustical_dav/resources/
root.rs

1use crate::Principal;
2use crate::extensions::{
3    CommonPropertiesExtension, CommonPropertiesProp, CommonPropertiesPropName,
4};
5use crate::privileges::UserPrivilegeSet;
6use crate::resource::{AxumMethods, PrincipalUri, Resource, ResourceName, ResourceService};
7use crate::xml::{Resourcetype, ResourcetypeInner};
8use async_trait::async_trait;
9use axum::Router;
10use axum::extract::FromRequestParts;
11use std::marker::PhantomData;
12
13#[derive(Clone)]
14pub struct RootResource<PR: Resource, P: Principal>(PhantomData<PR>, PhantomData<P>);
15
16impl<PR: Resource, P: Principal> Default for RootResource<PR, P> {
17    fn default() -> Self {
18        Self(PhantomData, PhantomData)
19    }
20}
21
22impl<PR: Resource, P: Principal> Resource for RootResource<PR, P> {
23    type Prop = CommonPropertiesProp;
24    type Error = PR::Error;
25    type Principal = P;
26
27    fn is_collection(&self) -> bool {
28        true
29    }
30
31    fn get_resourcetype(&self) -> Resourcetype {
32        Resourcetype(&[ResourcetypeInner(
33            Some(crate::namespace::NS_DAV),
34            "collection",
35        )])
36    }
37
38    fn get_displayname(&self) -> Option<&str> {
39        Some("RustiCal DAV root")
40    }
41
42    fn get_prop(
43        &self,
44        principal_uri: &impl PrincipalUri,
45        user: &P,
46        prop: &CommonPropertiesPropName,
47    ) -> Result<Self::Prop, Self::Error> {
48        CommonPropertiesExtension::get_prop(self, principal_uri, user, prop)
49    }
50
51    fn get_user_privileges(&self, _user: &P) -> Result<UserPrivilegeSet, Self::Error> {
52        Ok(UserPrivilegeSet::all())
53    }
54}
55
56#[derive(Clone)]
57pub struct RootResourceService<PRS: ResourceService + Clone, P: Principal, PURI: PrincipalUri>(
58    PRS,
59    PhantomData<P>,
60    PhantomData<PURI>,
61);
62
63impl<PRS: ResourceService + Clone, P: Principal, PURI: PrincipalUri>
64    RootResourceService<PRS, P, PURI>
65{
66    pub fn new(principal_resource_service: PRS) -> Self {
67        Self(principal_resource_service, PhantomData, PhantomData)
68    }
69}
70
71#[async_trait]
72impl<
73    PRS: ResourceService<Principal = P> + Clone,
74    P: Principal + FromRequestParts<Self>,
75    PURI: PrincipalUri,
76> ResourceService for RootResourceService<PRS, P, PURI>
77where
78    PRS::Resource: ResourceName,
79{
80    type PathComponents = ();
81    type MemberType = PRS::Resource;
82    type Resource = RootResource<PRS::Resource, P>;
83    type Error = PRS::Error;
84    type Principal = P;
85    type PrincipalUri = PURI;
86
87    const DAV_HEADER: &str = "1, 3, access-control";
88
89    async fn get_resource(
90        &self,
91        _: &(),
92        _show_deleted: bool,
93    ) -> Result<Self::Resource, Self::Error> {
94        Ok(RootResource::<PRS::Resource, P>::default())
95    }
96
97    fn axum_router<S: Send + Sync + Clone + 'static>(self) -> Router<S> {
98        Router::new()
99            .nest("/principal/{principal}", self.0.clone().axum_router())
100            .route_service("/", self.axum_service())
101    }
102}
103
104impl<PRS: ResourceService<Principal = P> + Clone, P: Principal, PURI: PrincipalUri> AxumMethods
105    for RootResourceService<PRS, P, PURI>
106{
107}