instant_epp/domain/
info.rs

1//! Types for EPP domain info request
2
3use chrono::{DateTime, Utc};
4use instant_xml::{FromXml, ToXml};
5
6use super::{DomainAuthInfo, DomainContact, HostAttr, NameServers, Status, XMLNS};
7use crate::common::{NoExtension, EPP_XMLNS};
8use crate::request::{Command, Transaction};
9
10impl<'a> Transaction<NoExtension> for DomainInfo<'a> {}
11
12impl<'a> Command for DomainInfo<'a> {
13    type Response = InfoData;
14    const COMMAND: &'static str = "info";
15}
16
17impl<'a> DomainInfo<'a> {
18    pub fn new(name: &'a str, auth_password: Option<&'a str>) -> Self {
19        Self {
20            info: DomainInfoRequestData {
21                name: Domain { hosts: "all", name },
22                auth_info: auth_password.map(|password| DomainAuthInfo {
23                    password: password.into(),
24                }),
25            },
26        }
27    }
28}
29
30// Request
31
32/// Type for data under the `<name>` element tag for the domain `<info>` tag
33#[derive(Debug, ToXml)]
34#[xml(rename = "name", ns(XMLNS))]
35pub struct Domain<'a> {
36    /// The hosts attribute. Default value is "all"
37    #[xml(attribute)]
38    hosts: &'a str,
39    /// The name of the domain
40    #[xml(direct)]
41    name: &'a str,
42}
43
44/// Type for `<name>` element under the domain `<info>` tag
45#[derive(Debug, ToXml)]
46#[xml(rename = "info", ns(XMLNS))]
47pub struct DomainInfoRequestData<'a> {
48    /// The data for the domain to be queried
49    name: Domain<'a>,
50    /// The auth info for the domain
51    auth_info: Option<DomainAuthInfo<'a>>,
52}
53
54#[derive(Debug, ToXml)]
55/// Type for EPP XML `<info>` command for domains
56#[xml(rename = "info", ns(EPP_XMLNS))]
57pub struct DomainInfo<'a> {
58    /// The data under the `<info>` tag for domain info
59    info: DomainInfoRequestData<'a>,
60}
61
62// Response
63
64/// The two types of ns lists, hostObj and hostAttr, that may be returned in the
65/// domain info response
66#[derive(Debug, FromXml)]
67pub struct DomainNsList {
68    /// List of `<hostObj>` ns elements
69    #[xml(rename = "hostObj")]
70    pub host_obj: Option<Vec<String>>,
71    /// List of `<hostAttr>` ns elements
72    pub host_attr: Option<Vec<HostAttr<'static>>>,
73}
74
75/// Type that represents the `<infData>` tag for domain info response
76#[derive(Debug, FromXml)]
77#[xml(rename = "infData", ns(XMLNS))]
78pub struct InfoData {
79    /// The domain name
80    pub name: String,
81    /// The domain ROID
82    pub roid: String,
83    /// The list of domain statuses
84    #[xml(rename = "status")]
85    pub statuses: Option<Vec<Status>>,
86    /// The domain registrant
87    pub registrant: Option<String>,
88    /// The list of domain contacts
89    #[xml(rename = "contact")]
90    pub contacts: Option<Vec<DomainContact<'static>>>,
91    /// The list of domain nameservers
92    pub ns: Option<NameServers<'static>>,
93    /// The list of domain hosts
94    #[xml(rename = "host")]
95    pub hosts: Option<Vec<String>>,
96    /// The epp user who owns the domain
97    #[xml(rename = "clID")]
98    pub client_id: String,
99    /// The epp user who created the domain
100    #[xml(rename = "crID")]
101    pub creator_id: Option<String>,
102    /// The domain creation date
103    #[xml(rename = "crDate")]
104    pub created_at: Option<DateTime<Utc>>,
105    /// The domain expiry date
106    #[xml(rename = "exDate")]
107    pub expiring_at: Option<DateTime<Utc>>,
108    /// The epp user who last updated the domain
109    #[xml(rename = "upID")]
110    pub updater_id: Option<String>,
111    /// The domain last updated date
112    #[xml(rename = "upDate")]
113    pub updated_at: Option<DateTime<Utc>>,
114    /// The domain transfer date
115    #[xml(rename = "trDate")]
116    pub transferred_at: Option<DateTime<Utc>>,
117    /// The domain auth info
118    #[xml(rename = "authInfo")]
119    pub auth_info: Option<DomainAuthInfo<'static>>,
120}
121
122#[cfg(test)]
123mod tests {
124    use super::DomainInfo;
125    use crate::domain::{HostInfo, HostObj, Status};
126    use crate::response::ResultCode;
127    use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID};
128    use chrono::{TimeZone, Utc};
129
130    #[test]
131    fn command() {
132        let object = DomainInfo::new("eppdev.com", Some("2fooBAR"));
133        assert_serialized("request/domain/info.xml", &object);
134    }
135
136    #[test]
137    fn response() {
138        let object = response_from_file::<DomainInfo>("response/domain/info.xml");
139        dbg!(&object);
140
141        let result = object.res_data().unwrap();
142        let auth_info = result.auth_info.as_ref().unwrap();
143        let ns = result.ns.as_ref().unwrap();
144        let hosts = result.hosts.as_ref().unwrap();
145        let statuses = result.statuses.as_ref().unwrap();
146        let registrant = result.registrant.as_ref().unwrap();
147        let contacts = result.contacts.as_ref().unwrap();
148
149        assert_eq!(object.result.code, ResultCode::CommandCompletedSuccessfully);
150        assert_eq!(object.result.message, SUCCESS_MSG);
151        assert_eq!(result.name, "eppdev-1.com");
152        assert_eq!(result.roid, "125899511_DOMAIN_COM-VRSN");
153        assert_eq!(statuses[0], Status::Ok);
154        assert_eq!(statuses[1], Status::ClientTransferProhibited);
155        assert_eq!(*registrant, "eppdev-contact-2");
156        assert_eq!(contacts[0].id, "eppdev-contact-2".to_string());
157        assert_eq!(contacts[0].contact_type, "admin".to_string());
158        assert_eq!(contacts[1].id, "eppdev-contact-2".to_string());
159        assert_eq!(contacts[1].contact_type, "tech".to_string());
160        assert_eq!(contacts[2].id, "eppdev-contact-2".to_string());
161        assert_eq!(contacts[2].contact_type, "billing".to_string());
162        assert_eq!(
163            ns.ns[0],
164            HostInfo::Obj(HostObj {
165                name: "ns1.eppdev-1.com".into()
166            })
167        );
168        assert_eq!(
169            ns.ns[1],
170            HostInfo::Obj(HostObj {
171                name: "ns2.eppdev-1.com".into()
172            })
173        );
174        assert_eq!((*hosts)[0], "ns1.eppdev-1.com");
175        assert_eq!((*hosts)[1], "ns2.eppdev-1.com");
176        assert_eq!(result.client_id, "eppdev");
177        assert_eq!(*result.creator_id.as_ref().unwrap(), "SYSTEM");
178        assert_eq!(
179            *result.created_at.as_ref().unwrap(),
180            Utc.with_ymd_and_hms(2021, 7, 23, 15, 31, 20).unwrap()
181        );
182        assert_eq!(*result.updater_id.as_ref().unwrap(), "SYSTEM");
183        assert_eq!(
184            *result.updated_at.as_ref().unwrap(),
185            Utc.with_ymd_and_hms(2021, 7, 23, 15, 31, 21).unwrap()
186        );
187        assert_eq!(
188            *result.expiring_at.as_ref().unwrap(),
189            Utc.with_ymd_and_hms(2023, 7, 23, 15, 31, 20).unwrap()
190        );
191        assert_eq!(auth_info.password, "epP4uthd#v");
192        assert_eq!(object.tr_ids.client_tr_id.unwrap(), CLTRID);
193        assert_eq!(object.tr_ids.server_tr_id, SVTRID);
194    }
195
196    #[test]
197    fn response_alt() {
198        response_from_file::<DomainInfo>("response/domain/info_alt.xml");
199    }
200}