Skip to main content

acme_proxy_core/
identifier.rs

1//! The ACME identifier (RFC 8555 §7.1.4) — the name an order, an
2//! authorization, a filter check and a signer's CSR check all speak about.
3//!
4//! Its own module rather than beside the order row it is stored in, because
5//! everything above the storage layer names it too: the problem documents'
6//! `subproblems`, the filters, the audit trail's frozen identifier list.
7
8use serde::{Deserialize, Serialize};
9
10/// An ACME identifier (RFC 8555 §7.1.4). Only `dns` is supported here, but the
11/// type is kept generic so the JSON round-trips whatever a client sent.
12///
13/// Stored inside the order's `identifiers` JSON array and echoed verbatim in the
14/// order object. Reused by the signer to check a finalize CSR's SANs.
15#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub struct Identifier {
17    #[serde(rename = "type")]
18    pub typ: String,
19    pub value: String,
20}
21
22impl Identifier {
23    /// A `dns` identifier, which is every identifier this server issues for.
24    ///
25    /// Here rather than in a test helper because the struct had no constructor
26    /// at all, and twelve modules had each grown their own `fn dns(&str)` to
27    /// avoid writing the literal — the same accumulation that put `TempDir` in
28    /// `testutil`, except these are one line each and belong in production,
29    /// where the handlers building identifiers benefit too.
30    #[must_use]
31    pub fn dns(value: impl Into<String>) -> Self {
32        Self::new("dns", value)
33    }
34
35    /// An identifier of any type. `typ` is kept a free string because RFC 8555
36    /// §9.7.7 leaves the registry open and the order object echoes back
37    /// whatever a client sent.
38    #[must_use]
39    pub fn new(typ: impl Into<String>, value: impl Into<String>) -> Self {
40        Self {
41            typ: typ.into(),
42            value: value.into(),
43        }
44    }
45}