use std::sync::Arc;
use crate::api::{ApiAccount, ApiDirectory, ApiIdentifier, ApiOrder, ApiRevocation};
use crate::cert::Certificate;
use crate::error;
use crate::order::{NewOrder, Order};
use crate::req::req_expect_header;
use crate::trans::Transport;
use crate::util::{base64url, read_json};
mod akey;
pub(crate) use self::akey::AcmeKey;
#[derive(Clone, Debug)]
pub(crate) struct AccountInner {
pub transport: Transport,
pub api_account: ApiAccount,
pub api_directory: ApiDirectory,
}
#[derive(Clone)]
pub struct Account {
inner: Arc<AccountInner>,
}
impl Account {
pub(crate) fn new(
transport: Transport,
api_account: ApiAccount,
api_directory: ApiDirectory,
) -> Self {
Account {
inner: Arc::new(AccountInner {
transport,
api_account,
api_directory,
}),
}
}
pub async fn acme_private_key_pem(&self) -> Result<String, error::Error> {
let pem = String::from_utf8(self.inner.transport.acme_key().await.to_pem()?)?;
Ok(pem)
}
pub async fn new_order(
&self,
primary_name: &str,
alt_names: &[&str],
) -> Result<NewOrder, error::Error> {
let prim_arr = [primary_name];
let domains = prim_arr.iter().chain(alt_names);
let order = ApiOrder {
identifiers: domains
.map(|s| ApiIdentifier {
_type: "dns".into(),
value: s.to_string(),
})
.collect(),
..Default::default()
};
let new_order_url = &self.inner.api_directory.newOrder;
let res = self.inner.transport.call(new_order_url, &order).await?;
let order_url = req_expect_header(&res, "location")?;
let api_order: ApiOrder = read_json(res).await?;
let order = Order::new(&self.inner, api_order, order_url);
Ok(NewOrder { order })
}
pub async fn revoke_certificate(
&self,
cert: &Certificate,
reason: RevocationReason,
) -> Result<(), error::Error> {
let certificate = base64url(&cert.certificate_der()?);
let revoc = ApiRevocation {
certificate,
reason: reason as usize,
};
let url = &self.inner.api_directory.revokeCert;
self.inner.transport.call(url, &revoc).await?;
Ok(())
}
pub fn api_account(&self) -> &ApiAccount {
&self.inner.api_account
}
}
pub enum RevocationReason {
Unspecified = 0,
KeyCompromise = 1,
CACompromise = 2,
AffiliationChanged = 3,
Superseded = 4,
CessationOfOperation = 5,
CertificateHold = 6,
RemoveFromCRL = 8,
PrivilegeWithdrawn = 9,
AACompromise = 10,
}
#[cfg(test)]
mod test {
use crate::*;
#[tokio::test]
async fn test_create_order() -> Result<(), error::Error> {
let server = crate::test::with_directory_server();
let url = DirectoryUrl::Other(&server.dir_url);
let dir = Directory::from_url(url).await?;
let acc = dir
.register_account(vec!["mailto:foo@bar.com".to_string()])
.await?;
let _ = acc.new_order("acmetest.example.com", &[]).await?;
Ok(())
}
}