diff --git a/epp-client/examples/client.rs b/epp-client/examples/client.rs index 29d804e..bd7fde6 100644 --- a/epp-client/examples/client.rs +++ b/epp-client/examples/client.rs @@ -1,4 +1,5 @@ use epp_client::{epp::request::generate_client_tr_id, connection::client::EppClient, connection, epp::xml::EppXml}; +use epp_client::epp::object::data::ContactStatus; use epp_client::epp::request::domain::check::EppDomainCheck; use epp_client::epp::response::domain::check::EppDomainCheckResponse; use epp_client::epp::request::contact::check::EppContactCheck; @@ -6,6 +7,12 @@ use epp_client::epp::response::contact::check::EppContactCheckResponse; use epp_client::epp::object::data::{PostalInfo, Address, Phone}; use epp_client::epp::request::contact::create::EppContactCreate; use epp_client::epp::response::contact::create::EppContactCreateResponse; +use epp_client::epp::request::contact::info::EppContactInfo; +use epp_client::epp::response::contact::info::EppContactInfoResponse; +use epp_client::epp::request::contact::update::EppContactUpdate; +use epp_client::epp::response::contact::update::EppContactUpdateResponse; +use epp_client::epp::request::contact::delete::EppContactDelete; +use epp_client::epp::response::contact::delete::EppContactDeleteResponse; async fn check_domains(client: &mut EppClient) { let domains = vec!["eppdev.com", "hexonet.net"]; @@ -38,6 +45,33 @@ async fn create_contact(client: &mut EppClient) { client.transact::<_, EppContactCreateResponse>(&contact_create).await.unwrap(); } +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_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 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() }]; + contact_update.remove_statuses(add_statuses); + + // println!("{}", contact_update.serialize().unwrap()); + + client.transact::<_, EppContactUpdateResponse>(&contact_update).await.unwrap(); +} + +async fn query_contact(client: &mut EppClient) { + let mut contact_info = EppContactInfo::new("eppdev-contact-1", "eppdev-387323", generate_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()); + + client.transact::<_, EppContactDeleteResponse>(&contact_delete).await.unwrap(); +} + async fn hello(client: &mut EppClient) { let greeting = client.hello().await.unwrap(); @@ -60,5 +94,11 @@ async fn main() { // check_contacts(&mut client).await; - create_contact(&mut client).await; + // create_contact(&mut client).await; + + // query_contact(&mut client).await; + + // update_contact(&mut client).await; + + // delete_contact(&mut client).await; } diff --git a/epp-client/src/epp/object.rs b/epp-client/src/epp/object.rs index 36fa103..74fbc8c 100644 --- a/epp-client/src/epp/object.rs +++ b/epp-client/src/epp/object.rs @@ -5,7 +5,7 @@ use std::fmt::Display; use crate::epp::xml::{EPP_XMLNS, EPP_XMLNS_XSI, EPP_XSI_SCHEMA_LOCATION}; -#[derive(Serialize, Deserialize, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub struct StringValue(String); impl Default for StringValue { diff --git a/epp-client/src/epp/object/data.rs b/epp-client/src/epp/object/data.rs index aff677c..d5a855f 100644 --- a/epp-client/src/epp/object/data.rs +++ b/epp-client/src/epp/object/data.rs @@ -2,6 +2,12 @@ use crate::epp::object::{StringValue, StringValueTrait}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] +pub struct ContactStatus { + #[serde(rename = "s")] + pub status: String, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Phone { #[serde(rename = "$value")] pub number: String, @@ -9,7 +15,7 @@ pub struct Phone { extension: Option, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Address { street: Vec, city: StringValue, @@ -21,7 +27,7 @@ pub struct Address { country_code: StringValue, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct PostalInfo { #[serde(rename = "type")] info_type: String, @@ -32,10 +38,10 @@ pub struct PostalInfo { address: Address, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct AuthInfo { #[serde(rename = "pw")] - password: StringValue, + pub password: StringValue, } impl Phone { diff --git a/epp-client/src/epp/request/contact.rs b/epp-client/src/epp/request/contact.rs index 3aa3078..035f812 100644 --- a/epp-client/src/epp/request/contact.rs +++ b/epp-client/src/epp/request/contact.rs @@ -1,2 +1,5 @@ pub mod check; pub mod create; +pub mod delete; +pub mod info; +pub mod update; diff --git a/epp-client/src/epp/request/contact/delete.rs b/epp-client/src/epp/request/contact/delete.rs new file mode 100644 index 0000000..5b0cf75 --- /dev/null +++ b/epp-client/src/epp/request/contact/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_CONTACT_XMLNS; +use serde::{Deserialize, Serialize}; + +pub type EppContactDelete = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ContactData { + pub xmlns: String, + pub id: StringValue, +} + +#[derive(Serialize, Deserialize, Debug, ElementName)] +#[element_name(name = "delete")] +pub struct ContactDelete { + #[serde(rename = "delete")] + contact: ContactData, +} + +impl EppContactDelete { + pub fn new(id: &str, client_tr_id: &str) -> EppContactDelete { + EppObject::build(Command:: { + command: ContactDelete { + contact: ContactData { + xmlns: EPP_CONTACT_XMLNS.to_string(), + id: id.to_string_value(), + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } +} diff --git a/epp-client/src/epp/request/contact/info.rs b/epp-client/src/epp/request/contact/info.rs new file mode 100644 index 0000000..7062778 --- /dev/null +++ b/epp-client/src/epp/request/contact/info.rs @@ -0,0 +1,39 @@ +use epp_client_macros::*; + +use crate::epp::command::Command; +use crate::epp::object::data::AuthInfo; +use crate::epp::object::{ElementName, EppObject, StringValue, StringValueTrait}; +use crate::epp::xml::EPP_CONTACT_XMLNS; +use serde::{Deserialize, Serialize}; + +pub type EppContactInfo = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ContactQuery { + xmlns: String, + id: StringValue, + #[serde(rename = "authInfo")] + auth_info: AuthInfo, +} + +#[derive(Serialize, Deserialize, Debug, ElementName)] +#[element_name(name = "info")] +pub struct ContactInfo { + #[serde(rename = "info")] + query: ContactQuery, +} + +impl EppContactInfo { + pub fn new(id: &str, auth_password: &str, client_tr_id: &str) -> EppContactInfo { + EppObject::build(Command:: { + command: ContactInfo { + query: ContactQuery { + xmlns: EPP_CONTACT_XMLNS.to_string(), + id: id.to_string_value(), + auth_info: AuthInfo::new(auth_password), + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } +} diff --git a/epp-client/src/epp/request/contact/update.rs b/epp-client/src/epp/request/contact/update.rs new file mode 100644 index 0000000..ebd166e --- /dev/null +++ b/epp-client/src/epp/request/contact/update.rs @@ -0,0 +1,115 @@ +use epp_client_macros::*; + +use crate::epp::command::Command; +use crate::epp::object::data::{AuthInfo, ContactStatus, Phone, PostalInfo}; +use crate::epp::object::{ElementName, EppObject, StringValue, StringValueTrait}; +use crate::epp::response::contact::info::EppContactInfoResponse; +use crate::epp::xml::EPP_CONTACT_XMLNS; +use crate::error; +use serde::{Deserialize, Serialize}; + +pub type EppContactUpdate = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ContactChangeInfo { + #[serde(rename = "postalInfo")] + postal_info: PostalInfo, + voice: Phone, + fax: Option, + email: StringValue, + #[serde(rename = "authInfo")] + auth_info: AuthInfo, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct StatusList { + status: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ContactUpdateData { + xmlns: String, + id: StringValue, + #[serde(rename = "add")] + add_statuses: Option, + #[serde(rename = "rem")] + remove_statuses: Option, + #[serde(rename = "chg")] + change_info: Option, +} + +#[derive(Serialize, Deserialize, Debug, ElementName)] +#[element_name(name = "update")] +pub struct ContactUpdate { + #[serde(rename = "update")] + contact: ContactUpdateData, +} + +impl EppContactUpdate { + pub fn new(id: &str, client_tr_id: &str) -> EppContactUpdate { + EppObject::build(Command:: { + command: ContactUpdate { + contact: ContactUpdateData { + xmlns: EPP_CONTACT_XMLNS.to_string(), + id: id.to_string_value(), + add_statuses: None, + remove_statuses: None, + change_info: None, + }, + }, + client_tr_id: client_tr_id.to_string_value(), + }) + } + + pub fn set_info( + &mut self, + email: &str, + postal_info: PostalInfo, + voice: Phone, + auth_password: &str, + ) { + self.data.command.contact.change_info = Some(ContactChangeInfo { + email: email.to_string_value(), + postal_info: postal_info, + voice: voice, + auth_info: AuthInfo::new(auth_password), + fax: None, + }); + } + + pub fn set_fax(&mut self, fax: Phone) { + match &mut self.data.command.contact.change_info { + Some(ref mut info) => info.fax = Some(fax), + _ => (), + } + } + + pub fn add_statuses(&mut self, statuses: Vec) { + self.data.command.contact.add_statuses = Some(StatusList { status: statuses }); + } + + pub fn remove_statuses(&mut self, statuses: Vec) { + self.data.command.contact.remove_statuses = Some(StatusList { status: statuses }); + } + + pub fn load_from_epp_contact_info( + &mut self, + contact_info: EppContactInfoResponse, + ) -> Result<(), error::Error> { + match contact_info.data.res_data { + Some(res_data) => { + self.data.command.contact.change_info = Some(ContactChangeInfo { + email: res_data.info_data.email.clone(), + postal_info: res_data.info_data.postal_info.clone(), + voice: res_data.info_data.voice.clone(), + fax: res_data.info_data.fax.clone(), + auth_info: res_data.info_data.auth_info.clone(), + }); + Ok(()) + } + None => Err(error::Error::Other( + "No res_data in EppContactInfoResponse object".to_string(), + )), + } + } +} diff --git a/epp-client/src/epp/response/contact.rs b/epp-client/src/epp/response/contact.rs index 3aa3078..035f812 100644 --- a/epp-client/src/epp/response/contact.rs +++ b/epp-client/src/epp/response/contact.rs @@ -1,2 +1,5 @@ pub mod check; pub mod create; +pub mod delete; +pub mod info; +pub mod update; diff --git a/epp-client/src/epp/response/contact/check.rs b/epp-client/src/epp/response/contact/check.rs index 789d7e0..82d6d5d 100644 --- a/epp-client/src/epp/response/contact/check.rs +++ b/epp-client/src/epp/response/contact/check.rs @@ -21,6 +21,8 @@ pub struct ContactCheckDataItem { #[derive(Serialize, Deserialize, Debug)] pub struct ContactCheckData { + #[serde(rename = "xmlns:contact")] + xmlns: String, #[serde(rename = "cd")] pub contact_list: Vec, } diff --git a/epp-client/src/epp/response/contact/create.rs b/epp-client/src/epp/response/contact/create.rs index 8cbea77..62f2d27 100644 --- a/epp-client/src/epp/response/contact/create.rs +++ b/epp-client/src/epp/response/contact/create.rs @@ -7,6 +7,8 @@ pub type EppContactCreateResponse = EppObject>; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ContactInfoData { + #[serde(rename = "xmlns:contact")] + xmlns: String, + pub id: StringValue, + pub roid: StringValue, + pub status: Vec, + #[serde(rename = "postalInfo")] + pub postal_info: PostalInfo, + pub voice: Phone, + pub fax: Option, + pub email: StringValue, + #[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: Option, + #[serde(rename = "upDate")] + pub updated_at: Option, + #[serde(rename = "trDate")] + pub transferred_at: Option, + #[serde(rename = "authInfo")] + pub auth_info: AuthInfo, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ContactInfoResult { + #[serde(rename = "infData")] + pub info_data: ContactInfoData, +} diff --git a/epp-client/src/epp/response/contact/update.rs b/epp-client/src/epp/response/contact/update.rs new file mode 100644 index 0000000..91c99d9 --- /dev/null +++ b/epp-client/src/epp/response/contact/update.rs @@ -0,0 +1,3 @@ +use crate::epp::response::EppCommandResponse; + +pub type EppContactUpdateResponse = EppCommandResponse;