tencent_sdk/services/ssl/
apply.rs

1use crate::{
2    client::{TencentCloudAsync, TencentCloudBlocking},
3    core::{Endpoint, TencentCloudResult},
4};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use std::borrow::Cow;
8
9#[derive(Debug, Deserialize)]
10pub struct ApplyCertificateResponse {
11    #[serde(rename = "Response")]
12    pub response: ApplyCertificateResult,
13}
14
15#[derive(Debug, Deserialize)]
16pub struct ApplyCertificateResult {
17    #[serde(rename = "CertificateId")]
18    pub certificate_id: Option<String>,
19    #[serde(rename = "RequestId")]
20    pub request_id: String,
21}
22
23#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
24#[serde(untagged)]
25pub enum DvAuthMethod<'a> {
26    #[serde(rename = "DNS_AUTO")]
27    DnsAuto,
28    #[serde(rename = "DNS")]
29    Dns,
30    #[serde(rename = "FILE")]
31    File,
32    #[serde(rename = "FILE_PROXY")]
33    FileProxy,
34    Custom(&'a str),
35}
36
37impl<'a> From<&'a str> for DvAuthMethod<'a> {
38    fn from(value: &'a str) -> Self {
39        match value.to_uppercase().as_str() {
40            "DNS_AUTO" => DvAuthMethod::DnsAuto,
41            "DNS" => DvAuthMethod::Dns,
42            "FILE" => DvAuthMethod::File,
43            "FILE_PROXY" => DvAuthMethod::FileProxy,
44            _ => DvAuthMethod::Custom(value),
45        }
46    }
47}
48
49impl<'a> DvAuthMethod<'a> {
50    pub fn as_str(&self) -> &str {
51        match self {
52            DvAuthMethod::DnsAuto => "DNS_AUTO",
53            DvAuthMethod::Dns => "DNS",
54            DvAuthMethod::File => "FILE",
55            DvAuthMethod::FileProxy => "FILE_PROXY",
56            DvAuthMethod::Custom(value) => value,
57        }
58    }
59}
60
61/// Request payload for `ApplyCertificate`.
62pub struct ApplyCertificate<'a> {
63    pub dv_auth_method: DvAuthMethod<'a>,
64    pub domain_name: &'a str,
65    pub project_id: Option<i64>,
66    pub package_type: Option<&'a str>,
67    pub contact_email: Option<&'a str>,
68    pub contact_phone: Option<&'a str>,
69    pub validity_period: Option<&'a str>,
70    pub csr_encrypt_algo: Option<&'a str>,
71    pub csr_key_parameter: Option<&'a str>,
72    pub csr_key_password: Option<&'a str>,
73    pub alias: Option<&'a str>,
74    pub old_certificate_id: Option<&'a str>,
75    pub package_id: Option<&'a str>,
76    pub delete_dns_auto_record: Option<bool>,
77    pub dns_names: Option<&'a [&'a str]>,
78}
79
80impl<'a> ApplyCertificate<'a> {
81    /// Create a new certificate application request
82    pub fn new(dv_auth_method: DvAuthMethod<'a>, domain_name: &'a str) -> Self {
83        Self {
84            dv_auth_method,
85            domain_name,
86            project_id: None,
87            package_type: None,
88            contact_email: None,
89            contact_phone: None,
90            validity_period: None,
91            csr_encrypt_algo: None,
92            csr_key_parameter: None,
93            csr_key_password: None,
94            alias: None,
95            old_certificate_id: None,
96            package_id: None,
97            delete_dns_auto_record: None,
98            dns_names: None,
99        }
100    }
101
102    /// Set project ID
103    pub fn with_project_id(mut self, project_id: i64) -> Self {
104        self.project_id = Some(project_id);
105        self
106    }
107
108    /// Set package type (currently only "83" is supported)
109    pub fn with_package_type(mut self, package_type: &'a str) -> Self {
110        self.package_type = Some(package_type);
111        self
112    }
113
114    /// Set contact email
115    pub fn with_contact_email(mut self, contact_email: &'a str) -> Self {
116        self.contact_email = Some(contact_email);
117        self
118    }
119
120    /// Set contact phone
121    pub fn with_contact_phone(mut self, contact_phone: &'a str) -> Self {
122        self.contact_phone = Some(contact_phone);
123        self
124    }
125
126    /// Set validity period (default "3")
127    pub fn with_validity_period(mut self, validity_period: &'a str) -> Self {
128        self.validity_period = Some(validity_period);
129        self
130    }
131
132    /// Set CSR encrypt algorithm (RSA or ECC)
133    pub fn with_csr_encrypt_algo(mut self, csr_encrypt_algo: &'a str) -> Self {
134        self.csr_encrypt_algo = Some(csr_encrypt_algo);
135        self
136    }
137
138    /// Set CSR key parameter (2048 for RSA, prime256v1 for ECC)
139    pub fn with_csr_key_parameter(mut self, csr_key_parameter: &'a str) -> Self {
140        self.csr_key_parameter = Some(csr_key_parameter);
141        self
142    }
143
144    /// Set CSR key password
145    pub fn with_csr_key_password(mut self, csr_key_password: &'a str) -> Self {
146        self.csr_key_password = Some(csr_key_password);
147        self
148    }
149
150    /// Set certificate alias
151    pub fn with_alias(mut self, alias: &'a str) -> Self {
152        self.alias = Some(alias);
153        self
154    }
155
156    /// Set old certificate ID for renewal
157    pub fn with_old_certificate_id(mut self, old_certificate_id: &'a str) -> Self {
158        self.old_certificate_id = Some(old_certificate_id);
159        self
160    }
161
162    /// Set package ID for free certificate expansion
163    pub fn with_package_id(mut self, package_id: &'a str) -> Self {
164        self.package_id = Some(package_id);
165        self
166    }
167
168    /// Set whether to delete DNS auto record after issuance
169    pub fn with_delete_dns_auto_record(mut self, delete_dns_auto_record: bool) -> Self {
170        self.delete_dns_auto_record = Some(delete_dns_auto_record);
171        self
172    }
173
174    /// Set DNS names for multi-domain certificates
175    pub fn with_dns_names(mut self, dns_names: &'a [&'a str]) -> Self {
176        self.dns_names = Some(dns_names);
177        self
178    }
179
180    /// Override the DV auth method.
181    pub fn with_dv_auth_method(mut self, dv_auth_method: DvAuthMethod<'a>) -> Self {
182        self.dv_auth_method = dv_auth_method;
183        self
184    }
185}
186
187impl<'a> Endpoint for ApplyCertificate<'a> {
188    type Output = ApplyCertificateResponse;
189
190    fn service(&self) -> Cow<'static, str> {
191        Cow::Borrowed("ssl")
192    }
193
194    fn action(&self) -> Cow<'static, str> {
195        Cow::Borrowed("ApplyCertificate")
196    }
197
198    fn version(&self) -> Cow<'static, str> {
199        Cow::Borrowed("2019-12-05")
200    }
201
202    fn region(&self) -> Option<Cow<'_, str>> {
203        // SSL APIs do not require a region parameter
204        None
205    }
206
207    fn payload(&self) -> Value {
208        let mut payload = serde_json::json!({
209            "DvAuthMethod": self.dv_auth_method.as_str(),
210            "DomainName": self.domain_name,
211        });
212
213        if let Some(project_id) = self.project_id {
214            payload["ProjectId"] = serde_json::json!(project_id);
215        }
216        if let Some(package_type) = self.package_type {
217            payload["PackageType"] = serde_json::json!(package_type);
218        }
219        if let Some(contact_email) = self.contact_email {
220            payload["ContactEmail"] = serde_json::json!(contact_email);
221        }
222        if let Some(contact_phone) = self.contact_phone {
223            payload["ContactPhone"] = serde_json::json!(contact_phone);
224        }
225        if let Some(validity_period) = self.validity_period {
226            payload["ValidityPeriod"] = serde_json::json!(validity_period);
227        }
228        if let Some(csr_encrypt_algo) = self.csr_encrypt_algo {
229            payload["CsrEncryptAlgo"] = serde_json::json!(csr_encrypt_algo);
230        }
231        if let Some(csr_key_parameter) = self.csr_key_parameter {
232            payload["CsrKeyParameter"] = serde_json::json!(csr_key_parameter);
233        }
234        if let Some(csr_key_password) = self.csr_key_password {
235            payload["CsrKeyPassword"] = serde_json::json!(csr_key_password);
236        }
237        if let Some(alias) = self.alias {
238            payload["Alias"] = serde_json::json!(alias);
239        }
240        if let Some(old_certificate_id) = self.old_certificate_id {
241            payload["OldCertificateId"] = serde_json::json!(old_certificate_id);
242        }
243        if let Some(package_id) = self.package_id {
244            payload["PackageId"] = serde_json::json!(package_id);
245        }
246        if let Some(delete_dns_auto_record) = self.delete_dns_auto_record {
247            payload["DeleteDnsAutoRecord"] = serde_json::json!(delete_dns_auto_record);
248        }
249        if let Some(dns_names) = self.dns_names {
250            payload["DnsNames"] = serde_json::json!(dns_names);
251        }
252
253        payload
254    }
255}
256
257/// Call SSL `ApplyCertificate` with the async client.
258pub async fn apply_certificate_async(
259    client: &TencentCloudAsync,
260    request: &ApplyCertificate<'_>,
261) -> TencentCloudResult<ApplyCertificateResponse> {
262    client.request(request).await
263}
264
265/// Call SSL `ApplyCertificate` with the blocking client.
266pub fn apply_certificate_blocking(
267    client: &TencentCloudBlocking,
268    request: &ApplyCertificate<'_>,
269) -> TencentCloudResult<ApplyCertificateResponse> {
270    client.request(request)
271}
272
273#[cfg(test)]
274mod tests {
275    use super::*;
276    use serde_json::json;
277
278    #[test]
279    fn apply_certificate_payload_serialization() {
280        let request = ApplyCertificate::new(DvAuthMethod::DnsAuto, "example.com")
281            .with_project_id(12345)
282            .with_package_type("83")
283            .with_contact_email("admin@example.com")
284            .with_validity_period("3")
285            .with_csr_encrypt_algo("RSA")
286            .with_csr_key_parameter("2048")
287            .with_alias("MyCertificate")
288            .with_delete_dns_auto_record(true);
289
290        let payload = request.payload();
291        assert_eq!(payload["DvAuthMethod"], json!("DNS_AUTO"));
292        assert_eq!(payload["DomainName"], json!("example.com"));
293        assert_eq!(payload["ProjectId"], json!(12345));
294        assert_eq!(payload["PackageType"], json!("83"));
295        assert_eq!(payload["ContactEmail"], json!("admin@example.com"));
296        assert_eq!(payload["ValidityPeriod"], json!("3"));
297        assert_eq!(payload["CsrEncryptAlgo"], json!("RSA"));
298        assert_eq!(payload["CsrKeyParameter"], json!("2048"));
299        assert_eq!(payload["Alias"], json!("MyCertificate"));
300        assert_eq!(payload["DeleteDnsAutoRecord"], json!(true));
301    }
302
303    #[test]
304    fn apply_certificate_with_dns_names() {
305        let dns_names = ["www.example.com", "api.example.com"];
306        let request =
307            ApplyCertificate::new(DvAuthMethod::Dns, "example.com").with_dns_names(&dns_names);
308
309        let payload = request.payload();
310        let dns_names_array = payload["DnsNames"]
311            .as_array()
312            .expect("DnsNames should be an array");
313        assert_eq!(dns_names_array[0], json!("www.example.com"));
314        assert_eq!(dns_names_array[1], json!("api.example.com"));
315    }
316
317    #[test]
318    fn deserialize_apply_certificate_response() {
319        let payload = r#"{
320            "Response": {
321                "CertificateId": "cert-123456",
322                "RequestId": "req-abc-123"
323            }
324        }"#;
325        let parsed: ApplyCertificateResponse =
326            serde_json::from_str(payload).expect("deserialize ApplyCertificateResponse");
327        assert_eq!(
328            parsed.response.certificate_id,
329            Some("cert-123456".to_string())
330        );
331        assert_eq!(parsed.response.request_id, "req-abc-123");
332    }
333
334    #[test]
335    fn builder_pattern_works_for_apply_certificate() {
336        let request = ApplyCertificate::new(DvAuthMethod::DnsAuto, "tencent.com")
337            .with_project_id(0)
338            .with_package_type("83")
339            .with_contact_email("ssl@tencent.com")
340            .with_contact_phone("18888888888")
341            .with_validity_period("3")
342            .with_csr_encrypt_algo("RSA")
343            .with_csr_key_parameter("2048")
344            .with_alias("prod-certificate")
345            .with_delete_dns_auto_record(true);
346
347        let payload = request.payload();
348        assert_eq!(payload["DvAuthMethod"], json!("DNS_AUTO"));
349        assert_eq!(payload["DomainName"], json!("tencent.com"));
350        assert_eq!(payload["ProjectId"], json!(0));
351        assert_eq!(payload["PackageType"], json!("83"));
352        assert_eq!(payload["ContactEmail"], json!("ssl@tencent.com"));
353        assert_eq!(payload["ContactPhone"], json!("18888888888"));
354        assert_eq!(payload["ValidityPeriod"], json!("3"));
355        assert_eq!(payload["CsrEncryptAlgo"], json!("RSA"));
356        assert_eq!(payload["CsrKeyParameter"], json!("2048"));
357        assert_eq!(payload["Alias"], json!("prod-certificate"));
358        assert_eq!(payload["DeleteDnsAutoRecord"], json!(true));
359    }
360
361    #[test]
362    fn apply_certificate_with_renewal() {
363        let request = ApplyCertificate::new(DvAuthMethod::Dns, "example.com")
364            .with_old_certificate_id("LqQxgqUe")
365            .with_validity_period("3");
366
367        let payload = request.payload();
368        assert_eq!(payload["DvAuthMethod"], json!("DNS"));
369        assert_eq!(payload["DomainName"], json!("example.com"));
370        assert_eq!(payload["OldCertificateId"], json!("LqQxgqUe"));
371        assert_eq!(payload["ValidityPeriod"], json!("3"));
372    }
373
374    #[test]
375    fn apply_certificate_with_ecc() {
376        let request = ApplyCertificate::new(DvAuthMethod::File, "example.com")
377            .with_csr_encrypt_algo("ECC")
378            .with_csr_key_parameter("prime256v1");
379
380        let payload = request.payload();
381        assert_eq!(payload["CsrEncryptAlgo"], json!("ECC"));
382        assert_eq!(payload["CsrKeyParameter"], json!("prime256v1"));
383    }
384}