Skip to main content

rustical_dav/resources/
root.rs

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