Skip to content

Commit

Permalink
acme: show renewal date on AcmeList
Browse files Browse the repository at this point in the history
  • Loading branch information
picoHz committed Jan 28, 2024
1 parent d0c1ec2 commit 7ecdf52
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 29 deletions.
1 change: 1 addition & 0 deletions taxy-api/src/acme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub struct AcmeInfo {
pub identifiers: Vec<String>,
#[schema(value_type = String, example = "http-01")]
pub challenge_type: String,
pub next_renewal: Option<i64>,
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
Expand Down
2 changes: 1 addition & 1 deletion taxy-webui/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use time::{format_description::well_known::Rfc3339, OffsetDateTime};
use wasm_bindgen::UnwrapThrowExt;
use web_time::{Duration, SystemTime, UNIX_EPOCH};

pub fn format_expiry(unix_time: i64) -> String {
pub fn format_time(unix_time: i64) -> String {
let time = OffsetDateTime::from_unix_timestamp(unix_time).unwrap_throw();
let timestamp = time.format(&Rfc3339).unwrap_throw();
let date = timestamp.split('T').next().unwrap_throw().to_string();
Expand Down
14 changes: 11 additions & 3 deletions taxy-webui/src/pages/cert_list.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::auth::use_ensure_auth;
use crate::format::format_expiry;
use crate::format::format_time;
use crate::pages::Route;
use crate::store::{AcmeStore, CertStore};
use crate::API_ENDPOINT;
Expand Down Expand Up @@ -210,7 +210,7 @@ pub fn cert_list() -> Html {
{entry.id.to_string()}
</td>
<td class="px-4 py-4">
{format_expiry(entry.not_after)}
{format_time(entry.not_after)}
</td>
<td class="px-4 py-4 w-0 whitespace-nowrap" align="right">
<a class="cursor-pointer font-medium text-blue-600 dark:text-blue-400 hover:underline mr-5" onclick={download_onclick}>{"Download"}</a>
Expand Down Expand Up @@ -289,7 +289,7 @@ pub fn cert_list() -> Html {
}
</td>
<td class="px-4 py-4">
{format_expiry(entry.not_after)}
{format_time(entry.not_after)}
</td>
<td class="px-4 py-4 w-0 whitespace-nowrap" align="right">
<a class="cursor-pointer font-medium text-blue-600 dark:text-blue-400 hover:underline mr-5" onclick={download_onclick}>{"Download"}</a>
Expand Down Expand Up @@ -321,6 +321,9 @@ pub fn cert_list() -> Html {
<th scope="col" class="px-4 py-3">
{"Provider"}
</th>
<th scope="col" class="px-4 py-3">
{"Renews on"}
</th>
<th scope="col" class="px-4 py-3" align="center">
{"Active"}
</th>
Expand Down Expand Up @@ -366,6 +369,11 @@ pub fn cert_list() -> Html {
<td class="px-4 py-4">
{provider}
</td>
<td class="px-4 py-4">
if let Some(time) = entry.next_renewal {
{ format_time(time) }
}
</td>
<td class="px-4 py-4 w-0 whitespace-nowrap" align="center">
<label class="relative inline-flex items-center cursor-pointer mt-1">
<input {onchange} type="checkbox" checked={active} class="sr-only peer" />
Expand Down
28 changes: 26 additions & 2 deletions taxy/src/certs/acme.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::certs::Cert;
use crate::{certs::Cert, server::cert_list::CertList};
use anyhow::bail;
use backoff::{backoff::Backoff, ExponentialBackoffBuilder};
use instant_acme::{
Expand Down Expand Up @@ -81,7 +81,7 @@ impl AcmeEntry {
self.id
}

pub fn info(&self) -> AcmeInfo {
pub fn info(&self, certs: &CertList) -> AcmeInfo {
AcmeInfo {
id: self.id,
config: self.acme.config.clone(),
Expand All @@ -92,8 +92,32 @@ impl AcmeEntry {
.map(|id| id.to_string())
.collect(),
challenge_type: self.acme.challenge_type.clone(),
next_renewal: self
.next_renewal(certs)
.and_then(|t| t.duration_since(SystemTime::UNIX_EPOCH).ok())
.map(|t| t.as_secs() as i64),
}
}

pub fn last_issued(&self, certs: &CertList) -> Option<SystemTime> {
certs
.find_certs_by_acme(self.id)
.iter()
.map(|cert| {
cert.metadata
.as_ref()
.map(|meta| meta.created_at)
.unwrap_or(SystemTime::UNIX_EPOCH)
})
.max()
}

pub fn next_renewal(&self, certs: &CertList) -> Option<SystemTime> {
let last_issued = self.last_issued(certs)?;
let renewal_days = self.acme.config.renewal_days;
let next_renewal = last_issued + Duration::from_secs(60 * 60 * 24 * renewal_days);
Some(next_renewal)
}
}

#[derive(Clone, Serialize, Deserialize)]
Expand Down
8 changes: 6 additions & 2 deletions taxy/src/server/rpc/acme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ impl RpcMethod for GetAcmeList {
type Output = Vec<AcmeInfo>;

async fn call(self, state: &mut ServerState) -> Result<Self::Output, Error> {
Ok(state.acmes.entries().map(|acme| acme.info()).collect())
Ok(state
.acmes
.entries()
.map(|acme| acme.info(&state.certs))
.collect())
}
}

Expand All @@ -29,7 +33,7 @@ impl RpcMethod for GetAcme {
state
.acmes
.get(self.id)
.map(|acme| acme.info())
.map(|acme| acme.info(&state.certs))
.ok_or(Error::IdNotFound {
id: self.id.to_string(),
})
Expand Down
31 changes: 10 additions & 21 deletions taxy/src/server/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ use rand::seq::SliceRandom;
use std::collections::HashSet;
use std::convert::Infallible;
use std::str;
use std::{
collections::HashMap,
sync::Arc,
time::{Duration, SystemTime},
};
use std::{collections::HashMap, sync::Arc};
use taxy_api::app::{AppConfig, AppInfo};
use taxy_api::error::Error;
use taxy_api::event::ServerEvent;
Expand Down Expand Up @@ -215,7 +211,11 @@ impl ServerState {

pub async fn update_acmes(&mut self) {
let _ = self.br_sender.send(ServerEvent::AcmeUpdated {
entries: self.acmes.entries().map(|acme| acme.info()).collect(),
entries: self
.acmes
.entries()
.map(|acme| acme.info(&self.certs))
.collect(),
});
self.start_http_challenges().await;
}
Expand Down Expand Up @@ -316,21 +316,10 @@ impl ServerState {
let entries = entries
.filter(|entry| {
entry.acme.config.active
&& self
.certs
.find_certs_by_acme(entry.id)
.iter()
.map(|cert| {
cert.metadata
.as_ref()
.map(|meta| meta.created_at)
.unwrap_or(SystemTime::UNIX_EPOCH)
})
.max()
.unwrap_or(SystemTime::UNIX_EPOCH)
.elapsed()
.unwrap_or_default()
> Duration::from_secs(60 * 60 * 24 * entry.acme.config.renewal_days)
&& entry
.next_renewal(&self.certs)
.map(|next| next.elapsed().is_ok())
== Some(true)
})
.collect::<Vec<_>>();

Expand Down

0 comments on commit 7ecdf52

Please sign in to comment.