Frnic contact create (#16)
This commit is contained in:
parent
1b6a774232
commit
7024bcd7a5
|
@ -0,0 +1,183 @@
|
|||
//! Types for EPP FRNIC contact requests
|
||||
use instant_xml::{Id, ToXml};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::request::{Extension, Transaction};
|
||||
|
||||
use super::{Create, Ext, XMLNS};
|
||||
|
||||
impl<'a> Transaction<Ext<Create<ContactCreate<'a>>>> for crate::contact::create::ContactCreate<'a> {}
|
||||
|
||||
impl<'a> Extension for Ext<Create<ContactCreate<'a>>> {
|
||||
type Response = ();
|
||||
}
|
||||
|
||||
/// For french TLDs, a contact is either an individual (PP) or a legal
|
||||
/// entity (PM). We use the `ContactCreate` extension to differentiate
|
||||
/// between the creation of a PP and a PM.
|
||||
#[derive(Debug)]
|
||||
pub enum ContactCreate<'a> {
|
||||
/// This contact is an individual.
|
||||
NaturalPerson {
|
||||
/// First name of the contact. The `<contact:name>` element
|
||||
/// will be the family name.
|
||||
first_name: Cow<'a, str>,
|
||||
},
|
||||
/// This contact is a legal entity.
|
||||
LegalEntity(Box<LegalEntityInfos<'a>>),
|
||||
}
|
||||
|
||||
impl<'a> From<ContactCreate<'a>> for Ext<Create<ContactCreate<'a>>> {
|
||||
fn from(data: ContactCreate<'a>) -> Self {
|
||||
Ext {
|
||||
data: Create { data },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ContactCreate<'a> {
|
||||
pub fn new_natural_person(first_name: &'a str) -> Self {
|
||||
Self::NaturalPerson {
|
||||
first_name: first_name.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_company(
|
||||
siren: Option<&'a str>,
|
||||
vat: Option<&'a str>,
|
||||
trademark: Option<&'a str>,
|
||||
duns: Option<&'a str>,
|
||||
local: Option<&'a str>,
|
||||
) -> Self {
|
||||
Self::LegalEntity(Box::new(LegalEntityInfos {
|
||||
legal_status: LegalStatus::Company,
|
||||
siren: siren.map(|s| s.into()),
|
||||
vat: vat.map(|v| v.into()),
|
||||
trademark: trademark.map(|t| t.into()),
|
||||
asso: None,
|
||||
duns: duns.map(|d| d.into()),
|
||||
local: local.map(|l| l.into()),
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn new_non_profit(
|
||||
waldec: Option<&'a str>,
|
||||
declaration: Option<&'a str>,
|
||||
publication: Option<Publication<'a>>,
|
||||
) -> Self {
|
||||
Self::LegalEntity(Box::new(LegalEntityInfos {
|
||||
legal_status: LegalStatus::Association,
|
||||
siren: None,
|
||||
vat: None,
|
||||
trademark: None,
|
||||
asso: Some(Association {
|
||||
waldec: waldec.map(|w| w.into()),
|
||||
declaration: declaration.map(|d| d.into()),
|
||||
publication,
|
||||
}),
|
||||
duns: None,
|
||||
local: None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToXml for ContactCreate<'a> {
|
||||
fn serialize<W: core::fmt::Write + ?Sized>(
|
||||
&self,
|
||||
_: Option<Id<'_>>,
|
||||
serializer: &mut instant_xml::Serializer<'_, W>,
|
||||
) -> Result<(), instant_xml::Error> {
|
||||
let contact_nc_name = "contact";
|
||||
let prefix = serializer.write_start(contact_nc_name, XMLNS)?;
|
||||
serializer.end_start()?;
|
||||
match self {
|
||||
Self::NaturalPerson { first_name } => {
|
||||
let first_name_nc_name = "firstName";
|
||||
let prefix = serializer.write_start(first_name_nc_name, XMLNS)?;
|
||||
serializer.end_start()?;
|
||||
first_name.serialize(None, serializer)?;
|
||||
serializer.write_close(prefix, first_name_nc_name)?;
|
||||
}
|
||||
Self::LegalEntity(infos) => infos.serialize(None, serializer)?,
|
||||
}
|
||||
serializer.write_close(prefix, contact_nc_name)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, ToXml)]
|
||||
#[xml(rename = "legalEntityInfos", ns(XMLNS))]
|
||||
pub struct LegalEntityInfos<'a> {
|
||||
pub legal_status: LegalStatus<'a>,
|
||||
pub siren: Option<Cow<'a, str>>,
|
||||
pub vat: Option<Cow<'a, str>>,
|
||||
pub trademark: Option<Cow<'a, str>>,
|
||||
pub asso: Option<Association<'a>>,
|
||||
pub duns: Option<Cow<'a, str>>,
|
||||
pub local: Option<Cow<'a, str>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LegalStatus<'a> {
|
||||
Company,
|
||||
Association,
|
||||
Other(Cow<'a, str>),
|
||||
}
|
||||
|
||||
impl<'a> ToXml for LegalStatus<'a> {
|
||||
fn serialize<W: core::fmt::Write + ?Sized>(
|
||||
&self,
|
||||
_field: Option<Id<'_>>,
|
||||
serializer: &mut instant_xml::Serializer<W>,
|
||||
) -> Result<(), instant_xml::Error> {
|
||||
let ncname = "legalStatus";
|
||||
let (s, data) = match self {
|
||||
LegalStatus::Company => ("company", None),
|
||||
LegalStatus::Association => ("association", None),
|
||||
LegalStatus::Other(text) => ("other", Some(&text.as_ref()[2..])),
|
||||
};
|
||||
let prefix = serializer.write_start(ncname, XMLNS)?;
|
||||
debug_assert_eq!(prefix, None);
|
||||
serializer.write_attr("s", XMLNS, s)?;
|
||||
if let Some(text) = data {
|
||||
serializer.end_start()?;
|
||||
text.serialize(None, serializer)?;
|
||||
serializer.write_close(prefix, ncname)?;
|
||||
} else {
|
||||
serializer.end_empty()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains information that permits the identification of associations.
|
||||
#[derive(Debug, ToXml)]
|
||||
#[xml(rename = "asso", ns(XMLNS))]
|
||||
pub struct Association<'a> {
|
||||
/// The Waldec registration number. "Waldec" is the acronym for
|
||||
/// the french "[Web des associations librement
|
||||
/// déclarées](https://www.associations.gouv.fr/le-rna-repertoire-national-des-associations.html)"
|
||||
pub waldec: Option<Cow<'a, str>>,
|
||||
/// Date of declaration to the prefecture
|
||||
#[xml(rename = "decl")]
|
||||
pub declaration: Option<Cow<'a, str>>,
|
||||
/// Information of publication in the official gazette
|
||||
#[xml(rename = "publ")]
|
||||
pub publication: Option<Publication<'a>>,
|
||||
}
|
||||
|
||||
/// Holds information about the publication in the
|
||||
/// official gazette for the association.
|
||||
#[derive(Debug, ToXml)]
|
||||
#[xml(rename = "publ", ns(XMLNS))]
|
||||
pub struct Publication<'a> {
|
||||
/// Page number of the announcement
|
||||
#[xml(attribute)]
|
||||
pub page: u32,
|
||||
#[xml(attribute)]
|
||||
/// Number of the announcement
|
||||
pub announce: u32,
|
||||
/// Date of publication
|
||||
#[xml(direct)]
|
||||
pub date: Cow<'a, str>,
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
//! Mapping for the [frnic-2.0
|
||||
//! extension](https://www.afnic.fr/wp-media/uploads/2022/10/guide_d_integration_technique_EN_FRandoverseasTLD_30_09_VF.pdf)
|
||||
use instant_xml::{FromXml, ToXml};
|
||||
|
||||
pub mod contact;
|
||||
|
||||
pub use contact::ContactCreate;
|
||||
|
||||
pub const XMLNS: &str = "http://www.afnic.fr/xml/epp/frnic-2.0";
|
||||
|
||||
#[derive(Debug, FromXml, ToXml)]
|
||||
#[xml(rename = "ext", ns(XMLNS))]
|
||||
pub struct Ext<T> {
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, FromXml, ToXml)]
|
||||
#[xml(rename = "create", ns(XMLNS))]
|
||||
pub struct Create<T> {
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::contact::ContactCreate;
|
||||
use crate::contact::{Address, PostalInfo, Voice};
|
||||
use crate::extensions::frnic;
|
||||
use crate::tests::assert_serialized;
|
||||
use frnic::{contact, Ext};
|
||||
|
||||
#[test]
|
||||
fn test_contact_create_natural_person() {
|
||||
// Technical Integration Guide, page 23.
|
||||
let frnic_contact = Ext::from(frnic::ContactCreate::new_natural_person("Michel"));
|
||||
let object = ContactCreate::new(
|
||||
"XXX000",
|
||||
"test@test.fr",
|
||||
PostalInfo::new(
|
||||
"loc",
|
||||
"Dupont",
|
||||
None,
|
||||
Address::new(
|
||||
&["1 Rue des fleurs"],
|
||||
"Paris",
|
||||
None,
|
||||
Some("75000"),
|
||||
"FR".parse().unwrap(),
|
||||
),
|
||||
),
|
||||
Some(Voice::new("+33.1234567890")),
|
||||
"Afn-12345678",
|
||||
);
|
||||
assert_serialized(
|
||||
"request/extensions/frnic_create_contact_natural_person.xml",
|
||||
(&object, &frnic_contact),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contact_create_company() {
|
||||
// Technical Integration Guide, page 27.
|
||||
let frnic_contact = Ext::from(frnic::ContactCreate::new_company(
|
||||
None, None, None, None, None,
|
||||
));
|
||||
let object = ContactCreate::new(
|
||||
"XXXXXXX",
|
||||
"test@test.fr",
|
||||
PostalInfo::new(
|
||||
"loc",
|
||||
"SARL DUPONT",
|
||||
None,
|
||||
Address::new(
|
||||
&["1 Rue des coquelicots"],
|
||||
"Paris",
|
||||
None,
|
||||
Some("75000"),
|
||||
"FR".parse().unwrap(),
|
||||
),
|
||||
),
|
||||
Some(Voice::new("+33.1234567890")),
|
||||
"Afn-123456",
|
||||
);
|
||||
assert_serialized(
|
||||
"request/extensions/frnic_create_contact_company.xml",
|
||||
(&object, &frnic_contact),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contact_create_corporation_with_siren() {
|
||||
// Technical Integration Guide, page 28.
|
||||
let frnic_contact = Ext::from(frnic::ContactCreate::new_company(
|
||||
Some("123456789"),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
));
|
||||
let object = ContactCreate::new(
|
||||
"XXXX0000",
|
||||
"test@test.fr",
|
||||
PostalInfo::new(
|
||||
"loc",
|
||||
"SARL DUPONT SIREN",
|
||||
None,
|
||||
Address::new(
|
||||
&["1 Rue des Sirenes"],
|
||||
"Paris",
|
||||
None,
|
||||
Some("75000"),
|
||||
"FR".parse().unwrap(),
|
||||
),
|
||||
),
|
||||
Some(Voice::new("+33.1234567890")),
|
||||
"Afn-123456",
|
||||
);
|
||||
assert_serialized(
|
||||
"request/extensions/frnic_create_contact_siren.xml",
|
||||
(&object, &frnic_contact),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contact_create_non_profit() {
|
||||
// Technical Integration Guide, page 38.
|
||||
let frnic_contact = Ext::from(frnic::ContactCreate::new_non_profit(
|
||||
None,
|
||||
Some("2011-05-02"),
|
||||
Some(contact::Publication {
|
||||
announce: 123456,
|
||||
page: 15,
|
||||
date: "2011-05-07".into(),
|
||||
}),
|
||||
));
|
||||
let object = ContactCreate::new(
|
||||
"XXXX0000",
|
||||
"test@test.fr",
|
||||
PostalInfo::new(
|
||||
"loc",
|
||||
"Dupont JO",
|
||||
None,
|
||||
Address::new(
|
||||
&["1 Rue des Fleurs"],
|
||||
"Paris",
|
||||
None,
|
||||
Some("75000"),
|
||||
"FR".parse().unwrap(),
|
||||
),
|
||||
),
|
||||
Some(Voice::new("+33.1234567890")),
|
||||
"Afn-123456",
|
||||
);
|
||||
assert_serialized(
|
||||
"request/extensions/frnic_create_contact_non_profit.xml",
|
||||
(&object, &frnic_contact),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -61,6 +61,8 @@ pub mod extensions {
|
|||
|
||||
pub const XMLNS: &str = "urn:ietf:params:xml:ns:rgp-1.0";
|
||||
}
|
||||
|
||||
pub mod frnic;
|
||||
}
|
||||
|
||||
pub use client::EppClient;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||
<command>
|
||||
<create>
|
||||
<create xmlns="urn:ietf:params:xml:ns:contact-1.0">
|
||||
<id>XXXXXXX</id>
|
||||
<postalInfo type="loc">
|
||||
<name>SARL DUPONT</name>
|
||||
<addr>
|
||||
<street>1 Rue des coquelicots</street>
|
||||
<city>Paris</city>
|
||||
<pc>75000</pc>
|
||||
<cc>FR</cc>
|
||||
</addr>
|
||||
</postalInfo>
|
||||
<voice>+33.1234567890</voice>
|
||||
<email>test@test.fr</email>
|
||||
<authInfo>
|
||||
<pw>Afn-123456</pw>
|
||||
</authInfo>
|
||||
</create>
|
||||
</create>
|
||||
<extension>
|
||||
<ext xmlns="http://www.afnic.fr/xml/epp/frnic-2.0">
|
||||
<create>
|
||||
<contact>
|
||||
<legalEntityInfos>
|
||||
<legalStatus s="company" />
|
||||
</legalEntityInfos>
|
||||
</contact>
|
||||
</create>
|
||||
</ext>
|
||||
</extension>
|
||||
<clTRID>cltrid:1626454866</clTRID>
|
||||
</command>
|
||||
</epp>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||
<command>
|
||||
<create>
|
||||
<create xmlns="urn:ietf:params:xml:ns:contact-1.0">
|
||||
<id>XXX000</id>
|
||||
<postalInfo type="loc">
|
||||
<name>Dupont</name>
|
||||
<addr>
|
||||
<street>1 Rue des fleurs</street>
|
||||
<city>Paris</city>
|
||||
<pc>75000</pc>
|
||||
<cc>FR</cc>
|
||||
</addr>
|
||||
</postalInfo>
|
||||
<voice>+33.1234567890</voice>
|
||||
<email>test@test.fr</email>
|
||||
<authInfo>
|
||||
<pw>Afn-12345678</pw>
|
||||
</authInfo>
|
||||
</create>
|
||||
</create>
|
||||
<extension>
|
||||
<ext xmlns="http://www.afnic.fr/xml/epp/frnic-2.0">
|
||||
<create>
|
||||
<contact>
|
||||
<firstName>Michel</firstName>
|
||||
</contact>
|
||||
</create>
|
||||
</ext>
|
||||
</extension>
|
||||
<clTRID>cltrid:1626454866</clTRID>
|
||||
</command>
|
||||
</epp>
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||
<command>
|
||||
<create>
|
||||
<create xmlns="urn:ietf:params:xml:ns:contact-1.0">
|
||||
<id>XXXX0000</id>
|
||||
<postalInfo type="loc">
|
||||
<name>Dupont JO</name>
|
||||
<addr>
|
||||
<street>1 Rue des Fleurs</street>
|
||||
<city>Paris</city>
|
||||
<pc>75000</pc>
|
||||
<cc>FR</cc>
|
||||
</addr>
|
||||
</postalInfo>
|
||||
<voice>+33.1234567890</voice>
|
||||
<email>test@test.fr</email>
|
||||
<authInfo>
|
||||
<pw>Afn-123456</pw>
|
||||
</authInfo>
|
||||
</create>
|
||||
</create>
|
||||
<extension>
|
||||
<ext xmlns="http://www.afnic.fr/xml/epp/frnic-2.0">
|
||||
<create>
|
||||
<contact>
|
||||
<legalEntityInfos>
|
||||
<legalStatus s="association" />
|
||||
<asso>
|
||||
<decl>2011-05-02</decl>
|
||||
<publ page="15" announce="123456">2011-05-07</publ>
|
||||
</asso>
|
||||
</legalEntityInfos>
|
||||
</contact>
|
||||
</create>
|
||||
</ext>
|
||||
</extension>
|
||||
<clTRID>cltrid:1626454866</clTRID>
|
||||
</command>
|
||||
</epp>
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||
<command>
|
||||
<create>
|
||||
<create xmlns="urn:ietf:params:xml:ns:contact-1.0">
|
||||
<id>XXXX0000</id>
|
||||
<postalInfo type="loc">
|
||||
<name>SARL DUPONT SIREN</name>
|
||||
<addr>
|
||||
<street>1 Rue des Sirenes</street>
|
||||
<city>Paris</city>
|
||||
<pc>75000</pc>
|
||||
<cc>FR</cc>
|
||||
</addr>
|
||||
</postalInfo>
|
||||
<voice>+33.1234567890</voice>
|
||||
<email>test@test.fr</email>
|
||||
<authInfo>
|
||||
<pw>Afn-123456</pw>
|
||||
</authInfo>
|
||||
</create>
|
||||
</create>
|
||||
<extension>
|
||||
<ext xmlns="http://www.afnic.fr/xml/epp/frnic-2.0">
|
||||
<create>
|
||||
<contact>
|
||||
<legalEntityInfos>
|
||||
<legalStatus s="company" />
|
||||
<siren>123456789</siren>
|
||||
</legalEntityInfos>
|
||||
</contact>
|
||||
</create>
|
||||
</ext>
|
||||
</extension>
|
||||
<clTRID>cltrid:1626454866</clTRID>
|
||||
</command>
|
||||
</epp>
|
Loading…
Reference in New Issue