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
use crate::api::Endpoint;
use derive_builder::Builder;
use http::Method;
use serde_json::{Map, Value};
use std::borrow::Cow;

use super::{fill_body_with_record, DnsContent};

#[derive(Debug, Builder)]
#[builder(setter(strip_option))]
pub struct CreateDns<'a> {
    #[builder(setter(into))]
    record: DnsContent,
    #[builder(setter(into))]
    domain: Cow<'a, str>,
    #[builder(default)]
    ttl: Option<u32>,
    #[builder(setter(into), default)]
    name: Option<Cow<'a, str>>,
}

impl<'a> CreateDns<'a> {
    pub fn builder() -> CreateDnsBuilder<'a> {
        CreateDnsBuilder::default()
    }
}

impl<'a> Endpoint for CreateDns<'a> {
    fn method(&self) -> Method {
        Method::POST
    }

    fn endpoint(&self) -> Cow<'static, str> {
        format!("dns/create/{}", self.domain).into()
    }

    fn body(&self) -> Map<String, Value> {
        let mut body = Map::default();
        if let Some(name) = &self.name {
            body.insert("name".into(), name.to_string().into());
        }

        if let Some(ttl) = self.ttl {
            body.insert("ttl".into(), ttl.to_string().into());
        }

        fill_body_with_record(&mut body, &self.record);

        body
    }
}

#[cfg(test)]
mod tests {
    use http::Method;
    use serde_json::json;

    use crate::{
        api::{self, Query},
        endpoints::{CreateDns, DnsContent},
        test::client::{ExpectedUrl, SingleTestClient},
    };

    #[test]
    fn record_is_necessary() {
        let err = CreateDns::builder().build().unwrap_err();
        assert_eq!("`record` must be initialized", err.to_string())
    }

    #[test]
    fn domain_is_necessary() {
        let err = CreateDns::builder()
            .record(DnsContent::Cname {
                content: "".to_string(),
            })
            .build()
            .unwrap_err();
        assert_eq!("`domain` must be initialized", err.to_string())
    }

    #[test]
    fn domain_and_record_are_sufficient() {
        CreateDns::builder()
            .domain("example.com")
            .record(DnsContent::Cname {
                content: "".to_string(),
            })
            .build()
            .unwrap();
    }

    #[test]
    fn endpoint() {
        let endpoint = ExpectedUrl::builder()
            .method(Method::POST)
            .endpoint("dns/create/example.com")
            .content_type("application/json")
            .body_json(&json!({
                "name": "*",
                "ttl": "600",
                "prio": "600",
                "type": "MX",
                "content": "cnCname",
            }))
            .build()
            .unwrap();
        let client = SingleTestClient::new_raw(endpoint, "");

        let endpoint = CreateDns::builder()
            .domain("example.com")
            .record(DnsContent::Mx {
                priority: 600,
                content: "cnCname".to_string(),
            })
            .ttl(600)
            .name("*")
            .build()
            .unwrap();

        api::ignore(endpoint).query(&client).unwrap();
    }
}