use xso::{AsXml, FromXml};
use crate::data_forms::DataForm;
use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
use crate::ns;
use crate::pubsub::{AffiliationAttribute, NodeName, Subscription};
use jid::Jid;
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::PUBSUB_OWNER, name = "affiliation")]
pub struct Affiliation {
#[xml(attribute)]
jid: Jid,
#[xml(attribute)]
affiliation: AffiliationAttribute,
}
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::PUBSUB_OWNER, name = "subscription")]
pub struct SubscriptionElem {
#[xml(attribute)]
pub jid: Jid,
#[xml(attribute)]
pub subscription: Subscription,
#[xml(attribute(default))]
pub subid: Option<String>,
}
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::PUBSUB_OWNER, name = "pubsub")]
pub struct Owner {
#[xml(child)]
pub payload: Payload,
}
impl IqGetPayload for Owner {}
impl IqSetPayload for Owner {}
impl IqResultPayload for Owner {}
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::PUBSUB_OWNER, exhaustive)]
pub enum Payload {
#[xml(name = "affiliations")]
Affiliations {
#[xml(attribute)]
node: NodeName,
#[xml(child(n = ..))]
affiliations: Vec<Affiliation>,
},
#[xml(name = "configure")]
Configure {
#[xml(attribute(default))]
node: Option<NodeName>,
#[xml(child(default))]
form: Option<DataForm>,
},
#[xml(name = "default")]
Default {
#[xml(child(default))]
form: Option<DataForm>,
},
#[xml(name = "delete")]
Delete {
#[xml(attribute)]
node: NodeName,
#[xml(extract(default, name = "redirect", fields(attribute(name = "uri", type_ = String))))]
redirect_uri: Option<String>,
},
#[xml(name = "purge")]
Purge {
#[xml(attribute)]
node: NodeName,
},
#[xml(name = "subscriptions")]
Subscriptions {
#[xml(attribute)]
node: NodeName,
#[xml(child(n = ..))]
subscriptions: Vec<SubscriptionElem>,
},
}
#[cfg(test)]
mod tests {
use super::*;
use crate::data_forms::{DataFormType, Field, FieldType};
use core::str::FromStr;
use jid::BareJid;
use minidom::Element;
#[test]
fn affiliations() {
let elem: Element = "<pubsub xmlns='http://jabber.org/protocol/pubsub#owner'><affiliations node='foo'><affiliation jid='hamlet@denmark.lit' affiliation='owner'/><affiliation jid='polonius@denmark.lit' affiliation='outcast'/></affiliations></pubsub>"
.parse()
.unwrap();
let elem1 = elem.clone();
let payload = Payload::Affiliations {
node: NodeName(String::from("foo")),
affiliations: vec![
Affiliation {
jid: Jid::from(BareJid::from_str("hamlet@denmark.lit").unwrap()),
affiliation: AffiliationAttribute::Owner,
},
Affiliation {
jid: Jid::from(BareJid::from_str("polonius@denmark.lit").unwrap()),
affiliation: AffiliationAttribute::Outcast,
},
],
};
let pubsub = Owner { payload };
let elem2 = Element::from(pubsub);
assert_eq!(elem1, elem2);
}
#[test]
fn configure() {
let elem: Element = "<pubsub xmlns='http://jabber.org/protocol/pubsub#owner'><configure node='foo'><x xmlns='jabber:x:data' type='submit'><field var='FORM_TYPE' type='hidden'><value>http://jabber.org/protocol/pubsub#node_config</value></field><field var='pubsub#access_model' type='list-single'><value>whitelist</value></field></x></configure></pubsub>"
.parse()
.unwrap();
let elem1 = elem.clone();
let payload = Payload::Configure {
node: Some(NodeName(String::from("foo"))),
form: Some(DataForm::new(
DataFormType::Submit,
ns::PUBSUB_CONFIGURE,
vec![Field::new("pubsub#access_model", FieldType::ListSingle)
.with_value("whitelist")],
)),
};
let pubsub = Owner { payload };
let elem2 = Element::from(pubsub);
assert_eq!(elem1, elem2);
}
#[test]
fn test_serialize_configure() {
let reference: Element = "<pubsub xmlns='http://jabber.org/protocol/pubsub#owner'><configure node='foo'><x xmlns='jabber:x:data' type='submit'/></configure></pubsub>"
.parse()
.unwrap();
let elem: Element = "<x xmlns='jabber:x:data' type='submit'/>".parse().unwrap();
let form = DataForm::try_from(elem).unwrap();
let payload = Payload::Configure {
node: Some(NodeName(String::from("foo"))),
form: Some(form),
};
let configure = Owner { payload };
let serialized: Element = configure.into();
assert_eq!(serialized, reference);
}
#[test]
fn default() {
let elem: Element = "<pubsub xmlns='http://jabber.org/protocol/pubsub#owner'><default><x xmlns='jabber:x:data' type='submit'><field var='FORM_TYPE' type='hidden'><value>http://jabber.org/protocol/pubsub#node_config</value></field><field var='pubsub#access_model' type='list-single'><value>whitelist</value></field></x></default></pubsub>"
.parse()
.unwrap();
let elem1 = elem.clone();
let payload = Payload::Default {
form: Some(DataForm::new(
DataFormType::Submit,
ns::PUBSUB_CONFIGURE,
vec![Field::new("pubsub#access_model", FieldType::ListSingle)
.with_value("whitelist")],
)),
};
let pubsub = Owner { payload };
let elem2 = Element::from(pubsub);
assert_eq!(elem1, elem2);
}
#[test]
fn delete() {
let elem: Element = "<pubsub xmlns='http://jabber.org/protocol/pubsub#owner'><delete node='foo'><redirect uri='xmpp:hamlet@denmark.lit?;node=blog'/></delete></pubsub>"
.parse()
.unwrap();
let elem1 = elem.clone();
let payload = Payload::Delete {
node: NodeName(String::from("foo")),
redirect_uri: Some(String::from("xmpp:hamlet@denmark.lit?;node=blog")),
};
let pubsub = Owner { payload };
let elem2 = Element::from(pubsub);
assert_eq!(elem1, elem2);
}
#[test]
fn purge() {
let elem: Element = "<pubsub xmlns='http://jabber.org/protocol/pubsub#owner'><purge node='foo'></purge></pubsub>"
.parse()
.unwrap();
let elem1 = elem.clone();
let payload = Payload::Purge {
node: NodeName(String::from("foo")),
};
let pubsub = Owner { payload };
let elem2 = Element::from(pubsub);
assert_eq!(elem1, elem2);
}
#[test]
fn subscriptions() {
let elem: Element = "<pubsub xmlns='http://jabber.org/protocol/pubsub#owner'><subscriptions node='foo'><subscription jid='hamlet@denmark.lit' subscription='subscribed'/><subscription jid='polonius@denmark.lit' subscription='unconfigured'/><subscription jid='bernardo@denmark.lit' subscription='subscribed' subid='123-abc'/><subscription jid='bernardo@denmark.lit' subscription='subscribed' subid='004-yyy'/></subscriptions></pubsub>"
.parse()
.unwrap();
let elem1 = elem.clone();
let payload = Payload::Subscriptions {
node: NodeName(String::from("foo")),
subscriptions: vec![
SubscriptionElem {
jid: Jid::from(BareJid::from_str("hamlet@denmark.lit").unwrap()),
subscription: Subscription::Subscribed,
subid: None,
},
SubscriptionElem {
jid: Jid::from(BareJid::from_str("polonius@denmark.lit").unwrap()),
subscription: Subscription::Unconfigured,
subid: None,
},
SubscriptionElem {
jid: Jid::from(BareJid::from_str("bernardo@denmark.lit").unwrap()),
subscription: Subscription::Subscribed,
subid: Some(String::from("123-abc")),
},
SubscriptionElem {
jid: Jid::from(BareJid::from_str("bernardo@denmark.lit").unwrap()),
subscription: Subscription::Subscribed,
subid: Some(String::from("004-yyy")),
},
],
};
let pubsub = Owner { payload };
let elem2 = Element::from(pubsub);
assert_eq!(elem1, elem2);
}
}