mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 08:12:24 +00:00
xml: Strict namespace, some tests and restructuring
This commit is contained in:
@@ -8,26 +8,34 @@ use tracing_actix_web::RootSpan;
|
||||
|
||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||
pub struct Resourcetype {
|
||||
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV")]
|
||||
addressbook: Option<()>,
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
|
||||
collection: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||
pub struct MkcolAddressbookProp {
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
|
||||
resourcetype: Option<Resourcetype>,
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
|
||||
displayname: Option<String>,
|
||||
#[xml(rename = b"addressbook-description")]
|
||||
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV")]
|
||||
description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||
pub struct PropElement<T: XmlDeserialize> {
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
|
||||
prop: T,
|
||||
}
|
||||
|
||||
#[derive(XmlDeserialize, XmlRootTag, Clone, Debug, PartialEq)]
|
||||
#[xml(root = b"mkcol")]
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
|
||||
struct MkcolRequest {
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
|
||||
set: PropElement<MkcolAddressbookProp>,
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@ use rustical_xml::XmlDeserialize;
|
||||
|
||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||
#[allow(dead_code)]
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
|
||||
pub struct AddressbookMultigetRequest {
|
||||
#[xml(ty = "untagged")]
|
||||
prop: PropfindType,
|
||||
#[xml(flatten)]
|
||||
href: Vec<String>,
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV", ty = "untagged")]
|
||||
pub(crate) prop: PropfindType,
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV", flatten)]
|
||||
pub(crate) href: Vec<String>,
|
||||
}
|
||||
|
||||
pub async fn get_objects_addressbook_multiget<AS: AddressbookStore>(
|
||||
|
||||
@@ -4,9 +4,10 @@ use actix_web::{
|
||||
HttpRequest, Responder,
|
||||
};
|
||||
use addressbook_multiget::{handle_addressbook_multiget, AddressbookMultigetRequest};
|
||||
use rustical_dav::xml::sync_collection::SyncCollectionRequest;
|
||||
use rustical_store::{auth::User, AddressbookStore};
|
||||
use rustical_xml::{XmlDeserialize, XmlDocument};
|
||||
use sync_collection::{handle_sync_collection, SyncCollectionRequest};
|
||||
use sync_collection::handle_sync_collection;
|
||||
use tracing::instrument;
|
||||
|
||||
mod addressbook_multiget;
|
||||
@@ -14,7 +15,9 @@ mod sync_collection;
|
||||
|
||||
#[derive(XmlDeserialize, XmlDocument, Clone, Debug, PartialEq)]
|
||||
pub(crate) enum ReportRequest {
|
||||
#[xml(ns = "rustical_dav::namespace::NS_CARDDAV")]
|
||||
AddressbookMultiget(AddressbookMultigetRequest),
|
||||
#[xml(ns = "rustical_dav::namespace::NS_DAV")]
|
||||
SyncCollection(SyncCollectionRequest),
|
||||
}
|
||||
|
||||
@@ -61,8 +64,7 @@ pub async fn route_report_addressbook<AS: AddressbookStore>(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rustical_dav::xml::{PropElement, Propname};
|
||||
use sync_collection::SyncLevel;
|
||||
use rustical_dav::xml::{sync_collection::SyncLevel, PropElement, Propname};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -92,4 +94,31 @@ mod tests {
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_xml_addressbook_multiget() {
|
||||
let report_request = ReportRequest::parse_str(r#"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<addressbook-multiget xmlns="urn:ietf:params:xml:ns:carddav" xmlns:D="DAV:">
|
||||
<D:prop>
|
||||
<D:getetag/>
|
||||
<address-data/>
|
||||
</D:prop>
|
||||
<D:href>/carddav/user/user/6f787542-5256-401a-8db97003260da/ae7a998fdfd1d84a20391168962c62b</D:href>
|
||||
</addressbook-multiget>
|
||||
"#).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
report_request,
|
||||
ReportRequest::AddressbookMultiget(AddressbookMultigetRequest {
|
||||
prop: rustical_dav::xml::PropfindType::Prop(PropElement(vec![
|
||||
Propname("getetag".to_owned()),
|
||||
Propname("address-data".to_owned())
|
||||
])),
|
||||
href: vec![
|
||||
"/carddav/user/user/6f787542-5256-401a-8db97003260da/ae7a998fdfd1d84a20391168962c62b".to_owned()
|
||||
]
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,56 +5,16 @@ use crate::{
|
||||
use actix_web::{http::StatusCode, HttpRequest};
|
||||
use rustical_dav::{
|
||||
resource::{CommonPropertiesProp, EitherProp, Resource},
|
||||
xml::{multistatus::ResponseElement, MultistatusElement},
|
||||
xml::{PropElement, PropfindType},
|
||||
xml::{
|
||||
multistatus::ResponseElement, sync_collection::SyncCollectionRequest, MultistatusElement,
|
||||
PropElement, PropfindType,
|
||||
},
|
||||
};
|
||||
use rustical_store::{
|
||||
auth::User,
|
||||
synctoken::{format_synctoken, parse_synctoken},
|
||||
AddressbookStore,
|
||||
};
|
||||
use rustical_xml::{ValueDeserialize, ValueSerialize, XmlDeserialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub(crate) enum SyncLevel {
|
||||
One,
|
||||
Infinity,
|
||||
}
|
||||
|
||||
impl ValueDeserialize for SyncLevel {
|
||||
fn deserialize(val: &str) -> Result<Self, rustical_xml::XmlError> {
|
||||
Ok(match val {
|
||||
"1" => Self::One,
|
||||
"Infinity" => Self::Infinity,
|
||||
_ => {
|
||||
return Err(rustical_xml::XmlError::Other(
|
||||
"Invalid sync-level".to_owned(),
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
impl ValueSerialize for SyncLevel {
|
||||
fn serialize(&self) -> String {
|
||||
match self {
|
||||
SyncLevel::One => "1",
|
||||
SyncLevel::Infinity => "Infinity",
|
||||
}
|
||||
.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||
// <!ELEMENT sync-collection (sync-token, sync-level, limit?, prop)>
|
||||
// <!-- DAV:limit defined in RFC 5323, Section 5.17 -->
|
||||
// <!-- DAV:prop defined in RFC 4918, Section 14.18 -->
|
||||
pub(crate) struct SyncCollectionRequest {
|
||||
pub(crate) sync_token: String,
|
||||
pub(crate) sync_level: SyncLevel,
|
||||
#[xml(ty = "untagged")]
|
||||
pub prop: PropfindType,
|
||||
pub(crate) limit: Option<u64>,
|
||||
}
|
||||
|
||||
pub async fn handle_sync_collection<AS: AddressbookStore>(
|
||||
sync_collection: SyncCollectionRequest,
|
||||
|
||||
Reference in New Issue
Block a user