1use 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#[derive(Debug, ToXml)]
34#[xml(rename = "name", ns(XMLNS))]
35pub struct Domain<'a> {
36 #[xml(attribute)]
38 hosts: &'a str,
39 #[xml(direct)]
41 name: &'a str,
42}
43
44#[derive(Debug, ToXml)]
46#[xml(rename = "info", ns(XMLNS))]
47pub struct DomainInfoRequestData<'a> {
48 name: Domain<'a>,
50 auth_info: Option<DomainAuthInfo<'a>>,
52}
53
54#[derive(Debug, ToXml)]
55#[xml(rename = "info", ns(EPP_XMLNS))]
57pub struct DomainInfo<'a> {
58 info: DomainInfoRequestData<'a>,
60}
61
62#[derive(Debug, FromXml)]
67pub struct DomainNsList {
68 #[xml(rename = "hostObj")]
70 pub host_obj: Option<Vec<String>>,
71 pub host_attr: Option<Vec<HostAttr<'static>>>,
73}
74
75#[derive(Debug, FromXml)]
77#[xml(rename = "infData", ns(XMLNS))]
78pub struct InfoData {
79 pub name: String,
81 pub roid: String,
83 #[xml(rename = "status")]
85 pub statuses: Option<Vec<Status>>,
86 pub registrant: Option<String>,
88 #[xml(rename = "contact")]
90 pub contacts: Option<Vec<DomainContact<'static>>>,
91 pub ns: Option<NameServers<'static>>,
93 #[xml(rename = "host")]
95 pub hosts: Option<Vec<String>>,
96 #[xml(rename = "clID")]
98 pub client_id: String,
99 #[xml(rename = "crID")]
101 pub creator_id: Option<String>,
102 #[xml(rename = "crDate")]
104 pub created_at: Option<DateTime<Utc>>,
105 #[xml(rename = "exDate")]
107 pub expiring_at: Option<DateTime<Utc>>,
108 #[xml(rename = "upID")]
110 pub updater_id: Option<String>,
111 #[xml(rename = "upDate")]
113 pub updated_at: Option<DateTime<Utc>>,
114 #[xml(rename = "trDate")]
116 pub transferred_at: Option<DateTime<Utc>>,
117 #[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}