1use std::sync::Arc;
3
4use crate::api::{ApiAccount, ApiDirectory, ApiIdentifier, ApiOrder, ApiRevocation};
5use crate::cert::Certificate;
6use crate::error::*;
7use crate::order::{NewOrder, Order};
8use crate::req::req_expect_header;
9use crate::trans::Transport;
10use crate::util::{base64url, read_json};
11
12mod akey;
13
14pub(crate) use self::akey::AcmeKey;
15
16#[derive(Clone, Debug)]
17pub(crate) struct AccountInner {
18 pub transport: Transport,
19 pub api_account: ApiAccount,
20 pub api_directory: ApiDirectory,
21}
22
23#[derive(Clone)]
38pub struct Account {
39 inner: Arc<AccountInner>,
40}
41
42impl Account {
43 pub(crate) fn new(
44 transport: Transport,
45 api_account: ApiAccount,
46 api_directory: ApiDirectory,
47 ) -> Self {
48 Account {
49 inner: Arc::new(AccountInner {
50 transport,
51 api_account,
52 api_directory,
53 }),
54 }
55 }
56
57 pub fn acme_private_key_pem(&self) -> Result<String> {
61 let pem = String::from_utf8(self.inner.transport.acme_key().to_pem()?)?;
62 Ok(pem)
63 }
64
65 pub fn new_order(&self, primary_name: &str, alt_names: &[&str]) -> Result<NewOrder> {
78 let prim_arr = [primary_name];
80 let domains = prim_arr.iter().chain(alt_names);
81 let order = ApiOrder {
82 identifiers: domains
83 .map(|s| ApiIdentifier {
84 _type: "dns".into(),
85 value: s.to_string(),
86 })
87 .collect(),
88 ..Default::default()
89 };
90
91 let new_order_url = &self.inner.api_directory.newOrder;
92
93 let res = self.inner.transport.call(new_order_url, &order)?;
94 let order_url = req_expect_header(&res, "location")?;
95 let api_order: ApiOrder = read_json(res)?;
96
97 let order = Order::new(&self.inner, api_order, order_url);
98 Ok(NewOrder { order })
99 }
100
101 pub fn revoke_certificate(&self, cert: &Certificate, reason: RevocationReason) -> Result<()> {
103 let certificate = base64url(&cert.certificate_der()?);
105
106 let revoc = ApiRevocation {
107 certificate,
108 reason: reason as usize,
109 };
110
111 let url = &self.inner.api_directory.revokeCert;
112 self.inner.transport.call(url, &revoc)?;
113
114 Ok(())
115 }
116
117 pub fn api_account(&self) -> &ApiAccount {
119 &self.inner.api_account
120 }
121}
122
123pub enum RevocationReason {
127 Unspecified = 0,
128 KeyCompromise = 1,
129 CACompromise = 2,
130 AffiliationChanged = 3,
131 Superseded = 4,
132 CessationOfOperation = 5,
133 CertificateHold = 6,
134 RemoveFromCRL = 8,
136 PrivilegeWithdrawn = 9,
137 AACompromise = 10,
138}
139
140#[cfg(test)]
141mod test {
142 use crate::*;
143
144 #[test]
145 fn test_create_order() -> Result<()> {
146 let server = crate::test::with_directory_server();
147 let url = DirectoryUrl::Other(&server.dir_url);
148 let dir = Directory::from_url(url)?;
149 let acc = dir.register_account(vec!["mailto:foo@bar.com".to_string()])?;
150 let _ = acc.new_order("acmetest.example.com", &[])?;
151 Ok(())
152 }
153}