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
use bonsaidb_core::document::{CollectionDocument, Emit, KeyId};
use bonsaidb_core::schema::{Collection, NamedCollection, Schema};
use bonsaidb_core::{define_basic_mapped_view, define_basic_unique_mapped_view};
use fabruic::{CertificateChain, PrivateKey};
use serde::de::Visitor;
use serde::{Deserialize, Serialize};

#[derive(Debug, Schema)]
#[schema(name = "hosted", authority = "khonsulabs", collections = [TlsCertificate], core = bonsaidb_core)]
#[cfg_attr(feature = "acme", schema(collections = [crate::server::acme::AcmeAccount]))]
pub struct Hosted;

#[derive(Clone, Debug, Serialize, Deserialize, Collection)]
#[collection(name = "tls-certificates", authority = "khonsulabs", views = [TlsCertificatesByDomain, TlsCertificateByAllDomains])]
#[collection(encryption_key = Some(KeyId::Master), encryption_optional, core = bonsaidb_core)]
pub struct TlsCertificate {
    pub domains: Vec<String>,
    pub private_key: SerializablePrivateKey,
    pub certificate_chain: CertificateChain,
}

impl NamedCollection for TlsCertificate {
    type ByNameView = TlsCertificateByAllDomains;
}

define_basic_unique_mapped_view!(
    TlsCertificateByAllDomains,
    TlsCertificate,
    1,
    "by-all-domains",
    String,
    |document: CollectionDocument<TlsCertificate>| {
        document
            .header
            .emit_key(document.contents.domains.join(";"))
    }
);

define_basic_mapped_view!(
    TlsCertificatesByDomain,
    TlsCertificate,
    1,
    "by-domain",
    String,
    CertificateChain,
    |document: CollectionDocument<TlsCertificate>| {
        document
            .contents
            .domains
            .into_iter()
            .map(|domain| {
                document
                    .header
                    .emit_key_and_value(domain, document.contents.certificate_chain.clone())
            })
            .collect()
    }
);

#[derive(Clone, Debug)]
pub struct SerializablePrivateKey(pub PrivateKey);

impl Serialize for SerializablePrivateKey {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        fabruic::dangerous::PrivateKey::serialize(&self.0, serializer)
    }
}

impl<'de> Deserialize<'de> for SerializablePrivateKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        PrivateKey::deserialize(deserializer).map(Self)
    }
}

struct SerializablePrivateKeyVisitor;

impl<'de> Visitor<'de> for SerializablePrivateKeyVisitor {
    type Value = SerializablePrivateKey;

    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        formatter.write_str("byte array")
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
    where
        E: serde::de::Error,
    {
        Ok(SerializablePrivateKey(PrivateKey::unchecked_from_der(
            v.to_vec(),
        )))
    }
}