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
//! Types for EPP namestore request and responses
//!
//! As described in [Namestore Extension Mapping](https://www.verisign.com/assets/epp-sdk/verisign_epp-extension_namestoreext_v01.html).

use std::borrow::Cow;

use instant_xml::{FromXml, ToXml};

use crate::{
    contact::{
        check::ContactCheck, create::ContactCreate, delete::ContactDelete, info::ContactInfo,
        update::ContactUpdate,
    },
    domain::{
        check::DomainCheck, create::DomainCreate, delete::DomainDelete, info::DomainInfo,
        renew::DomainRenew, transfer::DomainTransfer, update::DomainUpdate,
    },
    host::{
        check::HostCheck, create::HostCreate, delete::HostDelete, info::HostInfo,
        update::HostUpdate,
    },
    request::{Extension, Transaction},
};

pub const XMLNS: &str = "http://www.verisign-grs.com/epp/namestoreExt-1.1";

// Contact

impl Transaction<NameStore<'_>> for ContactCheck<'_> {}
impl Transaction<NameStore<'_>> for ContactCreate<'_> {}
impl Transaction<NameStore<'_>> for ContactDelete<'_> {}
impl Transaction<NameStore<'_>> for ContactInfo<'_> {}
impl Transaction<NameStore<'_>> for ContactUpdate<'_> {}

// Domain

impl Transaction<NameStore<'_>> for DomainCheck<'_> {}
impl Transaction<NameStore<'_>> for DomainCreate<'_> {}
impl Transaction<NameStore<'_>> for DomainDelete<'_> {}
impl Transaction<NameStore<'_>> for DomainInfo<'_> {}
impl Transaction<NameStore<'_>> for DomainRenew<'_> {}
impl Transaction<NameStore<'_>> for DomainTransfer<'_> {}
impl Transaction<NameStore<'_>> for DomainUpdate<'_> {}

// Host

impl Transaction<NameStore<'_>> for HostCheck<'_> {}
impl Transaction<NameStore<'_>> for HostCreate<'_> {}
impl Transaction<NameStore<'_>> for HostDelete<'_> {}
impl Transaction<NameStore<'_>> for HostInfo<'_> {}
impl Transaction<NameStore<'_>> for HostUpdate<'_> {}

impl<'a> NameStore<'a> {
    /// Create a new RGP restore report request
    pub fn new(subproduct: &'a str) -> NameStore {
        NameStore {
            subproduct: subproduct.into(),
        }
    }
}

impl<'a> Extension for NameStore<'a> {
    type Response = NameStore<'static>;
}

#[derive(Debug, FromXml, ToXml)]
/// Type for EPP XML `<namestoreExt>` extension
#[xml(rename = "namestoreExt", ns(XMLNS))]
pub struct NameStore<'a> {
    /// The object holding the list of domains to be checked
    #[xml(rename = "subProduct")]
    pub subproduct: Cow<'a, str>,
}

#[cfg(test)]
mod tests {
    use super::NameStore;
    use crate::domain::check::DomainCheck;
    use crate::tests::{assert_serialized, response_from_file_with_ext};

    #[test]
    fn command() {
        let namestore_ext = NameStore::new("com");

        let object = DomainCheck {
            domains: &["example1.com", "example2.com", "example3.com"],
        };

        assert_serialized(
            "request/extensions/namestore.xml",
            (&object, &namestore_ext),
        );
    }

    #[test]
    fn response() {
        let object = response_from_file_with_ext::<DomainCheck, NameStore>(
            "response/extensions/namestore.xml",
        );
        let ext = object.extension().unwrap();
        assert_eq!(ext.subproduct, "com");
    }
}