Migrate DAV props to serde. Big clusterfuck right now but it'll hopefully pay off

This commit is contained in:
Lennart
2024-03-14 19:24:23 +01:00
parent a145445277
commit b540362791
10 changed files with 246 additions and 190 deletions

View File

@@ -11,4 +11,5 @@ derive_more = "0.99"
futures-util = "0.3"
quick-xml = "0.31"
rustical_auth = { path = "../auth/" }
serde = { version = "1.0.197", features = ["derive"] }
strum = "0.26.2"

View File

@@ -1,4 +1,5 @@
pub mod depth_extractor;
pub mod namespace;
pub mod resource;
pub mod tagname;
pub mod xml_snippets;

View File

@@ -1,13 +1,16 @@
use std::{io::Write, str::FromStr};
use actix_web::{http::StatusCode, HttpRequest};
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use quick_xml::Writer;
use rustical_auth::AuthInfo;
use strum::VariantNames;
use serde::Serialize;
use std::str::FromStr;
use strum::{EnumProperty, VariantNames};
use crate::xml_snippets::{write_invalid_props_response, write_propstat_response};
use crate::{
tagname::TagName,
xml_snippets::{write_invalid_props_response, write_propstat_response},
};
// A resource is identified by a URI and has properties
// A resource can also be a collection
@@ -17,7 +20,8 @@ use crate::xml_snippets::{write_invalid_props_response, write_propstat_response}
pub trait Resource: Sized {
type MemberType: Resource;
type UriComponents: Sized; // defines how the resource URI maps to parameters, i.e. /{principal}/{calendar} -> (String, String)
type PropType: FromStr + VariantNames;
type PropType: FromStr + VariantNames + Into<&'static str> + EnumProperty + Clone;
type PropResponse: Serialize;
async fn acquire_from_request(
req: HttpRequest,
@@ -32,7 +36,7 @@ pub trait Resource: Sized {
fn list_dead_props() -> &'static [&'static str] {
Self::PropType::VARIANTS
}
fn write_prop<W: Write>(&self, writer: &mut Writer<W>, prop: Self::PropType) -> Result<()>;
fn get_prop(&self, prop: Self::PropType) -> Result<Self::PropResponse>;
}
pub trait HandlePropfind {
@@ -59,13 +63,12 @@ impl<R: Resource> HandlePropfind for R {
for prop in props {
if let Ok(valid_prop) = R::PropType::from_str(prop) {
// TODO: Fix error types
match self
.write_prop(writer, valid_prop)
.map_err(|_e| quick_xml::Error::TextNotFound)
{
// TODO: clean this mess up
Ok(_) => {}
// not really an invalid prop, but some error happened
match self.get_prop(valid_prop.clone()) {
Ok(response) => {
writer
.write_serializable(valid_prop.tagname(), &response)
.map_err(|_e| quick_xml::Error::TextNotFound)?;
}
Err(_) => invalid_props.push(prop),
};
} else {

11
crates/dav/src/tagname.rs Normal file
View File

@@ -0,0 +1,11 @@
use strum::EnumProperty;
pub trait TagName {
fn tagname(self) -> &'static str;
}
impl<P: EnumProperty + Into<&'static str>> TagName for P {
fn tagname(self) -> &'static str {
self.get_str("tagname").unwrap_or(self.into())
}
}

View File

@@ -6,21 +6,20 @@ use quick_xml::{
events::{attributes::Attribute, BytesText},
Writer,
};
use serde::Serialize;
pub fn write_resourcetype<W: Write>(
writer: &mut Writer<W>,
types: Vec<&str>,
) -> Result<(), quick_xml::Error> {
writer
.create_element("resourcetype")
.write_inner_content(|writer| {
for resourcetype in types {
writer.create_element(resourcetype).write_empty()?;
}
Ok::<(), quick_xml::Error>(())
})?;
Ok(())
#[derive(Serialize)]
pub struct HrefElement {
pub href: String,
}
impl HrefElement {
pub fn new(href: String) -> Self {
Self { href }
}
}
#[derive(Serialize)]
pub struct TextNode(pub Option<String>);
pub fn write_invalid_props_response<W: Write>(
writer: &mut Writer<W>,