taxy_api/
cert.rs

1use crate::id::ShortId;
2use crate::subject_name::SubjectName;
3use serde_default::DefaultFromSerde;
4use serde_derive::{Deserialize, Serialize};
5use std::fmt;
6use std::time::{Duration, SystemTime, UNIX_EPOCH};
7use utoipa::{IntoParams, ToSchema};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
10#[serde(rename_all = "snake_case")]
11pub enum CertKind {
12    Server,
13    Client,
14    Root,
15}
16
17impl fmt::Display for CertKind {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        write!(
20            f,
21            "{}",
22            match self {
23                CertKind::Server => "server",
24                CertKind::Client => "client",
25                CertKind::Root => "root",
26            }
27        )
28    }
29}
30
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
32pub struct CertInfo {
33    #[schema(example = "a13e1ecc080e42cfcdd5")]
34    pub id: ShortId,
35    pub kind: CertKind,
36    #[schema(example = "a13e1ecc080e42cfcdd5b77fec8450c777554aa7269c029b242a7c548d0d73da")]
37    pub fingerprint: String,
38    #[schema(example = "CN=taxy self signed cert")]
39    pub issuer: String,
40    pub root_cert: Option<String>,
41    #[schema(value_type = [String], example = json!(["localhost"]))]
42    pub san: Vec<SubjectName>,
43    #[schema(example = "67090118400")]
44    pub not_after: i64,
45    #[schema(example = "157766400")]
46    pub not_before: i64,
47    pub is_ca: bool,
48    pub has_private_key: bool,
49    pub metadata: Option<CertMetadata>,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
53pub struct SelfSignedCertRequest {
54    #[schema(value_type = [String], example = json!(["localhost"]))]
55    pub san: Vec<SubjectName>,
56    #[schema(example = "f9cf7e3faa1aca7e6086")]
57    pub ca_cert: Option<ShortId>,
58}
59
60#[derive(DefaultFromSerde, Clone, Serialize, Deserialize, IntoParams)]
61#[into_params(parameter_in = Query)]
62pub struct UploadQuery {
63    #[serde(default = "default_cert_kind")]
64    pub kind: CertKind,
65}
66
67fn default_cert_kind() -> CertKind {
68    CertKind::Server
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
72pub struct CertMetadata {
73    pub acme_id: ShortId,
74    #[serde(
75        serialize_with = "serialize_created_at",
76        deserialize_with = "deserialize_created_at"
77    )]
78    #[schema(value_type = u64)]
79    pub created_at: SystemTime,
80}
81
82fn serialize_created_at<S>(time: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
83where
84    S: serde::Serializer,
85{
86    let timestamp = time
87        .duration_since(UNIX_EPOCH)
88        .map_err(|_| serde::ser::Error::custom("invalid timestamp"))?;
89    serializer.serialize_u64(timestamp.as_secs())
90}
91
92fn deserialize_created_at<'de, D>(deserializer: D) -> Result<SystemTime, D::Error>
93where
94    D: serde::Deserializer<'de>,
95{
96    use serde::Deserialize;
97    let timestamp = u64::deserialize(deserializer)?;
98    Ok(UNIX_EPOCH + Duration::from_secs(timestamp))
99}
100
101#[derive(ToSchema)]
102pub struct CertPostBody {
103    #[schema(format = Binary)]
104    pub chain: String,
105    #[schema(format = Binary)]
106    pub key: String,
107}