use jid::Jid;
use crate::core::{error::Error, FromXml, IntoXml};
use crate::data_forms::DataForm;
use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
use crate::ns::PUBSUB_OWNER;
use crate::pubsub::{AffiliationAttribute, NodeName, Subscription};
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "affiliations")]
pub struct Affiliations {
#[xml(attribute)]
pub node: NodeName,
#[xml(children)]
pub affiliations: Vec<Affiliation>,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "affiliation")]
pub struct Affiliation {
#[xml(attribute)]
pub jid: Jid,
#[xml(attribute)]
pub affiliation: AffiliationAttribute,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "configure")]
pub struct Configure {
#[xml(attribute)]
pub node: Option<NodeName>,
#[xml(child(default))]
pub form: Option<DataForm>,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "default")]
pub struct Default {
#[xml(child(default))]
pub form: Option<DataForm>,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "delete")]
pub struct Delete {
#[xml(attribute)]
pub node: NodeName,
#[xml(child(default))]
pub redirect: Option<Redirect>,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "redirect")]
pub struct Redirect {
#[xml(attribute)]
pub uri: String,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "purge")]
pub struct Purge {
#[xml(attribute)]
pub node: NodeName,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "subscriptions")]
pub struct Subscriptions {
#[xml(attribute)]
pub node: NodeName,
#[xml(children)]
pub subscriptions: Vec<SubscriptionElem>,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = PUBSUB_OWNER, name = "subscription")]
pub struct SubscriptionElem {
#[xml(attribute)]
pub jid: Jid,
#[xml(attribute)]
pub subscription: Subscription,
#[xml(attribute)]
pub subid: Option<String>,
}
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(wrapped_with(namespace = PUBSUB_OWNER, name = "pubsub"))]
pub enum PubSubOwner {
#[xml(transparent)]
Affiliations(Affiliations),
#[xml(transparent)]
Configure(Configure),
#[xml(transparent)]
Default(Default),
#[xml(transparent)]
Delete(Delete),
#[xml(transparent)]
Purge(Purge),
#[xml(transparent)]
Subscriptions(Subscriptions),
}
impl IqGetPayload for PubSubOwner {}
impl IqSetPayload for PubSubOwner {}
impl IqResultPayload for PubSubOwner {}
#[cfg(test)]
mod tests {
use super::*;
use crate::data_forms::{DataFormType, Field, FieldType};
use crate::ns;
use crate::Element;
use jid::BareJid;
use std::str::FromStr;
#[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 pubsub = PubSubOwner::Affiliations(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 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 pubsub = PubSubOwner::Configure(Configure {
node: Some(NodeName(String::from("foo"))),
form: Some(DataForm {
type_: DataFormType::Submit,
form_type: Some(String::from(ns::PUBSUB_CONFIGURE)),
title: None,
instructions: None,
fields: vec![Field {
var: String::from("pubsub#access_model"),
type_: FieldType::ListSingle,
label: None,
required: false,
options: vec![],
values: vec![String::from("whitelist")],
media: vec![],
}],
}),
});
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 configure = PubSubOwner::Configure(Configure {
node: Some(NodeName(String::from("foo"))),
form: Some(form),
});
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 pubsub = PubSubOwner::Default(Default {
form: Some(DataForm {
type_: DataFormType::Submit,
form_type: Some(String::from(ns::PUBSUB_CONFIGURE)),
title: None,
instructions: None,
fields: vec![Field {
var: String::from("pubsub#access_model"),
type_: FieldType::ListSingle,
label: None,
required: false,
options: vec![],
values: vec![String::from("whitelist")],
media: vec![],
}],
}),
});
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 pubsub = PubSubOwner::Delete(Delete {
node: NodeName(String::from("foo")),
redirect: Some(Redirect {
uri: String::from("xmpp:hamlet@denmark.lit?;node=blog"),
}),
});
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 pubsub = PubSubOwner::Purge(Purge {
node: NodeName(String::from("foo")),
});
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 pubsub = PubSubOwner::Subscriptions(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 elem2 = Element::from(pubsub);
assert_eq!(elem1, elem2);
}
}