diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index 6ecb958..4d6506c 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -2,10 +2,10 @@ use super::methods::mkcalendar::route_mkcalendar; use super::methods::post::route_post; use super::methods::report::route_report_calendar; use super::prop::{SupportedCalendarComponentSet, SupportedCalendarData, SupportedReportSet}; -use crate::calendar_object::resource::CalendarObjectResource; +use crate::calendar_object::resource::{CalendarObjectResource, CalendarObjectResourceService}; use crate::{CalDavPrincipalUri, Error}; use actix_web::http::Method; -use actix_web::web; +use actix_web::web::{self, Data}; use async_trait::async_trait; use chrono::{DateTime, Utc}; use derive_more::derive::{From, Into}; @@ -21,7 +21,6 @@ use rustical_store::auth::User; use rustical_store::{Calendar, CalendarStore, SubscriptionStore}; use rustical_xml::{EnumUnitVariants, EnumVariants}; use rustical_xml::{XmlDeserialize, XmlSerialize}; -use std::marker::PhantomData; use std::str::FromStr; use std::sync::Arc; @@ -311,14 +310,14 @@ impl Resource for CalendarResource { pub struct CalendarResourceService { cal_store: Arc, - __phantom_sub: PhantomData, + sub_store: Arc, } impl CalendarResourceService { - pub fn new(cal_store: Arc) -> Self { + pub fn new(cal_store: Arc, sub_store: Arc) -> Self { Self { cal_store, - __phantom_sub: PhantomData, + sub_store, } } } @@ -386,13 +385,17 @@ impl ResourceService for CalendarResourc Ok(()) } - #[inline] - fn actix_additional_routes(res: actix_web::Resource) -> actix_web::Resource { + fn actix_scope(self) -> actix_web::Scope { let report_method = web::method(Method::from_str("REPORT").unwrap()); let mkcalendar_method = web::method(Method::from_str("MKCALENDAR").unwrap()); - - res.route(report_method.to(route_report_calendar::)) - .route(mkcalendar_method.to(route_mkcalendar::)) - .post(route_post::) + web::scope("/{calendar_id}") + .app_data(Data::from(self.sub_store.clone())) + .service(CalendarObjectResourceService::new(self.cal_store.clone()).actix_scope()) + .service( + self.actix_resource() + .route(report_method.to(route_report_calendar::)) + .route(mkcalendar_method.to(route_mkcalendar::)) + .post(route_post::), + ) } } diff --git a/crates/caldav/src/calendar_object/resource.rs b/crates/caldav/src/calendar_object/resource.rs index 2bc0974..abf94b3 100644 --- a/crates/caldav/src/calendar_object/resource.rs +++ b/crates/caldav/src/calendar_object/resource.rs @@ -1,5 +1,6 @@ use super::methods::{get_event, put_event}; use crate::{CalDavPrincipalUri, Error}; +use actix_web::web; use async_trait::async_trait; use derive_more::derive::{From, Into}; use rustical_dav::{ @@ -149,8 +150,11 @@ impl ResourceService for CalendarObjectResourceService { Ok(()) } - #[inline] - fn actix_additional_routes(res: actix_web::Resource) -> actix_web::Resource { - res.get(get_event::).put(put_event::) + fn actix_scope(self) -> actix_web::Scope { + web::scope("/{object_id}.ics").service( + self.actix_resource() + .get(get_event::) + .put(put_event::), + ) } } diff --git a/crates/caldav/src/calendar_set/mod.rs b/crates/caldav/src/calendar_set/mod.rs index 5156a6f..2487154 100644 --- a/crates/caldav/src/calendar_set/mod.rs +++ b/crates/caldav/src/calendar_set/mod.rs @@ -1,12 +1,13 @@ -use crate::calendar::resource::CalendarResource; +use crate::calendar::resource::{CalendarResource, CalendarResourceService}; use crate::{CalDavPrincipalUri, Error}; +use actix_web::web; use async_trait::async_trait; use rustical_dav::extensions::{CommonPropertiesExtension, CommonPropertiesProp}; use rustical_dav::privileges::UserPrivilegeSet; use rustical_dav::resource::{PrincipalUri, Resource, ResourceService}; use rustical_dav::xml::{Resourcetype, ResourcetypeInner}; -use rustical_store::CalendarStore; use rustical_store::auth::User; +use rustical_store::{CalendarStore, SubscriptionStore}; use rustical_xml::{EnumUnitVariants, EnumVariants, XmlDeserialize, XmlSerialize}; use std::sync::Arc; @@ -60,18 +61,24 @@ impl Resource for CalendarSetResource { } } -pub struct CalendarSetResourceService { +pub struct CalendarSetResourceService { + name: &'static str, cal_store: Arc, + sub_store: Arc, } -impl CalendarSetResourceService { - pub fn new(cal_store: Arc) -> Self { - Self { cal_store } +impl CalendarSetResourceService { + pub fn new(name: &'static str, cal_store: Arc, sub_store: Arc) -> Self { + Self { + name, + cal_store, + sub_store, + } } } #[async_trait(?Send)] -impl ResourceService for CalendarSetResourceService { +impl ResourceService for CalendarSetResourceService { type PathComponents = (String,); type MemberType = CalendarResource; type Resource = CalendarSetResource; @@ -107,4 +114,16 @@ impl ResourceService for CalendarSetResourceService { }) .collect()) } + + fn actix_scope(self) -> actix_web::Scope { + web::scope(&format!("/{}", self.name)) + .service( + CalendarResourceService::<_, S>::new( + self.cal_store.clone(), + self.sub_store.clone(), + ) + .actix_scope(), + ) + .service(self.actix_resource()) + } } diff --git a/crates/caldav/src/lib.rs b/crates/caldav/src/lib.rs index ab5deec..7a74ac0 100644 --- a/crates/caldav/src/lib.rs +++ b/crates/caldav/src/lib.rs @@ -4,13 +4,10 @@ use actix_web::dev::{HttpServiceFactory, ServiceResponse}; use actix_web::http::header::{self, HeaderName, HeaderValue}; use actix_web::http::{Method, StatusCode}; use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; -use actix_web::web::{self, Data}; -use calendar::resource::CalendarResourceService; -use calendar_object::resource::CalendarObjectResourceService; -use calendar_set::CalendarSetResourceService; +use actix_web::web::Data; use derive_more::Constructor; -use principal::{PrincipalResource, PrincipalResourceService}; -use rustical_dav::resource::{PrincipalUri, ResourceService, ResourceServiceRoute}; +use principal::PrincipalResourceService; +use rustical_dav::resource::{PrincipalUri, ResourceService}; use rustical_dav::resources::RootResourceService; use rustical_store::auth::{AuthenticationMiddleware, AuthenticationProvider, User}; use rustical_store::{AddressbookStore, CalendarStore, ContactBirthdayStore, SubscriptionStore}; @@ -75,71 +72,19 @@ pub fn caldav_service< ) -> impl HttpServiceFactory { let birthday_store = Arc::new(ContactBirthdayStore::new(addr_store)); - web::scope("") - .wrap(AuthenticationMiddleware::new(auth_provider.clone())) - .wrap(options_handler()) - .app_data(Data::from(store.clone())) - .app_data(Data::from(birthday_store.clone())) - .app_data(Data::from(subscription_store)) - .app_data(Data::new(CalDavPrincipalUri::new( - format!("{prefix}/principal").leak(), - ))) - .service( - RootResourceService::::default() - .actix_resource(), - ) - .service( - web::scope("/principal").service( - web::scope("/{principal}") - .service( - PrincipalResourceService { - auth_provider, - home_set: &[("calendar", false), ("birthdays", true)], - } - .actix_resource(), - ) - .service( - web::scope("/calendar") - .service( - CalendarSetResourceService::new(store.clone()).actix_resource(), - ) - .service( - web::scope("/{calendar_id}") - .service(ResourceServiceRoute( - CalendarResourceService::<_, S>::new(store.clone()), - )) - .service( - web::scope("/{object_id}.ics").service( - CalendarObjectResourceService::new(store.clone()) - .actix_resource(), - ), - ), - ), - ) - .service( - web::scope("/birthdays") - .service( - CalendarSetResourceService::new(birthday_store.clone()) - .actix_resource(), - ) - .service( - web::scope("/{calendar_id}") - .service(ResourceServiceRoute( - CalendarResourceService::<_, S>::new( - birthday_store.clone(), - ), - )) - .service( - web::scope("/{object_id}.ics").service( - CalendarObjectResourceService::new( - birthday_store.clone(), - ) - .actix_resource(), - ), - ), - ), - ), - ), - ) - .service(subscription_resource::()) + RootResourceService::<_, User, CalDavPrincipalUri>::new(PrincipalResourceService { + auth_provider: auth_provider.clone(), + sub_store: subscription_store.clone(), + birthday_store: birthday_store.clone(), + cal_store: store.clone(), + }) + .actix_scope() + .wrap(AuthenticationMiddleware::new(auth_provider.clone())) + .wrap(options_handler()) + .app_data(Data::from(store.clone())) + .app_data(Data::from(birthday_store.clone())) + .app_data(Data::new(CalDavPrincipalUri::new( + format!("{prefix}/principal").leak(), + ))) + .service(subscription_resource(subscription_store)) } diff --git a/crates/caldav/src/principal/mod.rs b/crates/caldav/src/principal/mod.rs index f8725ac..7b836ae 100644 --- a/crates/caldav/src/principal/mod.rs +++ b/crates/caldav/src/principal/mod.rs @@ -1,5 +1,6 @@ -use crate::calendar_set::CalendarSetResource; +use crate::calendar_set::{CalendarSetResource, CalendarSetResourceService}; use crate::{CalDavPrincipalUri, Error}; +use actix_web::web; use async_trait::async_trait; use rustical_dav::extensions::{CommonPropertiesExtension, CommonPropertiesProp}; use rustical_dav::privileges::UserPrivilegeSet; @@ -7,13 +8,14 @@ use rustical_dav::resource::{PrincipalUri, Resource, ResourceService}; use rustical_dav::xml::{HrefElement, Resourcetype, ResourcetypeInner}; use rustical_store::auth::user::PrincipalType; use rustical_store::auth::{AuthenticationProvider, User}; +use rustical_store::{CalendarStore, SubscriptionStore}; use rustical_xml::{EnumUnitVariants, EnumVariants, XmlDeserialize, XmlSerialize}; use std::sync::Arc; #[derive(Clone)] pub struct PrincipalResource { principal: User, - home_set: &'static [(&'static str, bool)], + home_set: &'static [&'static str], } #[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone)] @@ -72,7 +74,7 @@ impl Resource for PrincipalResource { .into_iter() .map(|principal| puri.principal_uri(principal)) .flat_map(|principal_url| { - self.home_set.iter().map(move |&(home_name, _read_only)| { + self.home_set.iter().map(move |&home_name| { HrefElement::new(format!("{}/{}", &principal_url, home_name)) }) }) @@ -117,13 +119,36 @@ impl Resource for PrincipalResource { } } -pub struct PrincipalResourceService { - pub auth_provider: Arc, - pub home_set: &'static [(&'static str, bool)], +#[derive(Debug)] +pub struct PrincipalResourceService< + AP: AuthenticationProvider, + S: SubscriptionStore, + CS: CalendarStore, + BS: CalendarStore, +> { + pub(crate) auth_provider: Arc, + pub(crate) sub_store: Arc, + pub(crate) cal_store: Arc, + pub(crate) birthday_store: Arc, +} + +impl Clone + for PrincipalResourceService +{ + fn clone(&self) -> Self { + Self { + auth_provider: self.auth_provider.clone(), + sub_store: self.sub_store.clone(), + cal_store: self.cal_store.clone(), + birthday_store: self.birthday_store.clone(), + } + } } #[async_trait(?Send)] -impl ResourceService for PrincipalResourceService { +impl + ResourceService for PrincipalResourceService +{ type PathComponents = (String,); type MemberType = CalendarSetResource; type Resource = PrincipalResource; @@ -142,7 +167,7 @@ impl ResourceService for PrincipalResourceService ResourceService for PrincipalResourceService Result, Self::Error> { - Ok(self - .home_set - .iter() - .map(|&(set_name, read_only)| { - ( - set_name.to_string(), - CalendarSetResource { - principal: principal.to_owned(), - read_only, - }, + Ok(vec![ + ( + "calendar".to_owned(), + CalendarSetResource { + principal: principal.to_owned(), + read_only: false, + }, + ), + ( + "birthdays".to_owned(), + CalendarSetResource { + principal: principal.to_owned(), + read_only: true, + }, + ), + ]) + } + + fn actix_scope(self) -> actix_web::Scope { + web::scope("/principal/{principal}") + .service( + CalendarSetResourceService::<_, S>::new( + "calendar", + self.cal_store.clone(), + self.sub_store.clone(), ) - }) - .collect()) + .actix_scope(), + ) + .service( + CalendarSetResourceService::<_, S>::new( + "birthdays", + self.birthday_store.clone(), + self.sub_store.clone(), + ) + .actix_scope(), + ) + .service(self.actix_resource()) } } diff --git a/crates/caldav/src/subscription.rs b/crates/caldav/src/subscription.rs index 829e4e7..77116a8 100644 --- a/crates/caldav/src/subscription.rs +++ b/crates/caldav/src/subscription.rs @@ -1,6 +1,8 @@ +use std::sync::Arc; + use actix_web::{ - web::{self, Data, Path}, HttpResponse, + web::{self, Data, Path}, }; use rustical_dav::xml::multistatus::PropstatElement; use rustical_store::SubscriptionStore; @@ -17,8 +19,9 @@ async fn handle_delete( Ok(HttpResponse::NoContent().body("Unregistered")) } -pub fn subscription_resource() -> actix_web::Resource { +pub fn subscription_resource(sub_store: Arc) -> actix_web::Resource { web::resource("/subscription/{id}") + .app_data(Data::from(sub_store)) .name("subscription") .delete(handle_delete::) } diff --git a/crates/carddav/src/address_object/resource.rs b/crates/carddav/src/address_object/resource.rs index d00e728..e364731 100644 --- a/crates/carddav/src/address_object/resource.rs +++ b/crates/carddav/src/address_object/resource.rs @@ -1,4 +1,5 @@ use crate::{CardDavPrincipalUri, Error}; +use actix_web::web; use async_trait::async_trait; use derive_more::derive::{Constructor, From, Into}; use rustical_dav::{ @@ -146,7 +147,11 @@ impl ResourceService for AddressObjectResourceService } #[inline] - fn actix_additional_routes(res: actix_web::Resource) -> actix_web::Resource { - res.get(get_object::).put(put_object::) + fn actix_scope(self) -> actix_web::Scope { + web::scope("/{object_id}.vcf").service( + self.actix_resource() + .get(get_object::) + .put(put_object::), + ) } } diff --git a/crates/carddav/src/addressbook/resource.rs b/crates/carddav/src/addressbook/resource.rs index 2cf7ece..9f23e3d 100644 --- a/crates/carddav/src/addressbook/resource.rs +++ b/crates/carddav/src/addressbook/resource.rs @@ -2,10 +2,10 @@ use super::methods::mkcol::route_mkcol; use super::methods::post::route_post; use super::methods::report::route_report_addressbook; use super::prop::{SupportedAddressData, SupportedReportSet}; -use crate::address_object::resource::AddressObjectResource; +use crate::address_object::resource::{AddressObjectResource, AddressObjectResourceService}; use crate::{CardDavPrincipalUri, Error}; use actix_web::http::Method; -use actix_web::web; +use actix_web::web::{self, Data}; use async_trait::async_trait; use derive_more::derive::{From, Into}; use rustical_dav::extensions::{ @@ -18,20 +18,19 @@ use rustical_dav_push::{DavPushExtension, DavPushExtensionProp}; use rustical_store::auth::User; use rustical_store::{Addressbook, AddressbookStore, SubscriptionStore}; use rustical_xml::{EnumUnitVariants, EnumVariants, XmlDeserialize, XmlSerialize}; -use std::marker::PhantomData; use std::str::FromStr; use std::sync::Arc; pub struct AddressbookResourceService { addr_store: Arc, - __phantom_sub: PhantomData, + sub_store: Arc, } impl AddressbookResourceService { - pub fn new(addr_store: Arc) -> Self { + pub fn new(addr_store: Arc, sub_store: Arc) -> Self { Self { addr_store, - __phantom_sub: PhantomData, + sub_store, } } } @@ -256,11 +255,17 @@ impl ResourceService } #[inline] - fn actix_additional_routes(res: actix_web::Resource) -> actix_web::Resource { + fn actix_scope(self) -> actix_web::Scope { let mkcol_method = web::method(Method::from_str("MKCOL").unwrap()); let report_method = web::method(Method::from_str("REPORT").unwrap()); - res.route(mkcol_method.to(route_mkcol::)) - .route(report_method.to(route_report_addressbook::)) - .post(route_post::) + web::scope("/{addressbook_id}") + .app_data(Data::from(self.sub_store.clone())) + .service(AddressObjectResourceService::::new(self.addr_store.clone()).actix_scope()) + .service( + self.actix_resource() + .route(mkcol_method.to(route_mkcol::)) + .route(report_method.to(route_report_addressbook::)) + .post(route_post::), + ) } } diff --git a/crates/carddav/src/lib.rs b/crates/carddav/src/lib.rs index 2ad1839..2ac6b51 100644 --- a/crates/carddav/src/lib.rs +++ b/crates/carddav/src/lib.rs @@ -7,13 +7,11 @@ use actix_web::{ header::{self, HeaderName, HeaderValue}, }, middleware::{ErrorHandlerResponse, ErrorHandlers}, - web::{self, Data}, + web::Data, }; -use address_object::resource::AddressObjectResourceService; -use addressbook::resource::AddressbookResourceService; use derive_more::Constructor; pub use error::Error; -use principal::{PrincipalResource, PrincipalResourceService}; +use principal::PrincipalResourceService; use rustical_dav::resource::{PrincipalUri, ResourceService}; use rustical_dav::resources::RootResourceService; use rustical_store::{ @@ -68,38 +66,19 @@ pub fn carddav_service, subscription_store: Arc, ) -> impl HttpServiceFactory { - web::scope("") - .wrap(AuthenticationMiddleware::new(auth_provider.clone())) - .wrap(options_handler()) - .app_data(Data::from(store.clone())) - .app_data(Data::from(subscription_store)) - .app_data(Data::new(CardDavPrincipalUri::new( - format!("{prefix}/principal").leak(), - ))) - .service( - RootResourceService::::default() - .actix_resource(), - ) - .service( - web::scope("/principal").service( - web::scope("/{principal}") - .service( - PrincipalResourceService::new(store.clone(), auth_provider) - .actix_resource(), - ) - .service( - web::scope("/{addressbook_id}") - .service( - AddressbookResourceService::::new(store.clone()) - .actix_resource(), - ) - .service( - web::scope("/{object_id}.vcf").service( - AddressObjectResourceService::::new(store.clone()) - .actix_resource(), - ), - ), - ), - ), - ) + RootResourceService::<_, User, CardDavPrincipalUri>::new( + PrincipalResourceService::<_, _, S>::new( + store.clone(), + auth_provider.clone(), + subscription_store.clone(), + ), + ) + .actix_scope() + .wrap(AuthenticationMiddleware::new(auth_provider.clone())) + .wrap(options_handler()) + .app_data(Data::from(store.clone())) + .app_data(Data::new(CardDavPrincipalUri::new( + format!("{prefix}/principal").leak(), + ))) + // TODO: Add endpoint to delete subscriptions } diff --git a/crates/carddav/src/principal/mod.rs b/crates/carddav/src/principal/mod.rs index 83757cf..10dd64a 100644 --- a/crates/carddav/src/principal/mod.rs +++ b/crates/carddav/src/principal/mod.rs @@ -1,25 +1,46 @@ -use crate::addressbook::resource::AddressbookResource; +use crate::addressbook::resource::{AddressbookResource, AddressbookResourceService}; use crate::{CardDavPrincipalUri, Error}; +use actix_web::web; use async_trait::async_trait; use rustical_dav::extensions::{CommonPropertiesExtension, CommonPropertiesProp}; use rustical_dav::privileges::UserPrivilegeSet; use rustical_dav::resource::{PrincipalUri, Resource, ResourceService}; use rustical_dav::xml::{HrefElement, Resourcetype, ResourcetypeInner}; -use rustical_store::AddressbookStore; use rustical_store::auth::{AuthenticationProvider, User}; +use rustical_store::{AddressbookStore, SubscriptionStore}; use rustical_xml::{EnumUnitVariants, EnumVariants, XmlDeserialize, XmlSerialize}; use std::sync::Arc; -pub struct PrincipalResourceService { +pub struct PrincipalResourceService< + A: AddressbookStore, + AP: AuthenticationProvider, + S: SubscriptionStore, +> { addr_store: Arc, auth_provider: Arc, + sub_store: Arc, } -impl PrincipalResourceService { - pub fn new(addr_store: Arc, auth_provider: Arc) -> Self { +impl Clone + for PrincipalResourceService +{ + fn clone(&self) -> Self { + Self { + addr_store: self.addr_store.clone(), + auth_provider: self.auth_provider.clone(), + sub_store: self.sub_store.clone(), + } + } +} + +impl + PrincipalResourceService +{ + pub fn new(addr_store: Arc, auth_provider: Arc, sub_store: Arc) -> Self { Self { addr_store, auth_provider, + sub_store, } } } @@ -120,8 +141,8 @@ impl Resource for PrincipalResource { } #[async_trait(?Send)] -impl ResourceService - for PrincipalResourceService +impl ResourceService + for PrincipalResourceService { type PathComponents = (String,); type MemberType = AddressbookResource; @@ -152,4 +173,16 @@ impl ResourceService .map(|addressbook| (addressbook.id.to_owned(), addressbook.into())) .collect()) } + + fn actix_scope(self) -> actix_web::Scope { + web::scope("/principal/{principal}") + .service( + AddressbookResourceService::<_, S>::new( + self.addr_store.clone(), + self.sub_store.clone(), + ) + .actix_scope(), + ) + .service(self.actix_resource()) + } } diff --git a/crates/dav/src/resource/methods/propfind.rs b/crates/dav/src/resource/methods/propfind.rs index 743f068..e9be1c5 100644 --- a/crates/dav/src/resource/methods/propfind.rs +++ b/crates/dav/src/resource/methods/propfind.rs @@ -44,8 +44,6 @@ pub(crate) async fn route_propfind( } }; - dbg!(&propfind); - // TODO: respect namespaces? let props = match &propfind.prop { PropfindType::Allprop => vec!["allprop"], diff --git a/crates/dav/src/resource/resource_service.rs b/crates/dav/src/resource/resource_service.rs index 0a796b5..326c28d 100644 --- a/crates/dav/src/resource/resource_service.rs +++ b/crates/dav/src/resource/resource_service.rs @@ -1,7 +1,6 @@ use super::methods::{route_delete, route_propfind, route_proppatch}; use super::{PrincipalUri, Resource}; use crate::Principal; -use actix_web::dev::{AppService, HttpServiceFactory}; use actix_web::web::Data; use actix_web::{ResponseError, http::Method, web}; use async_trait::async_trait; @@ -47,30 +46,12 @@ pub trait ResourceService: Sized + 'static { #[inline] fn actix_resource(self) -> actix_web::Resource { - Self::actix_additional_routes( - web::resource("") - .app_data(Data::new(self)) - .route( - web::method(Method::from_str("PROPFIND").unwrap()).to(route_propfind::), - ) - .route( - web::method(Method::from_str("PROPPATCH").unwrap()).to(route_proppatch::), - ) - .delete(route_delete::), - ) + web::resource("") + .app_data(Data::new(self)) + .route(web::method(Method::from_str("PROPFIND").unwrap()).to(route_propfind::)) + .route(web::method(Method::from_str("PROPPATCH").unwrap()).to(route_proppatch::)) + .delete(route_delete::) } - /// Hook for other resources to insert their additional methods (i.e. REPORT, MKCALENDAR) - #[inline] - fn actix_additional_routes(res: actix_web::Resource) -> actix_web::Resource { - res - } -} - -pub struct ResourceServiceRoute(pub RS); - -impl HttpServiceFactory for ResourceServiceRoute { - fn register(self, config: &mut AppService) { - self.0.actix_resource().register(config); - } + fn actix_scope(self) -> actix_web::Scope; } diff --git a/crates/dav/src/resources/root.rs b/crates/dav/src/resources/root.rs index 81664f1..0d0782a 100644 --- a/crates/dav/src/resources/root.rs +++ b/crates/dav/src/resources/root.rs @@ -5,6 +5,7 @@ use crate::extensions::{ use crate::privileges::UserPrivilegeSet; use crate::resource::{PrincipalUri, Resource, ResourceService}; use crate::xml::{Resourcetype, ResourcetypeInner}; +use actix_web::web; use async_trait::async_trait; use std::marker::PhantomData; @@ -44,30 +45,38 @@ impl Resource for RootResource { } #[derive(Clone)] -pub struct RootResourceService( - PhantomData, +pub struct RootResourceService( + PRS, PhantomData

, PhantomData, ); -impl Default for RootResourceService { - fn default() -> Self { - Self(PhantomData, PhantomData, PhantomData) +impl + RootResourceService +{ + pub fn new(principal_resource_service: PRS) -> Self { + Self(principal_resource_service, PhantomData, PhantomData) } } #[async_trait(?Send)] -impl, P: Principal, PURI: PrincipalUri> ResourceService - for RootResourceService +impl + Clone, P: Principal, PURI: PrincipalUri> ResourceService + for RootResourceService { type PathComponents = (); - type MemberType = PR; - type Resource = RootResource; - type Error = PR::Error; + type MemberType = PRS::Resource; + type Resource = RootResource; + type Error = PRS::Error; type Principal = P; type PrincipalUri = PURI; async fn get_resource(&self, _: &()) -> Result { - Ok(RootResource::::default()) + Ok(RootResource::::default()) + } + + fn actix_scope(self) -> actix_web::Scope { + web::scope("") + .service(self.0.clone().actix_scope()) + .service(self.actix_resource()) } }