1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Types for EPP contact create request

use chrono::{DateTime, Utc};
use instant_xml::{FromXml, ToXml};

use super::{ContactAuthInfo, Fax, PostalInfo, Voice, XMLNS};
use crate::common::{NoExtension, EPP_XMLNS};
use crate::request::{Command, Transaction};

impl<'a> Transaction<NoExtension> for ContactCreate<'a> {}

impl<'a> Command for ContactCreate<'a> {
    type Response = CreateData;
    const COMMAND: &'static str = "create";
}

// Request

/// Type for elements under the contact `<create>` tag
#[derive(Debug, ToXml)]
#[xml(rename = "create", ns(XMLNS))]
pub struct ContactCreateRequest<'a> {
    /// Contact `<id>` tag
    id: &'a str,
    /// Contact `<postalInfo>` tag
    postal_info: PostalInfo<'a>,
    /// Contact `<voice>` tag
    voice: Option<Voice<'a>>,
    /// Contact `<fax>` tag,]
    fax: Option<Fax<'a>>,
    /// Contact `<email>` tag
    email: &'a str,
    /// Contact `<authInfo>` tag
    auth_info: ContactAuthInfo<'a>,
}

/// Type for EPP XML `<create>` command for contacts
#[derive(Debug, ToXml)]
#[xml(rename = "create", ns(EPP_XMLNS))]
pub struct ContactCreate<'a> {
    /// Data for `<create>` command for contact
    pub contact: ContactCreateRequest<'a>,
}

impl<'a> ContactCreate<'a> {
    pub fn new(
        id: &'a str,
        email: &'a str,
        postal_info: PostalInfo<'a>,
        voice: Option<Voice<'a>>,
        auth_password: &'a str,
    ) -> Self {
        Self {
            contact: ContactCreateRequest {
                id,
                postal_info,
                voice,
                fax: None,
                email,
                auth_info: ContactAuthInfo::new(auth_password),
            },
        }
    }

    /// Sets the `<fax>` data for the request
    pub fn set_fax(&mut self, fax: Fax<'a>) {
        self.contact.fax = Some(fax);
    }
}

// Response

/// Type that represents the `<creData>` tag for contact create response
#[derive(Debug, FromXml)]
#[xml(rename = "creData", ns(XMLNS))]
pub struct CreateData {
    /// The contact id
    pub id: String,
    #[xml(rename = "crDate")]
    /// The contact creation date
    pub created_at: DateTime<Utc>,
}

#[cfg(test)]
mod tests {
    use chrono::{TimeZone, Utc};

    use super::{ContactCreate, Fax, PostalInfo, Voice};
    use crate::contact::Address;
    use crate::response::ResultCode;
    use crate::tests::{assert_serialized, response_from_file, CLTRID, SUCCESS_MSG, SVTRID};

    #[test]
    fn command() {
        let street = &["58", "Orchid Road"];
        let address = Address::new(
            street,
            "Paris",
            Some("Paris"),
            Some("392374"),
            "FR".parse().unwrap(),
        );
        let postal_info = PostalInfo::new("int", "John Doe", Some("Acme Widgets"), address);
        let mut voice = Voice::new("+33.47237942");
        voice.set_extension("123");
        let mut fax = Fax::new("+33.86698799");
        fax.set_extension("677");

        let mut object = ContactCreate::new(
            "eppdev-contact-3",
            "contact@eppdev.net",
            postal_info,
            Some(voice),
            "eppdev-387323",
        );
        object.set_fax(fax);

        assert_serialized("request/contact/create.xml", &object);
    }

    #[test]
    fn command_minimal() {
        let address = Address::new(&[], "Paris", None, None, "FR".parse().unwrap());
        let postal_info = PostalInfo::new("int", "John Doe", None, address);
        let object = ContactCreate::new(
            "eppdev-contact-3",
            "contact@eppdev.net",
            postal_info,
            None,
            "eppdev-387323",
        );

        assert_serialized("request/contact/create_minimal.xml", &object);
    }

    #[test]
    fn response() {
        let object = response_from_file::<ContactCreate>("response/contact/create.xml");
        let results = object.res_data().unwrap();

        assert_eq!(object.result.code, ResultCode::CommandCompletedSuccessfully);
        assert_eq!(object.result.message, SUCCESS_MSG);
        assert_eq!(results.id, "eppdev-contact-4");
        assert_eq!(
            results.created_at,
            Utc.with_ymd_and_hms(2021, 7, 25, 16, 5, 32).unwrap(),
        );
        assert_eq!(object.tr_ids.client_tr_id.unwrap(), CLTRID);
        assert_eq!(object.tr_ids.server_tr_id, SVTRID);
    }
}