//! Types for EPP contact create request use super::{ContactAuthInfo, Phone, PostalInfo, XMLNS}; use crate::common::{NoExtension, ObjectStatus, StringValue}; use crate::request::{Command, Transaction}; use serde::Serialize; impl<'a> Transaction for ContactUpdate<'a> {} impl<'a> Command for ContactUpdate<'a> { type Response = (); const COMMAND: &'static str = "update"; } impl<'a> ContactUpdate<'a> { pub fn new(id: &'a str) -> ContactUpdate { Self { contact: ContactUpdateRequestData { xmlns: XMLNS, id: id.into(), add_statuses: None, remove_statuses: None, change_info: None, }, } } /// Sets the data for the <chg> tag for the contact update request pub fn set_info( &mut self, email: &'a str, postal_info: PostalInfo<'a>, voice: Phone<'a>, auth_password: &'a str, ) { self.contact.change_info = Some(ContactChangeInfo { email: Some(email.into()), postal_info: Some(postal_info), voice: Some(voice), auth_info: Some(ContactAuthInfo::new(auth_password)), fax: None, }); } /// Sets the data for the <fax> tag under <chg> for the contact update request pub fn set_fax(&mut self, fax: Phone<'a>) { if let Some(info) = &mut self.contact.change_info { info.fax = Some(fax) } } /// Sets the data for the <add> tag for the contact update request pub fn add(&mut self, status: &'a [ObjectStatus]) { self.contact.add_statuses = Some(StatusList { status }); } /// Sets the data for the <rem> tag for the contact update request pub fn remove(&mut self, status: &'a [ObjectStatus]) { self.contact.remove_statuses = Some(StatusList { status }); } } /// Type for elements under the <chg> tag for contact update request #[derive(Serialize, Debug)] pub struct ContactChangeInfo<'a> { #[serde(rename = "contact:postalInfo")] postal_info: Option>, #[serde(rename = "contact:voice")] voice: Option>, #[serde(rename = "contact:fax")] fax: Option>, #[serde(rename = "contact:email")] email: Option>, #[serde(rename = "contact:authInfo")] auth_info: Option>, } /// Type for list of elements of the <status> tag for contact update request #[derive(Serialize, Debug)] pub struct StatusList<'a> { #[serde(rename = "contact:status")] status: &'a [ObjectStatus<'a>], } /// Type for elements under the contact <update> tag #[derive(Serialize, Debug)] pub struct ContactUpdateRequestData<'a> { #[serde(rename = "xmlns:contact")] xmlns: &'a str, #[serde(rename = "contact:id")] id: StringValue<'a>, #[serde(rename = "contact:add")] add_statuses: Option>, #[serde(rename = "contact:rem")] remove_statuses: Option>, #[serde(rename = "contact:chg")] change_info: Option>, } #[derive(Serialize, Debug)] /// Type for EPP XML <update> command for contacts pub struct ContactUpdate<'a> { /// The data under the <update> tag for the contact update #[serde(rename = "contact:update")] contact: ContactUpdateRequestData<'a>, } #[cfg(test)] mod tests { use super::{ContactUpdate, Phone, PostalInfo}; use crate::common::ObjectStatus; use crate::contact::Address; use crate::response::ResultCode; use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID}; #[test] fn command() { let mut object = ContactUpdate::new("eppdev-contact-3"); let street = &["58", "Orchid Road"]; let address = Address::new(street, "Paris", "Paris", "392374", "FR".parse().unwrap()); let postal_info = PostalInfo::new("loc", "John Doe", "Acme Widgets", address); let voice = Phone::new("+33.47237942"); object.set_info("newemail@eppdev.net", postal_info, voice, "eppdev-387323"); let add_statuses = &[ObjectStatus { status: "clientTransferProhibited".into(), }]; object.add(add_statuses); let remove_statuses = &[ObjectStatus { status: "clientDeleteProhibited".into(), }]; object.remove(remove_statuses); assert_serialized("request/contact/update.xml", &object); } #[test] fn contact_update() { let object = response_from_file::("response/contact/update.xml"); assert_eq!(object.result.code, ResultCode::CommandCompletedSuccessfully); assert_eq!(object.result.message, SUCCESS_MSG.into()); assert_eq!(object.tr_ids.client_tr_id.unwrap(), CLTRID.into()); assert_eq!(object.tr_ids.server_tr_id, SVTRID.into()); } }