principal.rs
⎇
Raw
1//! Attendee search and the system address book's cards.
2
3use pimdav::calcard::vcard::VCard;
4use pimdav::principal::{Principal, UserType, card};
5use pimdav::report::{Report, parse};
6use pimdav::xml::{DAV, Name, Propfind};
7
8fn search(body: &str) -> pimdav::principal::Search {
9 match parse(body.as_bytes()).unwrap() {
10 Report::PrincipalSearch(s) => s,
11 other => panic!("{other:?}"),
12 }
13}
14
15#[test]
16fn property_search_and_calendarserver_search() {
17 let addresses = ["mailto:board@rooms.filebrowser.invalid".to_string()];
18 let room = Principal {
19 name: "board",
20 display: "Board Room",
21 addresses: &addresses,
22 kind: UserType::Room,
23 };
24 let alice_addresses = ["mailto:alice@filebrowser.invalid".to_string()];
25 let alice = Principal {
26 name: "alice",
27 display: "Alice",
28 addresses: &alice_addresses,
29 kind: UserType::Individual,
30 };
31
32 let s = search(
33 r#"<d:principal-property-search xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
34 <d:property-search><d:prop><d:displayname/></d:prop><d:match>ROOM</d:match></d:property-search>
35 <d:property-search><d:prop><c:calendar-user-type/></d:prop><d:match>room</d:match></d:property-search>
36 <d:prop><d:displayname/></d:prop>
37 </d:principal-property-search>"#,
38 );
39 assert!(s.matches(&room));
40 assert!(!s.matches(&alice));
41 assert_eq!(s.find, Propfind::Prop(vec![Name::new(DAV, "displayname")]));
42
43 let s = search(
44 r#"<d:principal-property-search xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
45 <d:property-search><d:prop><c:calendar-user-address-set/></d:prop>
46 <d:match match-type="starts-with">alice@</d:match></d:property-search>
47 </d:principal-property-search>"#,
48 );
49 assert!(s.matches(&alice));
50 assert!(!s.matches(&room));
51
52 let s = search(
53 r#"<cs:calendarserver-principal-search xmlns:cs="http://calendarserver.org/ns/" context="location">
54 <cs:search-token>bo</cs:search-token><cs:search-token>ro</cs:search-token>
55 <cs:limit><cs:nresults>5</cs:nresults></cs:limit>
56 </cs:calendarserver-principal-search>"#,
57 );
58 assert!(s.matches(&room));
59 assert!(!s.matches(&alice));
60 assert_eq!(s.limit, Some(5));
61}
62
63#[test]
64fn directory_card_escapes_text() {
65 let p = Principal {
66 name: "ops",
67 display: "Ops; Night, Shift",
68 addresses: &[],
69 kind: UserType::Resource,
70 };
71 let text = card("urn:uuid:1", &p, "ops@resources.filebrowser.invalid");
72 assert!(text.contains(r"FN:Ops\; Night\, Shift"), "{text}");
73 assert!(text.contains("KIND:device\r\n"));
74 assert!(VCard::parse(&text).is_ok());
75}
76
77#[test]
78fn list_all_and_stray_properties() {
79 // What python-caldav sends: no property-search, properties beside an
80 // empty `<prop>`.
81 let s = search(
82 r#"<d:principal-property-search xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
83 <d:prop/><c:calendar-home-set/><d:displayname/>
84 </d:principal-property-search>"#,
85 );
86 let p = Principal {
87 name: "x",
88 display: "X",
89 addresses: &[],
90 kind: UserType::Individual,
91 };
92 assert!(s.matches(&p));
93 assert_eq!(
94 s.find,
95 Propfind::Prop(vec![
96 Name::new(pimdav::xml::CALDAV, "calendar-home-set"),
97 Name::new(DAV, "displayname")
98 ])
99 );
100}
101