diff --git a/epp-client-macros/src/lib.rs b/epp-client-macros/src/lib.rs index 4032e48..c6359ab 100644 --- a/epp-client-macros/src/lib.rs +++ b/epp-client-macros/src/lib.rs @@ -6,11 +6,11 @@ use quote::quote; fn element_name_macro(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; let mut elem_name = ast.ident.to_string(); - let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl(); + let (impl_generics, type_generics, _) = &ast.generics.split_for_impl(); if ast.attrs.len() > 0 { let attribute = &ast.attrs[0]; - let meta = match attribute.parse_meta() { + match attribute.parse_meta() { Ok(syn::Meta::List(meta)) => { if meta.nested.len() > 0 { elem_name = match &meta.nested[0] { diff --git a/epp-client/Cargo.toml b/epp-client/Cargo.toml index 2fccefc..a95fda1 100644 --- a/epp-client/Cargo.toml +++ b/epp-client/Cargo.toml @@ -12,6 +12,7 @@ path = "examples/client.rs" [dependencies] epp-client-macros = { path = "../epp-client-macros" } bytes = "1" +chrono = "0.4" confy = "0.4" futures = "0.3" lazy_static = "1.4" diff --git a/epp-client/examples/client.rs b/epp-client/examples/client.rs index 05d450e..48051d2 100644 --- a/epp-client/examples/client.rs +++ b/epp-client/examples/client.rs @@ -1,31 +1,29 @@ +use std::{error::Error, time::SystemTime}; +use chrono::NaiveDate; + use epp_client::EppClient; -use epp_client::{epp::request::generate_client_tr_id, epp::xml::EppXml}; -use epp_client::epp::object::data::{PostalInfo, Address, Phone, DomainContact, ContactStatus}; -use epp_client::epp::EppDomainCheck; -use epp_client::epp::EppDomainCheckResponse; -use epp_client::epp::EppContactCheck; -use epp_client::epp::EppContactCheckResponse; -use epp_client::epp::EppContactCreate; -use epp_client::epp::EppContactCreateResponse; -use epp_client::epp::EppContactInfo; -use epp_client::epp::EppContactInfoResponse; -use epp_client::epp::EppContactUpdate; -use epp_client::epp::EppContactUpdateResponse; -use epp_client::epp::EppContactDelete; -use epp_client::epp::EppContactDeleteResponse; -use epp_client::epp::EppDomainCreate; -use epp_client::epp::EppDomainCreateResponse; +use epp_client::epp::object::{StringValueTrait}; +use epp_client::{epp::request, epp::xml::EppXml}; +use epp_client::epp::object::data::{ + PostalInfo, Address, Phone, DomainContact, ContactStatus, DomainStatus, HostObjList, HostAttrList, HostAttr, HostAddr +}; +use epp_client::epp::*; + +fn gen_client_tr_id(username: &str) -> Result> { + let timestamp = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?; + Ok(format!("{}:{}", username, timestamp.as_secs())) +} async fn check_domains(client: &mut EppClient) { let domains = vec!["eppdev.com", "hexonet.net"]; - let domain_check = EppDomainCheck::new(domains, generate_client_tr_id("eppdev").unwrap().as_str()); + let domain_check = EppDomainCheck::new(domains, gen_client_tr_id("eppdev").unwrap().as_str()); client.transact::<_, EppDomainCheckResponse>(&domain_check).await.unwrap(); } async fn check_contacts(client: &mut EppClient) { let contacts = vec!["eppdev-contact-1", "eppdev-contact-2"]; - let contact_check = EppContactCheck::new(contacts, generate_client_tr_id("eppdev").unwrap().as_str()); + let contact_check = EppContactCheck::new(contacts, gen_client_tr_id("eppdev").unwrap().as_str()); client.transact::<_, EppContactCheckResponse>(&contact_check).await.unwrap(); } @@ -39,7 +37,7 @@ async fn create_contact(client: &mut EppClient) { let mut fax = Phone::new("+47.86698799"); fax.set_extension("677"); - let mut contact_create = EppContactCreate::new("eppdev-contact-2", "contact@eppdev.net", postal_info, voice, "eppdev-387323", generate_client_tr_id("eppdev").unwrap().as_str()); + let mut contact_create = EppContactCreate::new("eppdev-contact-3", "contact@eppdev.net", postal_info, voice, "eppdev-387323", gen_client_tr_id("eppdev").unwrap().as_str()); contact_create.set_fax(fax); // println!("xml: {}", contact_create.serialize().unwrap()); @@ -48,10 +46,10 @@ async fn create_contact(client: &mut EppClient) { } async fn update_contact(client: &mut EppClient) { - let contact_info = EppContactInfo::new("eppdev-contact-1", "eppdev-387323", generate_client_tr_id("eppdev").unwrap().as_str()); + let contact_info = EppContactInfo::new("eppdev-contact-1", "eppdev-387323", gen_client_tr_id("eppdev").unwrap().as_str()); let contact_info_response = client.transact::<_, EppContactInfoResponse>(&contact_info).await.unwrap(); - let mut contact_update = EppContactUpdate::new("eppdev-contact-1", generate_client_tr_id("eppdev").unwrap().as_str()); + let mut contact_update = EppContactUpdate::new("eppdev-contact-1", gen_client_tr_id("eppdev").unwrap().as_str()); let contact_info_res_data = contact_info_response.data.res_data.unwrap(); contact_update.set_info("newemail@eppdev.net", contact_info_res_data.info_data.postal_info, contact_info_res_data.info_data.voice, contact_info_res_data.info_data.auth_info.password.to_string().as_str()); let add_statuses = vec![ContactStatus { status: "clientTransferProhibited".to_string() }]; @@ -63,13 +61,13 @@ async fn update_contact(client: &mut EppClient) { } async fn query_contact(client: &mut EppClient) { - let mut contact_info = EppContactInfo::new("eppdev-contact-2", "eppdev-387323", generate_client_tr_id("eppdev").unwrap().as_str()); + let mut contact_info = EppContactInfo::new("eppdev-contact-2", "eppdev-387323", gen_client_tr_id("eppdev").unwrap().as_str()); client.transact::<_, EppContactInfoResponse>(&contact_info).await.unwrap(); } async fn delete_contact(client: &mut EppClient) { - let contact_delete = EppContactDelete::new("eppdev-contact-1", generate_client_tr_id("eppdev").unwrap().as_str()); + let contact_delete = EppContactDelete::new("eppdev-contact-1", gen_client_tr_id("eppdev").unwrap().as_str()); client.transact::<_, EppContactDeleteResponse>(&contact_delete).await.unwrap(); } @@ -89,15 +87,112 @@ async fn create_domain(client: &mut EppClient) { id: "eppdev-contact-2".to_string() } ]; - // let domain_create = EppDomainCreate::new_with_ns("eppdev.com", 1, vec!["ns1.test.com", "ns2.test.com"], "eppdev-contact-1", "eppdevauth123", contacts, generate_client_tr_id("eppdev").unwrap().as_str()); + // let domain_create = EppDomainCreate::new_with_ns("eppdev.com", 1, vec!["ns1.test.com", "ns2.test.com"], "eppdev-contact-1", "eppdevauth123", contacts, gen_client_tr_id("eppdev").unwrap().as_str()); - let domain_create = EppDomainCreate::new("eppdev.com", 1, "eppdev-contact-2", "epP4uthd#v", contacts, generate_client_tr_id("eppdev").unwrap().as_str()); + let domain_create = EppDomainCreate::new("eppdev-1.com", 1, "eppdev-contact-2", "epP4uthd#v", contacts, gen_client_tr_id("eppdev").unwrap().as_str()); // println!("{}", domain_create.serialize().unwrap()); client.transact::<_, EppDomainCreateResponse>(&domain_create).await.unwrap(); } +async fn query_domain(client: &mut EppClient) { + let domain_info = EppDomainInfo::new("eppdev-1.com", gen_client_tr_id("eppdev").unwrap().as_str()); + + client.transact::<_, EppDomainInfoResponse>(&domain_info).await.unwrap(); +} + +async fn update_domain(client: &mut EppClient) { + let mut domain_update = EppDomainUpdate::new("eppdev.com", gen_client_tr_id("eppdev").unwrap().as_str()); + + let remove = DomainAddRemove { + ns: None, + // ns: Some(HostAttrList { + // hosts: vec![ + // HostAttr { + // name: "ns1.test.com".to_string_value(), + // addresses: Some(vec![ + // HostAddr::new_v4("177.163.23.23"), + // HostAddr::new_v6("213.221.54.17"), + // ] + // )}, + // HostAttr { + // name: "ns2.test.com".to_string_value(), + // addresses: None, + // }, + // ] + // }), + contacts: None, + statuses: Some(vec![ + DomainStatus { + status: "clientDeleteProhibited".to_string() + } + ]) + }; + + let add = DomainAddRemove { + ns: None, + contacts: Some(vec![ + DomainContact { + contact_type: "billing".to_string(), + id: "eppdev-contact-2".to_string() + } + ]), + statuses: None, + }; + + domain_update.add(add); + domain_update.remove(remove); + + // println!("{}", domain_update.serialize().unwrap()); + + client.transact::<_, EppDomainUpdateResponse>(&domain_update).await.unwrap(); +} + +async fn delete_domain(client: &mut EppClient) { + let domain_delete = EppDomainDelete::new("eppdev.com", gen_client_tr_id("eppdev").unwrap().as_str()); + + client.transact::<_, EppDomainDeleteResponse>(&domain_delete).await.unwrap(); +} + +async fn renew_domain(client: &mut EppClient) { + let exp_date = NaiveDate::from_ymd(2022, 7, 23); + + let renew_domain = EppDomainRenew::new("eppdev-1.com", exp_date, 1, gen_client_tr_id("eppdev").unwrap().as_str()); + + client.transact::<_, EppDomainRenewResponse>(&renew_domain).await.unwrap(); +} + +async fn request_transfer(client: &mut EppClient) { + let transfer_request = EppDomainTransferRequest::request("testing.com", 1, "epP4uthd#v", gen_client_tr_id("eppdev").unwrap().as_str()); + + println!("{}\n\n", transfer_request.serialize().unwrap()); +} + +async fn approve_transfer(client: &mut EppClient) { + let transfer_approve = EppDomainTransferRequest::approve("testing.com", gen_client_tr_id("eppdev").unwrap().as_str()); + + println!("{}\n\n", transfer_approve.serialize().unwrap()); +} + +async fn reject_transfer(client: &mut EppClient) { + let transfer_reject = EppDomainTransferRequest::reject("testing.com", gen_client_tr_id("eppdev").unwrap().as_str()); + + println!("{}\n\n", transfer_reject.serialize().unwrap()); +} + +async fn cancel_transfer(client: &mut EppClient) { + let transfer_cancel = EppDomainTransferRequest::cancel("testing.com", gen_client_tr_id("eppdev").unwrap().as_str()); + + println!("{}\n\n", transfer_cancel.serialize().unwrap()); +} + +async fn query_transfer(client: &mut EppClient) { + let transfer_query = EppDomainTransferRequest::query("testing.com", "epP4uthd#v", gen_client_tr_id("eppdev").unwrap().as_str()); + + println!("{}\n\n", transfer_query.serialize().unwrap()); +} + async fn hello(client: &mut EppClient) { let greeting = client.hello().await.unwrap(); @@ -114,6 +209,8 @@ async fn main() { Err(e) => panic!("Error: {}", e) }; + // client.set_client_tr_id_fn(gen_client_tr_id); + // hello(&mut client).await; // check_domains(&mut client).await; @@ -129,4 +226,22 @@ async fn main() { // delete_contact(&mut client).await; // create_domain(&mut client).await; + + // query_domain(&mut client).await; + + // update_domain(&mut client).await; + + // delete_domain(&mut client).await; + + // renew_domain(&mut client).await; + + // request_transfer(&mut client).await; + + // query_transfer(&mut client).await; + + // approve_transfer(&mut client).await; + + // reject_transfer(&mut client).await; + + // cancel_transfer(&mut client).await; } diff --git a/epp-client/src/connection/client.rs b/epp-client/src/connection/client.rs index 41d43ea..786fe17 100644 --- a/epp-client/src/connection/client.rs +++ b/epp-client/src/connection/client.rs @@ -1,6 +1,8 @@ use futures::executor::block_on; use std::{error::Error, fmt::Debug}; +// use std::time::SystemTime; use std::sync::mpsc; +// use std::sync::Arc; use crate::config::CONFIG; use crate::connection::registry::{epp_connect, EppConnection}; @@ -8,7 +10,6 @@ use crate::error; use crate::epp::request::{generate_client_tr_id, EppHello, EppLogin, EppLogout}; use crate::epp::response::{EppGreeting, EppCommandResponseStatus, EppCommandResponse, EppCommandResponseError}; use crate::epp::xml::EppXml; -use crate::epp::object::{ElementName, EppObject}; async fn connect(registry: &'static str) -> Result> { let registry_creds = match CONFIG.registry(registry) { @@ -40,9 +41,27 @@ async fn connect(registry: &'static str) -> Result> { pub struct EppClient { credentials: (String, String), connection: EppConnection, + // pub client_tr_id_fn: Arc String + Send + Sync>, } +// fn default_client_tr_id_fn(client: &EppClient) -> String { +// let timestamp = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { +// Ok(time) => time, +// Err(e) => panic!("Error in client TRID gen function: {}", e) +// }; +// format!("{}:{}", &client.username(), timestamp.as_secs()) +// } + impl EppClient { + pub fn username(&self) -> String { + self.credentials.0.to_string() + } + + // pub fn set_client_tr_id_fn(&mut self, func: F) + // where F: Fn(&EppClient) -> String + Send + Sync + 'static { + // self.client_tr_id_fn = Arc::new(func); + // } + pub async fn new(registry: &'static str) -> Result> { connect(registry).await } @@ -50,13 +69,14 @@ impl EppClient { async fn build(connection: EppConnection, credentials: (String, String)) -> Result> { let mut client = EppClient { connection: connection, - credentials: credentials + credentials: credentials, + // client_tr_id_fn: Arc::new(default_client_tr_id_fn), }; let client_tr_id = generate_client_tr_id(&client.credentials.0)?; let login_request = EppLogin::new(&client.credentials.0, &client.credentials.1, client_tr_id.as_str()); - client.transact::(&login_request).await?; + client.transact::<_, EppCommandResponse>(&login_request).await?; Ok(client) } @@ -109,7 +129,7 @@ impl EppClient { let client_tr_id = generate_client_tr_id(&self.credentials.0).unwrap(); let epp_logout = EppLogout::new(client_tr_id.as_str()); - self.transact::(&epp_logout).await; + self.transact::<_, EppCommandResponse>(&epp_logout).await; } } diff --git a/epp-client/src/connection/registry.rs b/epp-client/src/connection/registry.rs index f8d7473..dc9e276 100644 --- a/epp-client/src/connection/registry.rs +++ b/epp-client/src/connection/registry.rs @@ -59,12 +59,6 @@ impl EppConnection { self.write(&buf).await } - async fn read(&mut self) -> Result, Box> { - let mut buf = vec![0u8; 4096]; - self.stream.reader.read(&mut buf).await?; - Ok(buf) - } - async fn read_epp_response(&mut self) -> Result, Box> { let mut buf = [0u8; 4]; self.stream.reader.read_exact(&mut buf).await?; diff --git a/epp-client/src/epp.rs b/epp-client/src/epp.rs index 1f00fb9..ffb7cfb 100644 --- a/epp-client/src/epp.rs +++ b/epp-client/src/epp.rs @@ -12,6 +12,12 @@ pub use request::contact::info::*; pub use request::contact::update::*; pub use request::domain::check::*; pub use request::domain::create::*; +pub use request::domain::delete::*; +pub use request::domain::info::*; +pub use request::domain::renew::*; +pub use request::domain::transfer::*; +pub use request::domain::update::*; + pub use response::contact::check::*; pub use response::contact::create::*; pub use response::contact::delete::*; @@ -19,3 +25,8 @@ pub use response::contact::info::*; pub use response::contact::update::*; pub use response::domain::check::*; pub use response::domain::create::*; +pub use response::domain::delete::*; +pub use response::domain::info::*; +pub use response::domain::renew::*; +pub use response::domain::transfer::*; +pub use response::domain::update::*; diff --git a/epp-client/src/epp/object.rs b/epp-client/src/epp/object.rs index 74fbc8c..3f695b3 100644 --- a/epp-client/src/epp/object.rs +++ b/epp-client/src/epp/object.rs @@ -30,6 +30,12 @@ impl StringValueTrait for &str { } } +impl StringValueTrait for String { + fn to_string_value(&self) -> StringValue { + StringValue(self.to_string()) + } +} + pub trait ElementName { fn element_name(&self) -> &'static str; } diff --git a/epp-client/src/epp/object/data.rs b/epp-client/src/epp/object/data.rs index 4af18dc..2ff97aa 100644 --- a/epp-client/src/epp/object/data.rs +++ b/epp-client/src/epp/object/data.rs @@ -1,6 +1,63 @@ use crate::epp::object::{StringValue, StringValueTrait}; use serde::{Deserialize, Serialize}; +#[derive(Serialize, Deserialize, Debug)] +pub enum DomainNsList { + HostAttrList(HostAttrList), + HostObjList(HostObjList), +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct HostAddr { + #[serde(rename = "ip")] + ip_version: Option, + #[serde(rename = "$value")] + address: String, +} + +impl HostAddr { + pub fn new(ip_version: &str, address: &str) -> HostAddr { + HostAddr { + ip_version: Some(ip_version.to_string()), + address: address.to_string(), + } + } + + pub fn new_v4(address: &str) -> HostAddr { + HostAddr { + ip_version: Some("v4".to_string()), + address: address.to_string(), + } + } + + pub fn new_v6(address: &str) -> HostAddr { + HostAddr { + ip_version: Some("v6".to_string()), + address: address.to_string(), + } + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct HostAttr { + #[serde(rename = "hostName")] + pub name: StringValue, + #[serde(rename = "hostAddr")] + pub addresses: Option>, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct HostAttrList { + #[serde(rename = "hostAttr")] + pub hosts: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct HostObjList { + #[serde(rename = "hostObj")] + pub hosts: Vec, +} + #[derive(Serialize, Deserialize, Debug)] pub struct DomainContact { #[serde(rename = "$value")] @@ -29,6 +86,12 @@ impl Period { } } +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainStatus { + #[serde(rename = "s")] + pub status: String, +} + #[derive(Serialize, Deserialize, Debug)] pub struct ContactStatus { #[serde(rename = "s")] diff --git a/epp-client/src/epp/quick_xml.rs b/epp-client/src/epp/quick_xml.rs index ad59c12..1f01051 100644 --- a/epp-client/src/epp/quick_xml.rs +++ b/epp-client/src/epp/quick_xml.rs @@ -17,7 +17,7 @@ impl EppXml for EppObject } fn deserialize(epp_xml: &str) -> Result { - let mut object: Self::Output = match from_str(epp_xml) { + let object: Self::Output = match from_str(epp_xml) { Ok(v) => v, Err(e) => { return Err(error::Error::EppDeserializationError( diff --git a/epp-client/src/epp/request/contact/delete.rs b/epp-client/src/epp/request/contact/delete.rs index 5b0cf75..fd8f1eb 100644 --- a/epp-client/src/epp/request/contact/delete.rs +++ b/epp-client/src/epp/request/contact/delete.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; pub type EppContactDelete = EppObject>; #[derive(Serialize, Deserialize, Debug)] -pub struct ContactData { +pub struct ContactDeleteData { pub xmlns: String, pub id: StringValue, } @@ -17,14 +17,14 @@ pub struct ContactData { #[element_name(name = "delete")] pub struct ContactDelete { #[serde(rename = "delete")] - contact: ContactData, + contact: ContactDeleteData, } impl EppContactDelete { pub fn new(id: &str, client_tr_id: &str) -> EppContactDelete { EppObject::build(Command:: { command: ContactDelete { - contact: ContactData { + contact: ContactDeleteData { xmlns: EPP_CONTACT_XMLNS.to_string(), id: id.to_string_value(), }, diff --git a/epp-client/src/epp/request/domain.rs b/epp-client/src/epp/request/domain.rs index 3aa3078..cd7f494 100644 --- a/epp-client/src/epp/request/domain.rs +++ b/epp-client/src/epp/request/domain.rs @@ -1,2 +1,7 @@ pub mod check; pub mod create; +pub mod delete; +pub mod info; +pub mod renew; +pub mod transfer; +pub mod update; diff --git a/epp-client/src/epp/request/domain/create.rs b/epp-client/src/epp/request/domain/create.rs index 7a674ab..b4d2d32 100644 --- a/epp-client/src/epp/request/domain/create.rs +++ b/epp-client/src/epp/request/domain/create.rs @@ -1,7 +1,9 @@ use epp_client_macros::*; use crate::epp::command::Command; -use crate::epp::object::data::{AuthInfo, DomainContact, Period}; +use crate::epp::object::data::{ + AuthInfo, DomainContact, HostAttr, HostAttrList, HostObjList, Period, +}; use crate::epp::object::{ElementName, EppObject, StringValue, StringValueTrait}; use crate::epp::xml::EPP_DOMAIN_XMLNS; use serde::{Deserialize, Serialize}; @@ -9,59 +11,8 @@ use serde::{Deserialize, Serialize}; pub type EppDomainCreate = EppObject>>; pub type EppDomainCreateWithHostAttr = EppObject>>; -pub enum HostType { - HostObj, - HostAttr, -} - -pub trait HostList { - fn new(ns: Vec<&str>) -> Self; -} - #[derive(Serialize, Deserialize, Debug)] -pub struct HostAttr { - #[serde(rename = "hostName")] - host_name: StringValue, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct HostAttrList { - #[serde(rename = "hostAttr")] - hosts: Vec, -} - -impl HostList for HostAttrList { - fn new(ns: Vec<&str>) -> HostAttrList { - let ns_list = ns - .iter() - .map(|n| HostAttr { - host_name: n.to_string_value(), - }) - .collect::>(); - - HostAttrList { hosts: ns_list } - } -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct HostObjList { - #[serde(rename = "hostObj")] - hosts: Vec, -} - -impl HostList for HostObjList { - fn new(ns: Vec<&str>) -> HostObjList { - let ns_list = ns - .iter() - .map(|n| n.to_string_value()) - .collect::>(); - - HostObjList { hosts: ns_list } - } -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct DomainData { +pub struct DomainCreateData { xmlns: String, name: StringValue, period: Period, @@ -77,7 +28,7 @@ pub struct DomainData { #[element_name(name = "create")] pub struct DomainCreate { #[serde(rename = "create")] - domain: DomainData, + domain: DomainCreateData, } impl EppDomainCreate { @@ -90,13 +41,18 @@ impl EppDomainCreate { contacts: Vec, client_tr_id: &str, ) -> EppDomainCreate { + let ns_list = ns + .iter() + .map(|n| n.to_string_value()) + .collect::>(); + EppObject::build(Command::> { command: DomainCreate { - domain: DomainData { + domain: DomainCreateData { xmlns: EPP_DOMAIN_XMLNS.to_string(), name: name.to_string_value(), period: Period::new(period), - ns: Some(HostObjList::new(ns)), + ns: Some(HostObjList { hosts: ns_list }), registrant: Some(registrant_id.to_string_value()), auth_info: AuthInfo::new(auth_password), contacts: Some(contacts), @@ -116,7 +72,7 @@ impl EppDomainCreate { ) -> EppDomainCreate { EppObject::build(Command::> { command: DomainCreate { - domain: DomainData { + domain: DomainCreateData { xmlns: EPP_DOMAIN_XMLNS.to_string(), name: name.to_string_value(), period: Period::new(period), @@ -138,7 +94,7 @@ impl EppDomainCreate { ) -> EppDomainCreate { EppObject::build(Command::> { command: DomainCreate { - domain: DomainData { + domain: DomainCreateData { xmlns: EPP_DOMAIN_XMLNS.to_string(), name: name.to_string_value(), period: Period::new(period), @@ -155,7 +111,7 @@ impl EppDomainCreate { pub fn new_with_host_attr( name: &str, period: u16, - ns: Vec<&str>, + ns: Vec, registrant_id: &str, auth_password: &str, contacts: Vec, @@ -163,11 +119,11 @@ impl EppDomainCreate { ) -> EppDomainCreateWithHostAttr { EppObject::build(Command::> { command: DomainCreate { - domain: DomainData { + domain: DomainCreateData { xmlns: EPP_DOMAIN_XMLNS.to_string(), name: name.to_string_value(), period: Period::new(period), - ns: Some(HostAttrList::new(ns)), + ns: Some(HostAttrList { hosts: ns }), registrant: Some(registrant_id.to_string_value()), auth_info: AuthInfo::new(auth_password), contacts: Some(contacts), diff --git a/epp-client/src/epp/request/domain/delete.rs b/epp-client/src/epp/request/domain/delete.rs new file mode 100644 index 0000000..454180e --- /dev/null +++ b/epp-client/src/epp/request/domain/delete.rs @@ -0,0 +1,35 @@ +use epp_client_macros::*; + +use crate::epp::command::Command; +use crate::epp::object::{ElementName, EppObject, StringValue, StringValueTrait}; +use crate::epp::xml::EPP_DOMAIN_XMLNS; +use serde::{Deserialize, Serialize}; + +pub type EppDomainDelete = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainDeleteData { + pub xmlns: String, + pub name: StringValue, +} + +#[derive(Serialize, Deserialize, Debug, ElementName)] +#[element_name(name = "delete")] +pub struct DomainDelete { + #[serde(rename = "delete")] + domain: DomainDeleteData, +} + +impl EppDomainDelete { + pub fn new(name: &str, client_tr_id: &str) -> EppDomainDelete { + EppObject::build(Command:: { + command: DomainDelete { + domain: DomainDeleteData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } +} diff --git a/epp-client/src/epp/request/domain/info.rs b/epp-client/src/epp/request/domain/info.rs new file mode 100644 index 0000000..607f874 --- /dev/null +++ b/epp-client/src/epp/request/domain/info.rs @@ -0,0 +1,46 @@ +use epp_client_macros::*; + +use crate::epp::command::Command; +use crate::epp::object::{ElementName, EppObject, StringValueTrait}; +use crate::epp::xml::EPP_DOMAIN_XMLNS; +use serde::{Deserialize, Serialize}; + +pub type EppDomainInfo = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Domain { + hosts: String, + #[serde(rename = "$value")] + name: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainInfoData { + xmlns: String, + #[serde(rename = "name")] + domain: Domain, +} + +#[derive(Serialize, Deserialize, Debug, ElementName)] +#[element_name(name = "info")] +pub struct DomainInfo { + #[serde(rename = "info")] + info: DomainInfoData, +} + +impl EppDomainInfo { + pub fn new(name: &str, client_tr_id: &str) -> EppDomainInfo { + EppObject::build(Command:: { + command: DomainInfo { + info: DomainInfoData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + domain: Domain { + hosts: "all".to_string(), + name: name.to_string(), + }, + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } +} diff --git a/epp-client/src/epp/request/domain/renew.rs b/epp-client/src/epp/request/domain/renew.rs new file mode 100644 index 0000000..64494c0 --- /dev/null +++ b/epp-client/src/epp/request/domain/renew.rs @@ -0,0 +1,56 @@ +use epp_client_macros::*; + +use crate::epp::command::Command; +use crate::epp::object::data::Period; +use crate::epp::object::{ElementName, EppObject, StringValue, StringValueTrait}; +use crate::epp::xml::EPP_DOMAIN_XMLNS; +use chrono::NaiveDate; +use serde::{Deserialize, Serialize}; + +pub type EppDomainRenew = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainRenewData { + xmlns: String, + name: StringValue, + #[serde(rename = "curExpDate")] + current_expiry_date: StringValue, + period: Period, +} + +#[derive(Serialize, Deserialize, Debug, ElementName)] +#[element_name(name = "renew")] +pub struct DomainRenew { + #[serde(rename = "renew")] + domain: DomainRenewData, +} + +impl EppDomainRenew { + pub fn new( + name: &str, + current_expiry_date: NaiveDate, + years: u16, + client_tr_id: &str, + ) -> EppDomainRenew { + let exp_date_str = current_expiry_date + .format("%Y-%m-%d") + .to_string() + .to_string_value(); + + EppObject::build(Command:: { + command: DomainRenew { + domain: DomainRenewData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + current_expiry_date: exp_date_str, + period: Period::new(years), + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } + + pub fn set_period(&mut self, period: Period) { + self.data.command.domain.period = period; + } +} diff --git a/epp-client/src/epp/request/domain/transfer.rs b/epp-client/src/epp/request/domain/transfer.rs new file mode 100644 index 0000000..c3385c7 --- /dev/null +++ b/epp-client/src/epp/request/domain/transfer.rs @@ -0,0 +1,125 @@ +use epp_client_macros::*; + +use crate::epp::command::Command; +use crate::epp::object::data::{AuthInfo, Period}; +use crate::epp::object::{ElementName, EppObject, StringValue, StringValueTrait}; +use crate::epp::xml::EPP_DOMAIN_XMLNS; +use serde::{Deserialize, Serialize}; + +pub type EppDomainTransferRequest = EppObject>; +pub type EppDomainTransferApprove = EppObject>; +pub type EppDomainTransferReject = EppObject>; +pub type EppDomainTransferCancel = EppObject>; +pub type EppDomainTransferQuery = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainTransferData { + xmlns: String, + name: StringValue, + period: Option, + #[serde(rename = "authInfo")] + auth_info: Option, +} + +#[derive(Serialize, Deserialize, Debug, ElementName)] +#[element_name(name = "transfer")] +pub struct DomainTransfer { + #[serde(rename = "op")] + operation: String, + #[serde(rename = "transfer")] + domain: DomainTransferData, +} + +impl EppDomainTransferRequest { + pub fn request( + name: &str, + years: u16, + auth_password: &str, + client_tr_id: &str, + ) -> EppDomainTransferRequest { + EppObject::build(Command:: { + command: DomainTransfer { + operation: "request".to_string(), + domain: DomainTransferData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + period: Some(Period::new(years)), + auth_info: Some(AuthInfo::new(auth_password)), + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } + + pub fn set_period(&mut self, period: Period) { + self.data.command.domain.period = Some(period); + } +} + +impl EppDomainTransferApprove { + pub fn approve(name: &str, client_tr_id: &str) -> EppDomainTransferApprove { + EppObject::build(Command:: { + command: DomainTransfer { + operation: "approve".to_string(), + domain: DomainTransferData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + period: None, + auth_info: None, + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } +} + +impl EppDomainTransferCancel { + pub fn cancel(name: &str, client_tr_id: &str) -> EppDomainTransferCancel { + EppObject::build(Command:: { + command: DomainTransfer { + operation: "cancel".to_string(), + domain: DomainTransferData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + period: None, + auth_info: None, + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } +} + +impl EppDomainTransferReject { + pub fn reject(name: &str, client_tr_id: &str) -> EppDomainTransferReject { + EppObject::build(Command:: { + command: DomainTransfer { + operation: "reject".to_string(), + domain: DomainTransferData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + period: None, + auth_info: None, + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } +} + +impl EppDomainTransferQuery { + pub fn query(name: &str, auth_password: &str, client_tr_id: &str) -> EppDomainTransferQuery { + EppObject::build(Command:: { + command: DomainTransfer { + operation: "query".to_string(), + domain: DomainTransferData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + period: None, + auth_info: Some(AuthInfo::new(auth_password)), + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } +} diff --git a/epp-client/src/epp/request/domain/update.rs b/epp-client/src/epp/request/domain/update.rs new file mode 100644 index 0000000..972aeba --- /dev/null +++ b/epp-client/src/epp/request/domain/update.rs @@ -0,0 +1,103 @@ +use epp_client_macros::*; + +use crate::epp::command::Command; +use crate::epp::object::data::{AuthInfo, DomainContact, DomainStatus, HostAttrList, HostObjList}; +use crate::epp::object::{ElementName, EppObject, StringValue, StringValueTrait}; +use crate::epp::xml::EPP_DOMAIN_XMLNS; +use serde::{Deserialize, Serialize}; + +pub type EppDomainUpdate = EppObject>>; +pub type EppDomainUpdateWithHostAttr = EppObject>>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainChangeInfo { + registrant: StringValue, + #[serde(rename = "authInfo")] + auth_info: AuthInfo, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainAddRemove { + #[serde(rename = "ns")] + pub ns: Option, + #[serde(rename = "contact")] + pub contacts: Option>, + #[serde(rename = "status")] + pub statuses: Option>, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainUpdateData { + xmlns: String, + name: StringValue, + add: Option>, + #[serde(rename = "rem")] + remove: Option>, + #[serde(rename = "chg")] + change_info: Option, +} + +#[derive(Serialize, Deserialize, Debug, ElementName)] +#[element_name(name = "update")] +pub struct DomainUpdate { + #[serde(rename = "update")] + domain: DomainUpdateData, +} + +impl EppDomainUpdate { + pub fn new(name: &str, client_tr_id: &str) -> EppDomainUpdate { + EppObject::build(Command::> { + command: DomainUpdate { + domain: DomainUpdateData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + add: None, + remove: None, + change_info: None, + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } + + pub fn info(&mut self, info: DomainChangeInfo) { + self.data.command.domain.change_info = Some(info); + } + + pub fn add(&mut self, add: DomainAddRemove) { + self.data.command.domain.add = Some(add); + } + + pub fn remove(&mut self, remove: DomainAddRemove) { + self.data.command.domain.remove = Some(remove); + } +} + +impl EppDomainUpdateWithHostAttr { + pub fn new(name: &str, client_tr_id: &str) -> EppDomainUpdateWithHostAttr { + EppObject::build(Command::> { + command: DomainUpdate { + domain: DomainUpdateData { + xmlns: EPP_DOMAIN_XMLNS.to_string(), + name: name.to_string_value(), + add: None, + remove: None, + change_info: None, + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } + + pub fn info(&mut self, info: DomainChangeInfo) { + self.data.command.domain.change_info = Some(info); + } + + pub fn add(&mut self, add: DomainAddRemove) { + self.data.command.domain.add = Some(add); + } + + pub fn remove(&mut self, remove: DomainAddRemove) { + self.data.command.domain.remove = Some(remove); + } +} diff --git a/epp-client/src/epp/response.rs b/epp-client/src/epp/response.rs index e810cc2..147f3cd 100644 --- a/epp-client/src/epp/response.rs +++ b/epp-client/src/epp/response.rs @@ -151,12 +151,6 @@ pub struct ResponseTRID { pub server_tr_id: StringValue, } -#[derive(Serialize, Deserialize, Debug, PartialEq)] -pub struct ErrorResponseTRID { - #[serde(rename = "svTRID")] - pub server_tr_id: StringValue, -} - #[derive(Serialize, Deserialize, Debug, PartialEq, ElementName)] #[serde(rename_all = "lowercase")] #[element_name(name = "response")] diff --git a/epp-client/src/epp/response/domain.rs b/epp-client/src/epp/response/domain.rs index 3aa3078..cd7f494 100644 --- a/epp-client/src/epp/response/domain.rs +++ b/epp-client/src/epp/response/domain.rs @@ -1,2 +1,7 @@ pub mod check; pub mod create; +pub mod delete; +pub mod info; +pub mod renew; +pub mod transfer; +pub mod update; diff --git a/epp-client/src/epp/response/domain/delete.rs b/epp-client/src/epp/response/domain/delete.rs new file mode 100644 index 0000000..f91df08 --- /dev/null +++ b/epp-client/src/epp/response/domain/delete.rs @@ -0,0 +1,3 @@ +use crate::epp::response::EppCommandResponse; + +pub type EppDomainDeleteResponse = EppCommandResponse; diff --git a/epp-client/src/epp/response/domain/info.rs b/epp-client/src/epp/response/domain/info.rs new file mode 100644 index 0000000..d99f00c --- /dev/null +++ b/epp-client/src/epp/response/domain/info.rs @@ -0,0 +1,57 @@ +use serde::{Deserialize, Serialize}; + +use crate::epp::object::data::{AuthInfo, DomainContact, DomainNsList, DomainStatus}; +use crate::epp::object::{EppObject, StringValue}; +use crate::epp::response::CommandResponse; + +pub type EppDomainInfoResponse = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainCheck { + #[serde(rename = "$value")] + pub name: StringValue, + #[serde(rename = "avail")] + pub available: u16, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainCheckDataItem { + pub name: DomainCheck, + pub reason: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainInfoData { + #[serde(rename = "xmlns:domain")] + xmlns: String, + pub name: StringValue, + pub roid: StringValue, + pub status: Vec, + pub registrant: StringValue, + #[serde(rename = "contact")] + pub contacts: Vec, + pub ns: Option, + pub host: Option>, + #[serde(rename = "clID")] + pub client_id: StringValue, + #[serde(rename = "crID")] + pub creator_id: StringValue, + #[serde(rename = "crDate")] + pub created_at: StringValue, + #[serde(rename = "upID")] + pub updater_id: StringValue, + #[serde(rename = "upDate")] + pub updated_at: StringValue, + #[serde(rename = "exDate")] + pub expiry_date: StringValue, + #[serde(rename = "trDate")] + pub transferred_at: Option, + #[serde(rename = "authInfo")] + pub auth_info: AuthInfo, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainInfoResult { + #[serde(rename = "infData")] + pub check_data: DomainInfoData, +} diff --git a/epp-client/src/epp/response/domain/renew.rs b/epp-client/src/epp/response/domain/renew.rs new file mode 100644 index 0000000..c648d2e --- /dev/null +++ b/epp-client/src/epp/response/domain/renew.rs @@ -0,0 +1,21 @@ +use serde::{Deserialize, Serialize}; + +use crate::epp::object::{EppObject, StringValue}; +use crate::epp::response::CommandResponse; + +pub type EppDomainRenewResponse = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainRenewData { + #[serde(rename = "xmlns:domain")] + xmlns: String, + name: StringValue, + #[serde(rename = "exDate")] + expiry_date: StringValue, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainRenewResult { + #[serde(rename = "renData")] + pub renew_data: DomainRenewData, +} diff --git a/epp-client/src/epp/response/domain/transfer.rs b/epp-client/src/epp/response/domain/transfer.rs new file mode 100644 index 0000000..cfcbe07 --- /dev/null +++ b/epp-client/src/epp/response/domain/transfer.rs @@ -0,0 +1,36 @@ +use serde::{Deserialize, Serialize}; + +use crate::epp::object::{EppObject, StringValue}; +use crate::epp::response::CommandResponse; +use crate::epp::response::EppCommandResponse; + +pub type EppDomainTransferRequestResponse = EppObject>; +pub type EppDomainTransferApproveResponse = EppCommandResponse; +pub type EppDomainTransferRejectResponse = EppCommandResponse; +pub type EppDomainTransferCancelResponse = EppCommandResponse; +pub type EppDomainTransferQueryResponse = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainTransferData { + #[serde(rename = "xmlns:domain")] + xmlns: String, + name: StringValue, + #[serde(rename = "trStatus")] + transfer_status: StringValue, + #[serde(rename = "reID")] + requester_id: StringValue, + #[serde(rename = "reDate")] + request_date: StringValue, + #[serde(rename = "acID")] + responder_id: StringValue, + #[serde(rename = "acDate")] + respond_by_date: StringValue, + #[serde(rename = "exDate")] + expiry_date: StringValue, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct DomainTransferResult { + #[serde(rename = "trnData")] + pub transfer_data: DomainTransferData, +} diff --git a/epp-client/src/epp/response/domain/update.rs b/epp-client/src/epp/response/domain/update.rs new file mode 100644 index 0000000..ef33ef0 --- /dev/null +++ b/epp-client/src/epp/response/domain/update.rs @@ -0,0 +1,3 @@ +use crate::epp::response::EppCommandResponse; + +pub type EppDomainUpdateResponse = EppCommandResponse;