birthday calendar, lots of refactoring

This commit is contained in:
Lennart
2025-01-12 16:04:38 +01:00
parent f031478786
commit b9af6c10a3
19 changed files with 284 additions and 210 deletions

View File

@@ -61,11 +61,13 @@ pub(crate) async fn route_propfind<R: ResourceService>(
let mut member_responses = Vec::new();
if depth != Depth::Zero {
for (path, member) in resource_service
.get_members(&path, req.resource_map())
.await?
{
member_responses.push(member.propfind(&path, &props, &user, req.resource_map())?);
for (subpath, member) in resource_service.get_members(&path).await? {
member_responses.push(member.propfind(
&format!("{}/{}", req.path().trim_end_matches('/'), subpath),
&props,
&user,
req.resource_map(),
)?);
}
}

View File

@@ -4,8 +4,6 @@ use crate::xml::{multistatus::ResponseElement, TagList};
use crate::xml::{HrefElement, Resourcetype};
use crate::Error;
use actix_web::dev::ResourceMap;
use actix_web::error::UrlGenerationError;
use actix_web::test::TestRequest;
use actix_web::{http::StatusCode, ResponseError};
use itertools::Itertools;
pub use resource_service::ResourceService;
@@ -17,6 +15,8 @@ use strum::{EnumString, VariantNames};
mod methods;
mod resource_service;
pub use resource_service::*;
pub trait ResourceProp: XmlSerialize + XmlDeserialize {}
impl<T: XmlSerialize + XmlDeserialize> ResourceProp for T {}
@@ -62,7 +62,7 @@ pub trait Resource: Clone + 'static {
type PropName: ResourcePropName + From<Self::Prop> + Into<&'static str>;
type Prop: ResourceProp + PartialEq + Clone;
type Error: ResponseError + From<crate::Error>;
type PrincipalResource: Resource;
type PrincipalResource: Resource + NamedRoute;
fn get_resourcetype(&self) -> Resourcetype;
@@ -115,27 +115,10 @@ pub trait Resource: Clone + 'static {
Err(crate::Error::PropReadOnly)
}
fn resource_name() -> &'static str;
fn get_owner(&self) -> Option<&str> {
None
}
fn get_url<U, I>(rmap: &ResourceMap, elements: U) -> Result<String, UrlGenerationError>
where
U: IntoIterator<Item = I>,
I: AsRef<str>,
{
Ok(rmap
.url_for(
&TestRequest::default().to_http_request(),
Self::resource_name(),
elements,
)?
.path()
.to_owned())
}
fn get_user_privileges(&self, user: &User) -> Result<UserPrivilegeSet, Self::Error>;
fn propfind(

View File

@@ -1,9 +1,11 @@
use std::str::FromStr;
use actix_web::dev::{AppService, HttpServiceFactory};
use actix_web::error::UrlGenerationError;
use actix_web::test::TestRequest;
use actix_web::web::Data;
use actix_web::{dev::ResourceMap, http::Method, web, ResponseError};
use async_trait::async_trait;
use serde::Deserialize;
use std::str::FromStr;
use super::methods::{route_delete, route_propfind, route_proppatch};
use super::Resource;
@@ -17,8 +19,7 @@ pub trait ResourceService: Sized + 'static {
async fn get_members(
&self,
_path: &Self::PathComponents,
_rmap: &ResourceMap,
_path_components: &Self::PathComponents,
) -> Result<Vec<(String, Self::MemberType)>, Self::Error> {
Ok(vec![])
}
@@ -42,17 +43,11 @@ pub trait ResourceService: Sized + 'static {
Err(crate::Error::Unauthorized.into())
}
#[inline]
fn resource_name() -> &'static str {
Self::Resource::resource_name()
}
#[inline]
fn actix_resource(self) -> actix_web::Resource {
Self::actix_additional_routes(
web::resource("")
.app_data(Data::new(self))
.name(Self::resource_name())
.route(
web::method(Method::from_str("PROPFIND").unwrap()).to(route_propfind::<Self>),
)
@@ -69,3 +64,30 @@ pub trait ResourceService: Sized + 'static {
res
}
}
pub trait NamedRoute {
fn route_name() -> &'static str;
fn get_url<U, I>(rmap: &ResourceMap, elements: U) -> Result<String, UrlGenerationError>
where
U: IntoIterator<Item = I>,
I: AsRef<str>,
{
Ok(rmap
.url_for(
&TestRequest::default().to_http_request(),
Self::route_name(),
elements,
)?
.path()
.to_owned())
}
}
pub struct ResourceServiceRoute<RS: ResourceService>(pub RS);
impl<RS: ResourceService> HttpServiceFactory for ResourceServiceRoute<RS> {
fn register(self, config: &mut AppService) {
self.0.actix_resource().register(config);
}
}

View File

@@ -1,12 +1,11 @@
use crate::privileges::UserPrivilegeSet;
use crate::resource::{Resource, ResourceService};
use crate::resource::{NamedRoute, Resource, ResourceService};
use crate::xml::{Resourcetype, ResourcetypeInner};
use actix_web::dev::ResourceMap;
use async_trait::async_trait;
use rustical_store::auth::User;
use rustical_xml::{XmlDeserialize, XmlSerialize};
use serde::Serialize;
use std::any::type_name;
use std::marker::PhantomData;
use strum::{EnumString, IntoStaticStr, VariantNames};
@@ -32,7 +31,7 @@ impl From<RootResourceProp> for RootResourcePropName {
}
}
impl<PR: Resource> Resource for RootResource<PR> {
impl<PR: Resource + NamedRoute> Resource for RootResource<PR> {
type PropName = RootResourcePropName;
type Prop = RootResourceProp;
type Error = PR::Error;
@@ -51,16 +50,12 @@ impl<PR: Resource> Resource for RootResource<PR> {
unreachable!("we shouldn't end up here")
}
#[inline]
fn resource_name() -> &'static str {
type_name::<Self>()
}
fn get_user_privileges(&self, _user: &User) -> Result<UserPrivilegeSet, Self::Error> {
Ok(UserPrivilegeSet::all())
}
}
#[derive(Clone)]
pub struct RootResourceService<PR: Resource>(PhantomData<PR>);
impl<PR: Resource> Default for RootResourceService<PR> {
@@ -70,7 +65,7 @@ impl<PR: Resource> Default for RootResourceService<PR> {
}
#[async_trait(?Send)]
impl<PR: Resource> ResourceService for RootResourceService<PR> {
impl<PR: Resource + NamedRoute> ResourceService for RootResourceService<PR> {
type PathComponents = ();
type MemberType = PR;
type Resource = RootResource<PR>;