blocking.rs

  1// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use xso::{AsXml, FromXml};
  8
  9use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
 10use crate::ns;
 11use jid::Jid;
 12
 13/// The element requesting the blocklist, the result iq will contain a
 14/// [BlocklistResult].
 15#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
 16#[xml(namespace = ns::BLOCKING, name = "blocklist")]
 17pub struct BlocklistRequest;
 18
 19impl IqGetPayload for BlocklistRequest {}
 20
 21/// The element containing the current blocklist, as a reply from
 22/// [BlocklistRequest].
 23#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
 24#[xml(namespace = ns::BLOCKING, name = "blocklist")]
 25pub struct BlocklistResult {
 26    /// List of JIDs affected by this command.
 27    #[xml(extract(n = .., name = "item", fields(attribute(name = "jid", type_ = Jid))))]
 28    pub items: Vec<Jid>,
 29}
 30
 31impl IqResultPayload for BlocklistResult {}
 32
 33/// A query to block one or more JIDs.
 34// TODO: Prevent zero elements from being allowed.
 35#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
 36#[xml(namespace = ns::BLOCKING, name = "block")]
 37pub struct Block {
 38    /// List of JIDs affected by this command.
 39    #[xml(extract(n = .., name = "item", fields(attribute(name = "jid", type_ = Jid))))]
 40    pub items: Vec<Jid>,
 41}
 42
 43impl IqSetPayload for Block {}
 44
 45/// A query to unblock one or more JIDs, or all of them.
 46///
 47/// Warning: not putting any JID there means clearing out the blocklist.
 48#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
 49#[xml(namespace = ns::BLOCKING, name = "unblock")]
 50pub struct Unblock {
 51    /// List of JIDs affected by this command.
 52    #[xml(extract(n = .., name = "item", fields(attribute(name = "jid", type_ = Jid))))]
 53    pub items: Vec<Jid>,
 54}
 55
 56impl IqSetPayload for Unblock {}
 57
 58/// The application-specific error condition when a message is blocked.
 59#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
 60#[xml(namespace = ns::BLOCKING_ERRORS, name = "blocked")]
 61pub struct Blocked;
 62
 63#[cfg(test)]
 64mod tests {
 65    use xso::error::{Error, FromElementError};
 66
 67    use super::*;
 68    use minidom::Element;
 69
 70    #[cfg(target_pointer_width = "32")]
 71    #[test]
 72    fn test_size() {
 73        assert_size!(BlocklistRequest, 0);
 74        assert_size!(BlocklistResult, 12);
 75        assert_size!(Block, 12);
 76        assert_size!(Unblock, 12);
 77    }
 78
 79    #[cfg(target_pointer_width = "64")]
 80    #[test]
 81    fn test_size() {
 82        assert_size!(BlocklistRequest, 0);
 83        assert_size!(BlocklistResult, 24);
 84        assert_size!(Block, 24);
 85        assert_size!(Unblock, 24);
 86    }
 87
 88    #[test]
 89    fn test_simple() {
 90        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'/>".parse().unwrap();
 91        let request_elem = elem.clone();
 92        BlocklistRequest::try_from(request_elem).unwrap();
 93
 94        let result_elem = elem.clone();
 95        let result = BlocklistResult::try_from(result_elem).unwrap();
 96        assert!(result.items.is_empty());
 97
 98        let elem: Element = "<block xmlns='urn:xmpp:blocking'/>".parse().unwrap();
 99        let block = Block::try_from(elem).unwrap();
100        assert!(block.items.is_empty());
101
102        let elem: Element = "<unblock xmlns='urn:xmpp:blocking'/>".parse().unwrap();
103        let unblock = Unblock::try_from(elem).unwrap();
104        assert!(unblock.items.is_empty());
105    }
106
107    #[test]
108    fn test_items() {
109        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></blocklist>".parse().unwrap();
110        let two_items = vec![
111            Jid::new("coucou@coucou").unwrap(),
112            Jid::new("domain").unwrap(),
113        ];
114
115        let result_elem = elem.clone();
116        let result = BlocklistResult::try_from(result_elem).unwrap();
117        assert_eq!(result.items, two_items);
118
119        let elem: Element = "<block xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></block>".parse().unwrap();
120        let block = Block::try_from(elem).unwrap();
121        assert_eq!(block.items, two_items);
122
123        let elem: Element = "<unblock xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></unblock>".parse().unwrap();
124        let unblock = Unblock::try_from(elem).unwrap();
125        assert_eq!(unblock.items, two_items);
126    }
127
128    #[cfg(not(feature = "disable-validation"))]
129    #[test]
130    fn test_invalid() {
131        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking' coucou=''/>"
132            .parse()
133            .unwrap();
134        let request_elem = elem.clone();
135        let error = BlocklistRequest::try_from(request_elem).unwrap_err();
136        let message = match error {
137            FromElementError::Invalid(Error::Other(string)) => string,
138            _ => panic!(),
139        };
140        assert_eq!(message, "Unknown attribute in BlocklistRequest element.");
141
142        let result_elem = elem.clone();
143        let error = BlocklistResult::try_from(result_elem).unwrap_err();
144        let message = match error {
145            FromElementError::Invalid(Error::Other(string)) => string,
146            _ => panic!(),
147        };
148        assert_eq!(message, "Unknown attribute in BlocklistResult element.");
149
150        let elem: Element = "<block xmlns='urn:xmpp:blocking' coucou=''/>"
151            .parse()
152            .unwrap();
153        let error = Block::try_from(elem).unwrap_err();
154        let message = match error {
155            FromElementError::Invalid(Error::Other(string)) => string,
156            _ => panic!(),
157        };
158        assert_eq!(message, "Unknown attribute in Block element.");
159
160        let elem: Element = "<unblock xmlns='urn:xmpp:blocking' coucou=''/>"
161            .parse()
162            .unwrap();
163        let error = Unblock::try_from(elem).unwrap_err();
164        let message = match error {
165            FromElementError::Invalid(Error::Other(string)) => string,
166            _ => panic!(),
167        };
168        assert_eq!(message, "Unknown attribute in Unblock element.");
169    }
170
171    #[cfg(not(feature = "disable-validation"))]
172    #[test]
173    fn test_non_empty_blocklist_request() {
174        let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></blocklist>".parse().unwrap();
175        let error = BlocklistRequest::try_from(elem).unwrap_err();
176        let message = match error {
177            FromElementError::Invalid(Error::Other(string)) => string,
178            _ => panic!(),
179        };
180        assert_eq!(message, "Unknown child in BlocklistRequest element.");
181    }
182}