mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 22:52:22 +00:00
A little more preparation for new DAV Push spec
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use actix_web::{FromRequest, HttpRequest, ResponseError, http::StatusCode};
|
use actix_web::{FromRequest, HttpRequest, ResponseError, http::StatusCode};
|
||||||
use futures_util::future::{Ready, err, ok};
|
use futures_util::future::{Ready, err, ok};
|
||||||
use rustical_xml::ValueSerialize;
|
use rustical_xml::{ValueDeserialize, ValueSerialize, XmlError};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
@@ -25,12 +25,25 @@ impl ValueSerialize for Depth {
|
|||||||
match self {
|
match self {
|
||||||
Depth::Zero => "0",
|
Depth::Zero => "0",
|
||||||
Depth::One => "1",
|
Depth::One => "1",
|
||||||
Depth::Infinity => "Infinity",
|
Depth::Infinity => "infinity",
|
||||||
}
|
}
|
||||||
.to_owned()
|
.to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ValueDeserialize for Depth {
|
||||||
|
fn deserialize(val: &str) -> Result<Self, XmlError> {
|
||||||
|
match val {
|
||||||
|
"0" => Ok(Self::Zero),
|
||||||
|
"1" => Ok(Self::One),
|
||||||
|
"infinity" | "Infinity" => Ok(Self::Infinity),
|
||||||
|
_ => Err(XmlError::InvalidVariant(
|
||||||
|
"Invalid value for depth".to_owned(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<&[u8]> for Depth {
|
impl TryFrom<&[u8]> for Depth {
|
||||||
type Error = InvalidDepthHeader;
|
type Error = InvalidDepthHeader;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::{ContentUpdate, PropertyUpdate, SupportedTrigger, SupportedTriggers, Transports};
|
use crate::{ContentUpdate, PropertyUpdate, SupportedTriggers, Transports, Trigger};
|
||||||
use rustical_dav::header::Depth;
|
use rustical_dav::header::Depth;
|
||||||
use rustical_xml::{EnumUnitVariants, EnumVariants, XmlDeserialize, XmlSerialize};
|
use rustical_xml::{EnumUnitVariants, EnumVariants, Unparsed, XmlDeserialize, XmlSerialize};
|
||||||
|
|
||||||
#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumUnitVariants, EnumVariants)]
|
#[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumUnitVariants, EnumVariants)]
|
||||||
#[xml(unit_variants_ident = "DavPushExtensionPropName")]
|
#[xml(unit_variants_ident = "DavPushExtensionPropName")]
|
||||||
@@ -21,8 +21,8 @@ pub trait DavPushExtension {
|
|||||||
|
|
||||||
fn supported_triggers(&self) -> SupportedTriggers {
|
fn supported_triggers(&self) -> SupportedTriggers {
|
||||||
SupportedTriggers(vec![
|
SupportedTriggers(vec![
|
||||||
SupportedTrigger::ContentUpdate(ContentUpdate(Depth::One)),
|
Trigger::ContentUpdate(ContentUpdate(Depth::One)),
|
||||||
SupportedTrigger::PropertyUpdate(PropertyUpdate(Depth::One)),
|
Trigger::PropertyUpdate(PropertyUpdate(Depth::One)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rustical_dav::header::Depth;
|
use rustical_dav::header::Depth;
|
||||||
use rustical_xml::XmlSerialize;
|
use rustical_xml::{Unparsed, XmlDeserialize, XmlSerialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, XmlSerialize, PartialEq)]
|
#[derive(Debug, Clone, XmlSerialize, PartialEq)]
|
||||||
pub enum Transport {
|
pub enum Transport {
|
||||||
@@ -22,23 +22,39 @@ impl Default for Transports {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(XmlSerialize, PartialEq, Clone)]
|
#[derive(XmlSerialize, XmlDeserialize, PartialEq, Clone)]
|
||||||
pub struct SupportedTriggers(#[xml(flatten, ty = "untagged")] pub Vec<SupportedTrigger>);
|
pub struct SupportedTriggers(#[xml(flatten, ty = "untagged")] pub Vec<Trigger>);
|
||||||
|
|
||||||
#[derive(XmlSerialize, PartialEq, Clone)]
|
#[derive(XmlSerialize, XmlDeserialize, PartialEq, Debug, Clone)]
|
||||||
pub enum SupportedTrigger {
|
pub enum Trigger {
|
||||||
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
ContentUpdate(ContentUpdate),
|
ContentUpdate(ContentUpdate),
|
||||||
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
PropertyUpdate(PropertyUpdate),
|
PropertyUpdate(PropertyUpdate),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(XmlSerialize, PartialEq, Clone)]
|
#[derive(XmlSerialize, XmlDeserialize, PartialEq, Clone, Debug)]
|
||||||
pub struct ContentUpdate(
|
pub struct ContentUpdate(
|
||||||
#[xml(rename = b"depth", ns = "rustical_dav::namespace::NS_DAV")] pub Depth,
|
#[xml(rename = b"depth", ns = "rustical_dav::namespace::NS_DAV")] pub Depth,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(XmlSerialize, PartialEq, Clone)]
|
#[derive(XmlSerialize, PartialEq, Clone, Debug)]
|
||||||
pub struct PropertyUpdate(
|
pub struct PropertyUpdate(
|
||||||
#[xml(rename = b"depth", ns = "rustical_dav::namespace::NS_DAV")] pub Depth,
|
#[xml(rename = b"depth", ns = "rustical_dav::namespace::NS_DAV")] pub Depth,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
impl XmlDeserialize for PropertyUpdate {
|
||||||
|
fn deserialize<R: std::io::BufRead>(
|
||||||
|
reader: &mut quick_xml::NsReader<R>,
|
||||||
|
start: &quick_xml::events::BytesStart,
|
||||||
|
empty: bool,
|
||||||
|
) -> Result<Self, rustical_xml::XmlError> {
|
||||||
|
#[derive(XmlDeserialize, PartialEq, Clone, Debug)]
|
||||||
|
struct FakePropertyUpdate(
|
||||||
|
#[xml(rename = b"depth", ns = "rustical_dav::namespace::NS_DAV")] pub Depth,
|
||||||
|
#[xml(rename = b"prop", ns = "rustical_dav::namespace::NS_DAV")] pub Unparsed,
|
||||||
|
);
|
||||||
|
let FakePropertyUpdate(depth, _) = FakePropertyUpdate::deserialize(reader, start, empty)?;
|
||||||
|
Ok(Self(depth))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,25 @@
|
|||||||
use rustical_xml::{XmlDeserialize, XmlRootTag};
|
use crate::Trigger;
|
||||||
|
use rustical_xml::{XmlDeserialize, XmlRootTag, XmlSerialize};
|
||||||
|
|
||||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||||
#[xml(ns = "crate::namespace::NS_DAVPUSH")]
|
#[xml(ns = "crate::namespace::NS_DAVPUSH")]
|
||||||
pub struct WebPushSubscription {
|
pub struct WebPushSubscription {
|
||||||
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
pub push_resource: String,
|
pub push_resource: String,
|
||||||
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
|
pub content_encoding: String,
|
||||||
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
|
pub subscription_public_key: SubscriptionPublicKey,
|
||||||
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
|
pub auth_secret: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||||
|
pub struct SubscriptionPublicKey {
|
||||||
|
#[xml(ty = "attr", rename = b"type")]
|
||||||
|
ty: String,
|
||||||
|
#[xml(ty = "text")]
|
||||||
|
key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
#[derive(XmlDeserialize, Clone, Debug, PartialEq)]
|
||||||
@@ -13,6 +28,9 @@ pub struct SubscriptionElement {
|
|||||||
pub web_push_subscription: WebPushSubscription,
|
pub web_push_subscription: WebPushSubscription,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(XmlDeserialize, XmlSerialize, Clone, Debug, PartialEq)]
|
||||||
|
pub struct TriggerElement(#[xml(ty = "untagged", flatten)] Vec<Trigger>);
|
||||||
|
|
||||||
#[derive(XmlDeserialize, XmlRootTag, Clone, Debug, PartialEq)]
|
#[derive(XmlDeserialize, XmlRootTag, Clone, Debug, PartialEq)]
|
||||||
#[xml(root = b"push-register")]
|
#[xml(root = b"push-register")]
|
||||||
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
@@ -21,11 +39,16 @@ pub struct PushRegister {
|
|||||||
pub subscription: SubscriptionElement,
|
pub subscription: SubscriptionElement,
|
||||||
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
pub expires: Option<String>,
|
pub expires: Option<String>,
|
||||||
|
#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
|
||||||
|
pub trigger: TriggerElement,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::{ContentUpdate, PropertyUpdate};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use rustical_dav::header::Depth;
|
||||||
use rustical_xml::XmlDocument;
|
use rustical_xml::XmlDocument;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -33,12 +56,27 @@ mod tests {
|
|||||||
let push_register = PushRegister::parse_str(
|
let push_register = PushRegister::parse_str(
|
||||||
r#"
|
r#"
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<push-register xmlns="https://bitfire.at/webdav-push">
|
<push-register xmlns="https://bitfire.at/webdav-push" xmlns:D="DAV:">
|
||||||
<subscription>
|
<subscription>
|
||||||
<web-push-subscription>
|
<web-push-subscription>
|
||||||
<push-resource>https://up.example.net/yohd4yai5Phiz1wi</push-resource>
|
<push-resource>https://up.example.net/yohd4yai5Phiz1wi</push-resource>
|
||||||
|
<content-encoding>aes128gcm</content-encoding>
|
||||||
|
<subscription-public-key type="p256dh">BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4</subscription-public-key>
|
||||||
|
<auth-secret>BTBZMqHH6r4Tts7J_aSIgg</auth-secret>
|
||||||
</web-push-subscription>
|
</web-push-subscription>
|
||||||
</subscription>
|
</subscription>
|
||||||
|
<trigger>
|
||||||
|
<content-update>
|
||||||
|
<D:depth>infinity</D:depth>
|
||||||
|
</content-update>
|
||||||
|
<property-update>
|
||||||
|
<D:depth>0</D:depth>
|
||||||
|
<D:prop>
|
||||||
|
<D:displayname/>
|
||||||
|
<D:owner/>
|
||||||
|
</D:prop>
|
||||||
|
</property-update>
|
||||||
|
</trigger>
|
||||||
<expires>Wed, 20 Dec 2023 10:03:31 GMT</expires>
|
<expires>Wed, 20 Dec 2023 10:03:31 GMT</expires>
|
||||||
</push-register>
|
</push-register>
|
||||||
"#,
|
"#,
|
||||||
@@ -49,10 +87,17 @@ mod tests {
|
|||||||
PushRegister {
|
PushRegister {
|
||||||
subscription: SubscriptionElement {
|
subscription: SubscriptionElement {
|
||||||
web_push_subscription: WebPushSubscription {
|
web_push_subscription: WebPushSubscription {
|
||||||
push_resource: "https://up.example.net/yohd4yai5Phiz1wi".to_owned()
|
push_resource: "https://up.example.net/yohd4yai5Phiz1wi".to_owned(),
|
||||||
|
content_encoding: "aes128gcm".to_owned(),
|
||||||
|
subscription_public_key: SubscriptionPublicKey { ty: "p256dh".to_owned(), key: "BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4".to_owned() },
|
||||||
|
auth_secret: "BTBZMqHH6r4Tts7J_aSIgg".to_owned()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
expires: Some("Wed, 20 Dec 2023 10:03:31 GMT".to_owned())
|
expires: Some("Wed, 20 Dec 2023 10:03:31 GMT".to_owned()),
|
||||||
|
trigger: TriggerElement(vec![
|
||||||
|
Trigger::ContentUpdate(ContentUpdate(Depth::Infinity)),
|
||||||
|
Trigger::PropertyUpdate(PropertyUpdate(Depth::Zero)),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user