2021-07-26 15:51:37 +00:00
|
|
|
//! Types for EPP requests
|
|
|
|
|
2021-11-26 21:50:22 +00:00
|
|
|
use serde::{de::DeserializeOwned, ser::SerializeStruct, ser::Serializer, Deserialize, Serialize};
|
|
|
|
use std::fmt::Debug;
|
2021-07-16 19:16:28 +00:00
|
|
|
|
2021-11-26 21:50:22 +00:00
|
|
|
use crate::{
|
2021-11-26 21:51:11 +00:00
|
|
|
common::{ElementName, EppObject, Extension, StringValue},
|
2021-12-02 12:52:42 +00:00
|
|
|
response::{Response, ResponseStatus},
|
2021-11-26 21:50:22 +00:00
|
|
|
xml::EppXml,
|
|
|
|
};
|
2021-11-29 22:25:35 +00:00
|
|
|
use epp_client_macros::ElementName;
|
2021-07-16 19:16:28 +00:00
|
|
|
|
2021-11-26 19:36:28 +00:00
|
|
|
pub const EPP_VERSION: &str = "1.0";
|
|
|
|
pub const EPP_LANG: &str = "en";
|
|
|
|
|
2021-11-26 21:50:22 +00:00
|
|
|
/// Trait to set correct value for xml tags when tags are being generated from generic types
|
|
|
|
pub trait EppRequest<E: EppExtension>: Sized + Debug {
|
|
|
|
type Input: ElementName + DeserializeOwned + Serialize + Sized + Debug;
|
|
|
|
type Output: DeserializeOwned + Serialize + Debug;
|
|
|
|
|
|
|
|
fn into_parts(self) -> (Self::Input, Option<E>);
|
|
|
|
|
|
|
|
fn serialize_request(self, client_tr_id: &str) -> Result<String, Box<dyn std::error::Error>> {
|
|
|
|
let (command, extension) = self.into_parts();
|
|
|
|
let extension = extension.map(|data| Extension { data });
|
2021-12-02 13:18:21 +00:00
|
|
|
EppXml::serialize(&EppObject::build(Command {
|
2021-11-26 21:50:22 +00:00
|
|
|
command,
|
|
|
|
extension,
|
|
|
|
client_tr_id: client_tr_id.into(),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn deserialize_response(
|
|
|
|
epp_xml: &str,
|
2021-12-02 12:52:42 +00:00
|
|
|
) -> Result<Response<Self::Output, E::Response>, crate::error::Error> {
|
|
|
|
let rsp = <EppObject<Response<Self::Output, E::Response>> as EppXml>::deserialize(epp_xml)?;
|
2021-11-26 21:50:22 +00:00
|
|
|
match rsp.data.result.code {
|
|
|
|
0..=2000 => Ok(rsp.data),
|
2021-12-02 13:13:42 +00:00
|
|
|
_ => Err(crate::error::Error::EppCommandError(ResponseStatus {
|
|
|
|
result: rsp.data.result,
|
|
|
|
tr_ids: rsp.data.tr_ids,
|
|
|
|
})),
|
2021-11-26 21:50:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait EppExtension: ElementName + DeserializeOwned + Serialize + Sized + Debug {
|
|
|
|
type Response: ElementName + DeserializeOwned + Serialize + Debug;
|
|
|
|
}
|
|
|
|
|
2021-07-25 14:34:01 +00:00
|
|
|
#[derive(Deserialize, Debug, PartialEq, ElementName)]
|
|
|
|
#[element_name(name = "command")]
|
2021-07-26 19:27:18 +00:00
|
|
|
/// Type corresponding to the <command> tag in an EPP XML request
|
2021-07-29 15:42:36 +00:00
|
|
|
/// with an <extension> tag
|
2021-12-02 13:18:21 +00:00
|
|
|
pub struct Command<T: ElementName, E: ElementName> {
|
2021-07-26 19:27:18 +00:00
|
|
|
/// The instance that will be used to populate the <command> tag
|
2021-07-25 14:34:01 +00:00
|
|
|
pub command: T,
|
2021-07-26 15:51:37 +00:00
|
|
|
/// The client TRID
|
2021-07-29 15:42:36 +00:00
|
|
|
pub extension: Option<Extension<E>>,
|
2021-07-25 14:34:01 +00:00
|
|
|
#[serde(rename = "clTRID")]
|
|
|
|
pub client_tr_id: StringValue,
|
|
|
|
}
|
|
|
|
|
2021-12-02 13:18:21 +00:00
|
|
|
impl<T: ElementName + Serialize, E: ElementName + Serialize> Serialize for Command<T, E> {
|
2021-07-26 15:51:37 +00:00
|
|
|
/// Serializes the generic type T to the proper XML tag (set by the `#[element_name(name = <tagname>)]` attribute) for the request
|
2021-07-25 14:34:01 +00:00
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: Serializer,
|
|
|
|
{
|
2021-07-29 15:42:36 +00:00
|
|
|
let mut state = serializer.serialize_struct("command", 3)?;
|
2021-11-18 12:26:53 +00:00
|
|
|
state.serialize_field(T::ELEMENT, &self.command)?;
|
2021-07-29 15:42:36 +00:00
|
|
|
state.serialize_field("extension", &self.extension)?;
|
2021-07-25 14:34:01 +00:00
|
|
|
state.serialize_field("clTRID", &self.client_tr_id)?;
|
|
|
|
state.end()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-02 13:18:21 +00:00
|
|
|
impl<T: ElementName, E: ElementName> Command<T, E> {
|
2021-07-29 15:42:36 +00:00
|
|
|
/// Creates a new <command> tag for an EPP document with a containing <extension> tag
|
2021-12-02 13:18:21 +00:00
|
|
|
pub fn build(command: T, ext: E, client_tr_id: &str) -> Command<T, E> {
|
|
|
|
Command {
|
2021-10-27 22:45:32 +00:00
|
|
|
command,
|
2021-07-29 15:42:36 +00:00
|
|
|
extension: Some(Extension { data: ext }),
|
2021-11-18 12:51:43 +00:00
|
|
|
client_tr_id: client_tr_id.into(),
|
2021-07-29 15:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|