domani/src/domain/acme/manager.rs

58 lines
1.5 KiB
Rust
Raw Normal View History

use std::sync;
use crate::domain::acme;
use crate::error;
use crate::error::{MapUnexpected, ToUnexpected};
const LETS_ENCRYPT_URL: &'static str = "https://acme-v02.api.letsencrypt.org/directory";
#[mockall::automock]
pub trait Manager {}
pub trait BoxedManager: Manager + Send + Sync + Clone {}
struct ManagerImpl<Store>
where
Store: acme::store::BoxedStore,
{
store: Store,
account: sync::Arc<acme2::Account>,
}
pub async fn new<Store>(
store: Store,
contact_email: &str,
) -> Result<impl BoxedManager, error::Unexpected>
where
Store: acme::store::BoxedStore,
{
let dir = acme2::DirectoryBuilder::new(LETS_ENCRYPT_URL.to_string())
.build()
.await
.map_unexpected()?;
let mut builder = acme2::AccountBuilder::new(dir);
builder.contact(vec![contact_email.to_string()]);
builder.terms_of_service_agreed(true);
match store.get_account_key() {
Ok(account_key) => {
builder.private_key(account_key);
}
Err(acme::store::GetAccountKeyError::NotFound) => (),
Err(acme::store::GetAccountKeyError::Unexpected(err)) => return Err(err.to_unexpected()),
}
let account = builder.build().await.map_unexpected()?;
store
.set_account_key(&account.private_key())
.map_unexpected()?;
Ok(sync::Arc::new(ManagerImpl { store, account }))
}
impl<Store> BoxedManager for sync::Arc<ManagerImpl<Store>> where Store: acme::store::BoxedStore {}
impl<Store> Manager for sync::Arc<ManagerImpl<Store>> where Store: acme::store::BoxedStore {}