1
use std::sync::Arc;
2
use std::time::Duration;
3

            
4
use async_acme::cache::AcmeCache;
5
use async_trait::async_trait;
6
use bonsaidb_core::arc_bytes::serde::Bytes;
7
use bonsaidb_core::connection::AsyncConnection;
8
use bonsaidb_core::define_basic_unique_mapped_view;
9
use bonsaidb_core::document::{CollectionDocument, Emit, KeyId};
10
use bonsaidb_core::schema::{Collection, SerializedCollection};
11
use serde::{Deserialize, Serialize};
12

            
13
use crate::{Backend, CustomServer, Error};
14

            
15
9370
#[derive(Clone, Debug, Serialize, Deserialize, Collection)]
16
#[collection(name = "acme-accounts", authority = "khonsulabs", views = [AcmeAccountByContacts])]
17
#[collection(encryption_key = Some(KeyId::Master), encryption_optional, core = bonsaidb_core)]
18
pub struct AcmeAccount {
19
    pub contacts: Vec<String>,
20
    pub data: Bytes,
21
}
22

            
23
define_basic_unique_mapped_view!(
24
    AcmeAccountByContacts,
25
    AcmeAccount,
26
    1,
27
    "by-contacts",
28
    String,
29
    |document: CollectionDocument<AcmeAccount>| {
30
        document
31
            .header
32
            .emit_key(document.contents.contacts.join(";"))
33
    }
34
);
35

            
36
#[async_trait]
37
impl<B: Backend> AcmeCache for CustomServer<B> {
38
    type Error = Error;
39

            
40
    async fn read_account(&self, contacts: &[&str]) -> Result<Option<Vec<u8>>, Self::Error> {
41
        let db = self.hosted().await;
42
        let contact = db
43
            .view::<AcmeAccountByContacts>()
44
            .with_key(&contacts.join(";"))
45
            .query_with_collection_docs()
46
            .await?
47
            .documents
48
            .into_iter()
49
            .next();
50

            
51
        if let Some((_, contact)) = contact {
52
            Ok(Some(contact.contents.data.into_vec()))
53
        } else {
54
            Ok(None)
55
        }
56
    }
57

            
58
    async fn write_account(&self, contacts: &[&str], contents: &[u8]) -> Result<(), Self::Error> {
59
        let db = self.hosted().await;
60
        let mapped_account = db
61
            .view::<AcmeAccountByContacts>()
62
            .with_key(&contacts.join(";"))
63
            .query_with_collection_docs()
64
            .await?
65
            .documents
66
            .into_iter()
67
            .next();
68
        if let Some((_, mut account)) = mapped_account {
69
            account.contents.data = Bytes::from(contents);
70
            account.update_async(&db).await?;
71
        } else {
72
            AcmeAccount {
73
                contacts: contacts.iter().map(|&c| c.to_string()).collect(),
74
                data: Bytes::from(contents),
75
            }
76
            .push_into_async(&db)
77
            .await?;
78
        }
79

            
80
        Ok(())
81
    }
82

            
83
    async fn write_certificate(
84
        &self,
85
        _domains: &[String],
86
        _directory_url: &str,
87
        key_pem: &str,
88
        certificate_pem: &str,
89
    ) -> Result<(), Self::Error> {
90
        self.install_pem_certificate(certificate_pem.as_bytes(), key_pem.as_bytes())
91
            .await
92
    }
93
}
94

            
95
impl<B: Backend> CustomServer<B> {
96
1
    pub(crate) async fn update_acme_certificates(&self) -> Result<(), Error> {
97
        loop {
98
            {
99
1
                let key = self.data.primary_tls_key.lock().clone();
100
1
                while async_acme::rustls_helper::duration_until_renewal_attempt(key.as_deref(), 0)
101
1
                    > Duration::from_secs(24 * 60 * 60 * 14)
102
                {
103
1
                    tokio::time::sleep(Duration::from_secs(60 * 60)).await;
104
                }
105
            }
106

            
107
            log::info!(
108
                "requesting new tls certificate for {}",
109
                self.data.primary_domain
110
            );
111
            let domains = vec![self.data.primary_domain.clone()];
112
            async_acme::rustls_helper::order(
113
                |domain, key| {
114
                    let mut auth_keys = self.data.alpn_keys.lock();
115
                    auth_keys.insert(domain, Arc::new(key));
116
                    Ok(())
117
                },
118
                &self.data.acme.directory,
119
                &domains,
120
                Some(self),
121
                &self
122
                    .data
123
                    .acme
124
                    .contact_email
125
                    .iter()
126
                    .cloned()
127
                    .collect::<Vec<_>>(),
128
            )
129
            .await?;
130
        }
131
    }
132
}