instant_epp/domain/
update.rs

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