use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize, Serializer};
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Jws {
pub protected: String,
pub payload: String,
pub signature: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Account {
pub status: AccountStatus,
#[serde(rename = "contact")]
pub contacts: Option<Vec<String>>,
pub terms_of_service_agreed: Option<bool>,
pub orders: Option<String>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum AccountStatus {
Valid,
Deactivated,
Revoked,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NewAccount {
#[serde(rename = "contact")]
pub contacts: Option<Vec<String>>,
pub terms_of_service_agreed: bool,
pub only_return_existing: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub external_account_binding: Option<Jws>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Order {
pub status: OrderStatus,
pub expires: Option<DateTime<Utc>>,
pub identifiers: Vec<Identifier>,
pub not_before: Option<DateTime<Utc>>,
pub not_after: Option<DateTime<Utc>>,
pub error: Option<Error>,
pub authorizations: Vec<String>,
pub finalize: String,
pub certificate: Option<String>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum OrderStatus {
Pending,
Ready,
Processing,
Valid,
Invalid,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NewOrder {
pub identifiers: Vec<Identifier>,
pub not_before: Option<DateTime<Utc>>,
pub not_after: Option<DateTime<Utc>>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Authorization {
pub identifier: Identifier,
pub status: AuthorizationStatus,
pub expires: Option<DateTime<Utc>>,
pub challenges: Vec<Challenge>,
pub wildcard: Option<bool>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum AuthorizationStatus {
Pending,
Valid,
Invalid,
Deactivated,
Expired,
Revoked,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Challenge {
pub url: String,
pub status: ChallengeStatus,
pub validated: Option<DateTime<Utc>>,
#[serde(rename = "type")]
pub type_: ChallengeType,
pub token: String,
pub error: Option<Error>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum ChallengeType {
#[serde(rename = "dns-01")]
Dns01,
#[serde(rename = "http-01")]
Http01,
#[serde(rename = "tls-alpn-01")]
TlsAlpn01,
#[serde(other)]
Unknown,
}
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum ChallengeStatus {
Pending,
Processing,
Valid,
Invalid,
}
#[derive(Debug, Serialize)]
pub struct FinalizeOrder {
pub csr: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Directory {
pub new_nonce: String,
pub new_account: String,
pub new_order: String,
pub revoke_cert: String,
pub key_change: String,
pub new_authz: Option<String>,
#[serde(default)]
pub meta: DirectoryMeta,
}
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DirectoryMeta {
pub terms_of_service: Option<String>,
pub website: Option<String>,
pub caa_identities: Option<Vec<String>>,
pub external_account_required: Option<bool>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RevocationRequest {
pub certificate: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<RevocationReason>,
}
#[derive(Clone, Copy, Debug)]
#[repr(u8)]
pub enum RevocationReason {
Unspecified = 0,
KeyCompromise = 1,
CACompromise = 2,
AffiliationChanges = 3,
Superseded = 4,
CessationOfOperation = 5,
CertificateHold = 6,
RemoveFromCRL = 8,
PrivilegeWithdrawn = 9,
AACompromise = 10,
}
impl Serialize for RevocationReason {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_u8(*self as u8)
}
}
macro_rules! error_type {
(
$(
#[doc=$doc:expr]
$type:ident => $urn:expr
),+ $(,)?
) => {
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize)]
pub enum ErrorType {
$(
#[doc=$doc]
#[serde(rename = $urn)]
$type,
)*
Other(String),
}
impl ErrorType {
pub fn description(&self) -> &'static str {
match self {
$(
Self::$type => $doc,
)*
Self::Other(_) => "A non-standard error",
}
}
pub fn code(&self) -> &str {
match self {
$(
Self::$type => $urn,
)*
Self::Other(e) => e.as_str(),
}
}
}
};
}
error_type! {
AccountDoesNotExist => "urn:ietf:params:acme:error:accountDoesNotExist",
AlreadyRevoked => "urn:ietf:params:acme:error:alreadyRevoked",
BadCsr => "urn:ietf:params:acme:error:badCSR",
BadNonce => "urn:ietf:params:acme:error:badNonce",
BadPublicKey => "urn:ietf:params:acme:error:badPublicKey",
BadRevocationReason => "urn:ietf:params:acme:error:badRevocationReason",
BadSignatureAlgorithm => "urn:ietf:params:acme:error:badSignatureAlgorithm",
Caa => "urn:ietf:params:acme:error:caa",
Compound => "urn:ietf:params:acme:error:compound",
Connection => "urn:ietf:params:acme:error:connection",
Dns => "urn:ietf:params:acme:error:dns",
ExternalAccountRequired => "urn:ietf:params:acme:error:externalAccountRequired",
IncorrectResponse => "urn:ietf:params:acme:error:incorrectResponse",
InvalidContact => "urn:ietf:params:acme:error:invalidContact",
Malformed => "urn:ietf:params:acme:error:malformed",
OrderNotReady => "urn:ietf:params:acme:error:orderNotReady",
RateLimited => "urn:ietf:params:acme:error:rateLimited",
RejectedIdentifier => "urn:ietf:params:acme:error:rejectedIdentifier",
ServerInternal => "urn:ietf:params:acme:error:serverInternal",
Tls => "urn:ietf:params:acme:error:tls",
Unauthorized => "urn:ietf:params:acme:error:unauthorized",
UnsupportedContact => "urn:ietf:params:acme:error:unsupportedContact",
UnsupportedIdentifier => "urn:ietf:params:acme:error:unsupportedIdentifier",
UserActionRequired => "urn:ietf:params:acme:error:userActionRequired",
}
#[derive(Debug, Deserialize)]
pub struct Error {
#[serde(rename = "type")]
pub type_: ErrorType,
pub title: Option<String>,
pub detail: Option<String>,
pub status: Option<u16>,
pub subproblems: Option<Vec<SubProblem>>,
}
#[derive(Debug, Deserialize)]
pub struct SubProblem {
#[serde(rename = "type")]
pub type_: ErrorType,
pub title: Option<String>,
pub detail: Option<String>,
pub identifier: Option<Identifier>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", tag = "type", content = "value")]
pub enum Identifier {
Dns(String),
}