epp_client/domain/
update.rs

1//! Types for EPP domain check request
2//!
3use super::{DomainAuthInfo, DomainContact, HostList, XMLNS};
4use crate::{
5    common::{NoExtension, ObjectStatus, StringValue},
6    request::{Command, Transaction},
7};
8
9use serde::Serialize;
10
11impl<'a> Transaction<NoExtension> for DomainUpdate<'a> {}
12
13impl<'a> Command for DomainUpdate<'a> {
14    type Response = ();
15    const COMMAND: &'static str = "update";
16}
17
18impl<'a> DomainUpdate<'a> {
19    pub fn new(name: &'a str) -> Self {
20        Self {
21            domain: DomainUpdateRequestData {
22                xmlns: XMLNS,
23                name: name.into(),
24                add: None,
25                remove: None,
26                change_info: None,
27            },
28        }
29    }
30
31    /// Sets the data for the &lt;chg&gt; tag
32    pub fn info(&mut self, info: DomainChangeInfo<'a>) {
33        self.domain.change_info = Some(info);
34    }
35
36    /// Sets the data for the &lt;add&gt; tag
37    pub fn add(&mut self, add: DomainAddRemove<'a>) {
38        self.domain.add = Some(add);
39    }
40
41    /// Sets the data for the &lt;rem&gt; tag
42    pub fn remove(&mut self, remove: DomainAddRemove<'a>) {
43        self.domain.remove = Some(remove);
44    }
45}
46
47/// Type for elements under the &lt;chg&gt; tag for domain update
48#[derive(Serialize, Debug)]
49pub struct DomainChangeInfo<'a> {
50    /// The new registrant contact for the domain
51    #[serde(rename = "domain:registrant")]
52    pub registrant: Option<StringValue<'a>>,
53    /// The new auth info for the domain
54    #[serde(rename = "domain:authInfo")]
55    pub auth_info: Option<DomainAuthInfo<'a>>,
56}
57
58/// Type for elements under the &lt;add&gt; and &lt;rem&gt; tags for domain update
59#[derive(Serialize, Debug)]
60pub struct DomainAddRemove<'a> {
61    /// The list of nameservers to add or remove
62    /// Type T can be either a `HostObjList` or `HostAttrList`
63    #[serde(rename = "domain:ns")]
64    pub ns: Option<HostList<'a>>,
65    /// The list of contacts to add to or remove from the domain
66    #[serde(rename = "domain:contact")]
67    pub contacts: Option<&'a [DomainContact<'a>]>,
68    /// The list of statuses to add to or remove from the domain
69    #[serde(rename = "domain:status")]
70    pub statuses: Option<&'a [ObjectStatus<'a>]>,
71}
72
73/// Type for elements under the &lt;update&gt; tag for domain update
74#[derive(Serialize, Debug)]
75pub struct DomainUpdateRequestData<'a> {
76    /// XML namespace for domain commands
77    #[serde(rename = "xmlns:domain")]
78    pub xmlns: &'a str,
79    /// The name of the domain to update
80    #[serde(rename = "domain:name")]
81    pub name: StringValue<'a>,
82    /// `DomainAddRemove` Object containing the list of elements to be added
83    /// to the domain
84    #[serde(rename = "domain:add")]
85    pub add: Option<DomainAddRemove<'a>>,
86    /// `DomainAddRemove` Object containing the list of elements to be removed
87    /// from the domain
88    #[serde(rename = "domain:rem")]
89    pub remove: Option<DomainAddRemove<'a>>,
90    /// The data under the &lt;chg&gt; tag for domain update
91    #[serde(rename = "domain:chg")]
92    pub change_info: Option<DomainChangeInfo<'a>>,
93}
94
95#[derive(Serialize, Debug)]
96/// Type for EPP XML &lt;update&gt; command for domains
97pub struct DomainUpdate<'a> {
98    #[serde(rename = "domain:update")]
99    pub domain: DomainUpdateRequestData<'a>,
100}
101
102#[cfg(test)]
103mod tests {
104    use super::{DomainAddRemove, DomainAuthInfo, DomainChangeInfo, DomainContact, DomainUpdate};
105    use crate::common::ObjectStatus;
106    use crate::response::ResultCode;
107    use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID};
108
109    #[test]
110    fn command() {
111        let mut object = DomainUpdate::new("eppdev.com");
112
113        let statuses = &[ObjectStatus {
114            status: "clientDeleteProhibited".into(),
115        }];
116
117        let add = DomainAddRemove {
118            ns: None,
119            contacts: None,
120            statuses: Some(statuses),
121        };
122
123        let contacts = &[DomainContact {
124            contact_type: "billing".into(),
125            id: "eppdev-contact-2".into(),
126        }];
127
128        let remove = DomainAddRemove {
129            ns: None,
130            contacts: Some(contacts),
131            statuses: None,
132        };
133
134        let change_info = DomainChangeInfo {
135            registrant: None,
136            auth_info: Some(DomainAuthInfo::new("epP5uthd#v")),
137        };
138
139        object.add(add);
140        object.remove(remove);
141        object.info(change_info);
142        assert_serialized("request/domain/update.xml", &object);
143    }
144
145    #[test]
146    fn response() {
147        let object = response_from_file::<DomainUpdate>("response/domain/update.xml");
148
149        assert_eq!(object.result.code, ResultCode::CommandCompletedSuccessfully);
150        assert_eq!(object.result.message, SUCCESS_MSG.into());
151        assert_eq!(object.tr_ids.client_tr_id.unwrap(), CLTRID.into());
152        assert_eq!(object.tr_ids.server_tr_id, SVTRID.into());
153    }
154}