epp_client/contact/
update.rs

1//! Types for EPP contact create request
2
3use super::{ContactAuthInfo, Phone, PostalInfo, XMLNS};
4use crate::common::{NoExtension, ObjectStatus, StringValue};
5use crate::request::{Command, Transaction};
6use serde::Serialize;
7
8impl<'a> Transaction<NoExtension> for ContactUpdate<'a> {}
9
10impl<'a> Command for ContactUpdate<'a> {
11    type Response = ();
12    const COMMAND: &'static str = "update";
13}
14
15impl<'a> ContactUpdate<'a> {
16    pub fn new(id: &'a str) -> ContactUpdate {
17        Self {
18            contact: ContactUpdateRequestData {
19                xmlns: XMLNS,
20                id: id.into(),
21                add_statuses: None,
22                remove_statuses: None,
23                change_info: None,
24            },
25        }
26    }
27
28    /// Sets the data for the &lt;chg&gt; tag for the contact update request
29    pub fn set_info(
30        &mut self,
31        email: &'a str,
32        postal_info: PostalInfo<'a>,
33        voice: Phone<'a>,
34        auth_password: &'a str,
35    ) {
36        self.contact.change_info = Some(ContactChangeInfo {
37            email: Some(email.into()),
38            postal_info: Some(postal_info),
39            voice: Some(voice),
40            auth_info: Some(ContactAuthInfo::new(auth_password)),
41            fax: None,
42        });
43    }
44
45    /// Sets the data for the &lt;fax&gt; tag under &lt;chg&gt; for the contact update request
46    pub fn set_fax(&mut self, fax: Phone<'a>) {
47        if let Some(info) = &mut self.contact.change_info {
48            info.fax = Some(fax)
49        }
50    }
51
52    /// Sets the data for the &lt;add&gt; tag for the contact update request
53    pub fn add(&mut self, status: &'a [ObjectStatus]) {
54        self.contact.add_statuses = Some(StatusList { status });
55    }
56
57    /// Sets the data for the &lt;rem&gt; tag for the contact update request
58    pub fn remove(&mut self, status: &'a [ObjectStatus]) {
59        self.contact.remove_statuses = Some(StatusList { status });
60    }
61}
62
63/// Type for elements under the &lt;chg&gt; tag for contact update request
64#[derive(Serialize, Debug)]
65pub struct ContactChangeInfo<'a> {
66    #[serde(rename = "contact:postalInfo")]
67    postal_info: Option<PostalInfo<'a>>,
68    #[serde(rename = "contact:voice")]
69    voice: Option<Phone<'a>>,
70    #[serde(rename = "contact:fax")]
71    fax: Option<Phone<'a>>,
72    #[serde(rename = "contact:email")]
73    email: Option<StringValue<'a>>,
74    #[serde(rename = "contact:authInfo")]
75    auth_info: Option<ContactAuthInfo<'a>>,
76}
77
78/// Type for list of elements of the &lt;status&gt; tag for contact update request
79#[derive(Serialize, Debug)]
80pub struct StatusList<'a> {
81    #[serde(rename = "contact:status")]
82    status: &'a [ObjectStatus<'a>],
83}
84
85/// Type for elements under the contact &lt;update&gt; tag
86#[derive(Serialize, Debug)]
87pub struct ContactUpdateRequestData<'a> {
88    #[serde(rename = "xmlns:contact")]
89    xmlns: &'a str,
90    #[serde(rename = "contact:id")]
91    id: StringValue<'a>,
92    #[serde(rename = "contact:add")]
93    add_statuses: Option<StatusList<'a>>,
94    #[serde(rename = "contact:rem")]
95    remove_statuses: Option<StatusList<'a>>,
96    #[serde(rename = "contact:chg")]
97    change_info: Option<ContactChangeInfo<'a>>,
98}
99
100#[derive(Serialize, Debug)]
101/// Type for EPP XML &lt;update&gt; command for contacts
102pub struct ContactUpdate<'a> {
103    /// The data under the &lt;update&gt; tag for the contact update
104    #[serde(rename = "contact:update")]
105    contact: ContactUpdateRequestData<'a>,
106}
107
108#[cfg(test)]
109mod tests {
110    use super::{ContactUpdate, Phone, PostalInfo};
111    use crate::common::ObjectStatus;
112    use crate::contact::Address;
113    use crate::response::ResultCode;
114    use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID};
115
116    #[test]
117    fn command() {
118        let mut object = ContactUpdate::new("eppdev-contact-3");
119
120        let street = &["58", "Orchid Road"];
121        let address = Address::new(street, "Paris", "Paris", "392374", "FR".parse().unwrap());
122        let postal_info = PostalInfo::new("loc", "John Doe", "Acme Widgets", address);
123        let voice = Phone::new("+33.47237942");
124
125        object.set_info("newemail@eppdev.net", postal_info, voice, "eppdev-387323");
126        let add_statuses = &[ObjectStatus {
127            status: "clientTransferProhibited".into(),
128        }];
129        object.add(add_statuses);
130        let remove_statuses = &[ObjectStatus {
131            status: "clientDeleteProhibited".into(),
132        }];
133        object.remove(remove_statuses);
134
135        assert_serialized("request/contact/update.xml", &object);
136    }
137
138    #[test]
139    fn contact_update() {
140        let object = response_from_file::<ContactUpdate>("response/contact/update.xml");
141        assert_eq!(object.result.code, ResultCode::CommandCompletedSuccessfully);
142        assert_eq!(object.result.message, SUCCESS_MSG.into());
143        assert_eq!(object.tr_ids.client_tr_id.unwrap(), CLTRID.into());
144        assert_eq!(object.tr_ids.server_tr_id, SVTRID.into());
145    }
146}