1use xso::{text::Base64, AsXml, FromXml};
8
9use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
10use crate::ns;
11
12generate_elem_id!(
13 Name,
15 "name",
16 SASL_CERT
17);
18
19#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
21#[xml(namespace = ns::SASL_CERT, name = "x509cert")]
22pub struct Cert {
23 #[xml(text = Base64)]
25 pub data: Vec<u8>,
26}
27
28#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
30#[xml(namespace = ns::SASL_CERT, name = "append")]
31pub struct Append {
32 #[xml(child)]
34 pub name: Name,
35
36 #[xml(child)]
38 pub cert: Cert,
39
40 #[xml(flag(name = "no-cert-management"))]
42 pub no_cert_management: bool,
43}
44
45impl IqSetPayload for Append {}
46
47#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
49#[xml(namespace = ns::SASL_CERT, name = "items")]
50pub struct ListCertsQuery;
51
52impl IqGetPayload for ListCertsQuery {}
53
54generate_elem_id!(
55 Resource,
57 "resource",
58 SASL_CERT
59);
60
61#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
63#[xml(namespace = ns::SASL_CERT, name = "users")]
64pub struct Users {
65 #[xml(child(n = ..))]
67 pub resources: Vec<Resource>,
68}
69
70#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
72#[xml(namespace = ns::SASL_CERT, name = "item")]
73pub struct Item {
74 #[xml(child)]
76 pub name: Name,
77
78 #[xml(child)]
80 pub cert: Cert,
81
82 #[xml(flag(name = "no-cert-management"))]
84 pub no_cert_management: bool,
85
86 #[xml(child(default))]
88 pub users: Option<Users>,
89}
90
91#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
93#[xml(namespace = ns::SASL_CERT, name = "items")]
94pub struct ListCertsResponse {
95 #[xml(child(n = ..))]
97 pub items: Vec<Item>,
98}
99
100impl IqResultPayload for ListCertsResponse {}
101
102#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
104#[xml(namespace = ns::SASL_CERT, name = "disable")]
105pub struct Disable {
106 #[xml(child)]
108 pub name: Name,
109}
110
111impl IqSetPayload for Disable {}
112
113#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
115#[xml(namespace = ns::SASL_CERT, name = "revoke")]
116pub struct Revoke {
117 #[xml(child)]
119 pub name: Name,
120}
121
122impl IqSetPayload for Revoke {}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use crate::ns;
128 use core::str::FromStr;
129 use minidom::Element;
130
131 #[cfg(target_pointer_width = "32")]
132 #[test]
133 fn test_size() {
134 assert_size!(Append, 28);
135 assert_size!(Disable, 12);
136 assert_size!(Revoke, 12);
137 assert_size!(ListCertsQuery, 0);
138 assert_size!(ListCertsResponse, 12);
139 assert_size!(Item, 40);
140 assert_size!(Resource, 12);
141 assert_size!(Users, 12);
142 assert_size!(Cert, 12);
143 }
144
145 #[cfg(target_pointer_width = "64")]
146 #[test]
147 fn test_size() {
148 assert_size!(Append, 56);
149 assert_size!(Disable, 24);
150 assert_size!(Revoke, 24);
151 assert_size!(ListCertsQuery, 0);
152 assert_size!(ListCertsResponse, 24);
153 assert_size!(Item, 80);
154 assert_size!(Resource, 24);
155 assert_size!(Users, 24);
156 assert_size!(Cert, 24);
157 }
158
159 #[test]
160 fn simple() {
161 let elem: Element = "<append xmlns='urn:xmpp:saslcert:1'><name>Mobile Client</name><x509cert>AAAA</x509cert></append>".parse().unwrap();
162 let append = Append::try_from(elem).unwrap();
163 assert_eq!(append.name.0, "Mobile Client");
164 assert_eq!(append.cert.data, b"\0\0\0");
165
166 let elem: Element =
167 "<disable xmlns='urn:xmpp:saslcert:1'><name>Mobile Client</name></disable>"
168 .parse()
169 .unwrap();
170 let disable = Disable::try_from(elem).unwrap();
171 assert_eq!(disable.name.0, "Mobile Client");
172
173 let elem: Element =
174 "<revoke xmlns='urn:xmpp:saslcert:1'><name>Mobile Client</name></revoke>"
175 .parse()
176 .unwrap();
177 let revoke = Revoke::try_from(elem).unwrap();
178 assert_eq!(revoke.name.0, "Mobile Client");
179 }
180
181 #[test]
182 fn list() {
183 let elem: Element = r#"<items xmlns='urn:xmpp:saslcert:1'>
184 <item>
185 <name>Mobile Client</name>
186 <x509cert>AAAA</x509cert>
187 <users>
188 <resource>Phone</resource>
189 </users>
190 </item>
191 <item>
192 <name>Laptop</name>
193 <x509cert>BBBB</x509cert>
194 </item>
195 </items>"#
196 .parse()
197 .unwrap();
198 let mut list = ListCertsResponse::try_from(elem).unwrap();
199 assert_eq!(list.items.len(), 2);
200
201 let item = list.items.pop().unwrap();
202 assert_eq!(item.name.0, "Laptop");
203 assert_eq!(item.cert.data, [4, 16, 65]);
204 assert!(item.users.is_none());
205
206 let item = list.items.pop().unwrap();
207 assert_eq!(item.name.0, "Mobile Client");
208 assert_eq!(item.cert.data, b"\0\0\0");
209 assert_eq!(item.users.unwrap().resources.len(), 1);
210 }
211
212 #[test]
213 fn test_serialise() {
214 let append = Append {
215 name: Name::from_str("Mobile Client").unwrap(),
216 cert: Cert {
217 data: b"\0\0\0".to_vec(),
218 },
219 no_cert_management: false,
220 };
221 let elem: Element = append.into();
222 assert!(elem.is("append", ns::SASL_CERT));
223
224 let disable = Disable {
225 name: Name::from_str("Mobile Client").unwrap(),
226 };
227 let elem: Element = disable.into();
228 assert!(elem.is("disable", ns::SASL_CERT));
229 let elem = elem.children().cloned().collect::<Vec<_>>().pop().unwrap();
230 assert!(elem.is("name", ns::SASL_CERT));
231 assert_eq!(elem.text(), "Mobile Client");
232 }
233
234 #[test]
235 fn test_serialize_item() {
236 let reference: Element = "<item xmlns='urn:xmpp:saslcert:1'><name>Mobile Client</name><x509cert>AAAA</x509cert></item>"
237 .parse()
238 .unwrap();
239
240 let item = Item {
241 name: Name::from_str("Mobile Client").unwrap(),
242 cert: Cert {
243 data: b"\0\0\0".to_vec(),
244 },
245 no_cert_management: false,
246 users: None,
247 };
248
249 let serialized: Element = item.into();
250 assert_eq!(serialized, reference);
251 }
252
253 #[test]
254 fn test_serialize_append() {
255 let reference: Element = "<append xmlns='urn:xmpp:saslcert:1'><name>Mobile Client</name><x509cert>AAAA</x509cert></append>"
256 .parse()
257 .unwrap();
258
259 let append = Append {
260 name: Name::from_str("Mobile Client").unwrap(),
261 cert: Cert {
262 data: b"\0\0\0".to_vec(),
263 },
264 no_cert_management: false,
265 };
266
267 let serialized: Element = append.into();
268 assert_eq!(serialized, reference);
269 }
270
271 #[test]
272 fn test_serialize_disable() {
273 let reference: Element =
274 "<disable xmlns='urn:xmpp:saslcert:1'><name>Mobile Client</name></disable>"
275 .parse()
276 .unwrap();
277
278 let disable = Disable {
279 name: Name::from_str("Mobile Client").unwrap(),
280 };
281
282 let serialized: Element = disable.into();
283 assert_eq!(serialized, reference);
284 }
285
286 #[test]
287 fn test_serialize_revoke() {
288 let reference: Element =
289 "<revoke xmlns='urn:xmpp:saslcert:1'><name>Mobile Client</name></revoke>"
290 .parse()
291 .unwrap();
292
293 let revoke = Revoke {
294 name: Name::from_str("Mobile Client").unwrap(),
295 };
296
297 let serialized: Element = revoke.into();
298 assert_eq!(serialized, reference);
299 }
300}