rustical_dav_push/
register.rs

1use crate::Trigger;
2use rustical_xml::{XmlDeserialize, XmlRootTag, XmlSerialize};
3
4#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
5#[xml(ns = "crate::namespace::NS_DAVPUSH")]
6pub struct WebPushSubscription {
7    #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
8    pub push_resource: String,
9    #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
10    // DAVx5 4.4.9 does not seem to use it yet
11    pub content_encoding: Option<String>,
12    #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
13    pub subscription_public_key: SubscriptionPublicKey,
14    #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
15    pub auth_secret: String,
16}
17
18#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
19pub struct SubscriptionPublicKey {
20    #[xml(ty = "attr", rename = "type")]
21    pub ty: String,
22    #[xml(ty = "text")]
23    pub key: String,
24}
25
26#[derive(XmlDeserialize, Clone, Debug, PartialEq, Eq)]
27pub struct SubscriptionElement {
28    #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
29    pub web_push_subscription: WebPushSubscription,
30}
31
32#[derive(XmlDeserialize, XmlSerialize, Clone, Debug, PartialEq, Eq)]
33pub struct TriggerElement(#[xml(ty = "untagged", flatten)] Vec<Trigger>);
34
35#[derive(XmlDeserialize, XmlRootTag, Clone, Debug, PartialEq, Eq)]
36#[xml(root = "push-register")]
37#[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
38pub struct PushRegister {
39    #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
40    pub subscription: SubscriptionElement,
41    #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
42    pub expires: Option<String>,
43    #[xml(ns = "rustical_dav::namespace::NS_DAVPUSH")]
44    pub trigger: Option<TriggerElement>,
45}
46
47#[cfg(test)]
48mod tests {
49    use crate::{ContentUpdate, PropertyUpdate};
50
51    use super::*;
52    use rustical_dav::header::Depth;
53    use rustical_xml::XmlDocument;
54
55    #[test]
56    fn test_xml_push_register() {
57        let push_register = PushRegister::parse_str(
58            r#"
59            <?xml version="1.0" encoding="utf-8" ?>
60            <push-register xmlns="https://bitfire.at/webdav-push" xmlns:D="DAV:">
61                <subscription>
62                    <web-push-subscription>
63                        <push-resource>https://up.example.net/yohd4yai5Phiz1wi</push-resource>
64                        <content-encoding>aes128gcm</content-encoding>
65                        <subscription-public-key type="p256dh">BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4</subscription-public-key>
66                        <auth-secret>BTBZMqHH6r4Tts7J_aSIgg</auth-secret>
67                    </web-push-subscription>
68                </subscription>
69                <trigger>
70                    <content-update>
71                        <D:depth>infinity</D:depth>
72                    </content-update>
73                    <property-update>
74                        <D:depth>0</D:depth>
75                        <D:prop>
76                            <D:displayname/>
77                            <D:owner/>
78                        </D:prop>
79                    </property-update>
80                </trigger>
81                <expires>Wed, 20 Dec 2023 10:03:31 GMT</expires>
82            </push-register>
83    "#,
84        )
85        .unwrap();
86        assert_eq!(
87            push_register,
88            PushRegister {
89                subscription: SubscriptionElement {
90                    web_push_subscription: WebPushSubscription {
91                        push_resource: "https://up.example.net/yohd4yai5Phiz1wi".to_owned(),
92                        content_encoding: Some("aes128gcm".to_owned()),
93                        subscription_public_key: SubscriptionPublicKey { ty: "p256dh".to_owned(), key: "BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4".to_owned() },
94                        auth_secret: "BTBZMqHH6r4Tts7J_aSIgg".to_owned()
95                    }
96                },
97                expires: Some("Wed, 20 Dec 2023 10:03:31 GMT".to_owned()),
98                trigger: Some(TriggerElement(vec![
99                    Trigger::ContentUpdate(ContentUpdate(Depth::Infinity)),
100                    Trigger::PropertyUpdate(PropertyUpdate(Depth::Zero)),
101                ]))
102            }
103        );
104    }
105}