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 where Store: acme::store::BoxedStore, { store: Store, account: sync::Arc, } pub async fn new( store: Store, contact_email: &str, ) -> Result 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 BoxedManager for sync::Arc> where Store: acme::store::BoxedStore {} impl Manager for sync::Arc> where Store: acme::store::BoxedStore {}