58 lines
1.5 KiB
Rust
58 lines
1.5 KiB
Rust
|
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 {}
|