rustical_dav/resource/
resource_service.rs1use actix_web::dev::{AppService, HttpServiceFactory};
2use actix_web::error::UrlGenerationError;
3use actix_web::test::TestRequest;
4use actix_web::web::Data;
5use actix_web::{ResponseError, dev::ResourceMap, http::Method, web};
6use async_trait::async_trait;
7use serde::Deserialize;
8use std::str::FromStr;
9
10use crate::Principal;
11
12use super::Resource;
13use super::methods::{route_delete, route_propfind, route_proppatch};
14
15#[async_trait(?Send)]
16pub trait ResourceService: Sized + 'static {
17 type MemberType: Resource<Error = Self::Error, Principal = Self::Principal>;
18 type PathComponents: for<'de> Deserialize<'de> + Sized + Clone + 'static; type Resource: Resource<Error = Self::Error, Principal = Self::Principal>;
20 type Error: ResponseError + From<crate::Error>;
21 type Principal: Principal;
22
23 async fn get_members(
24 &self,
25 _path_components: &Self::PathComponents,
26 ) -> Result<Vec<(String, Self::MemberType)>, Self::Error> {
27 Ok(vec![])
28 }
29
30 async fn get_resource(
31 &self,
32 _path: &Self::PathComponents,
33 ) -> Result<Self::Resource, Self::Error>;
34 async fn save_resource(
35 &self,
36 _path: &Self::PathComponents,
37 _file: Self::Resource,
38 ) -> Result<(), Self::Error> {
39 Err(crate::Error::Unauthorized.into())
40 }
41 async fn delete_resource(
42 &self,
43 _path: &Self::PathComponents,
44 _use_trashbin: bool,
45 ) -> Result<(), Self::Error> {
46 Err(crate::Error::Unauthorized.into())
47 }
48
49 #[inline]
50 fn actix_resource(self) -> actix_web::Resource {
51 Self::actix_additional_routes(
52 web::resource("")
53 .app_data(Data::new(self))
54 .route(
55 web::method(Method::from_str("PROPFIND").unwrap()).to(route_propfind::<Self>),
56 )
57 .route(
58 web::method(Method::from_str("PROPPATCH").unwrap()).to(route_proppatch::<Self>),
59 )
60 .delete(route_delete::<Self>),
61 )
62 }
63
64 #[inline]
66 fn actix_additional_routes(res: actix_web::Resource) -> actix_web::Resource {
67 res
68 }
69}
70
71pub trait NamedRoute {
72 fn route_name() -> &'static str;
73
74 fn get_url<U, I>(rmap: &ResourceMap, elements: U) -> Result<String, UrlGenerationError>
75 where
76 U: IntoIterator<Item = I>,
77 I: AsRef<str>,
78 {
79 Ok(rmap
80 .url_for(
81 &TestRequest::default().to_http_request(),
82 Self::route_name(),
83 elements,
84 )?
85 .path()
86 .to_owned())
87 }
88}
89
90pub struct ResourceServiceRoute<RS: ResourceService>(pub RS);
91
92impl<RS: ResourceService> HttpServiceFactory for ResourceServiceRoute<RS> {
93 fn register(self, config: &mut AppService) {
94 self.0.actix_resource().register(config);
95 }
96}