Use anyhow for error handling
This commit is contained in:
parent
372a49262d
commit
97fae54252
6 changed files with 43 additions and 51 deletions
|
@ -8,6 +8,7 @@ license = "MIT OR Apache-2.0"
|
|||
publish = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.70", default-features = false, features = ["std"] }
|
||||
base64 = { version = "0.21.0", default-features = false, features = ["std"] }
|
||||
clap = { version = "4.1.13", default-features = false, features = ["std", "derive"] }
|
||||
ed25519-dalek = { version = "2.0.0-rc.2", default-features = false, features = ["fast", "rand_core", "std"] }
|
||||
|
|
|
@ -27,7 +27,7 @@ pub async fn new_action(action: Action<'_>) -> ActionResult {
|
|||
Action::ReadLine(reader_lock) => match read_entry(reader_lock).await {
|
||||
Some(r) => match r {
|
||||
Ok(entry) => ActionResult::NewEntry(entry),
|
||||
Err(err) => ActionResult::NewEntryError(err),
|
||||
Err(err) => ActionResult::NewEntryError(err.to_string()),
|
||||
},
|
||||
None => ActionResult::EndOfStream,
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::config::Config;
|
||||
use anyhow::Result;
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
||||
use sqlx::{ConnectOptions, SqlitePool};
|
||||
|
||||
|
@ -49,11 +50,7 @@ WHERE
|
|||
AND sdid = $2
|
||||
AND algorithm = $3";
|
||||
|
||||
pub async fn init(cnf: &Config) -> Result<SqlitePool, String> {
|
||||
do_init(cnf).await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
async fn do_init(cnf: &Config) -> Result<SqlitePool, sqlx::Error> {
|
||||
pub async fn init(cnf: &Config) -> Result<SqlitePool> {
|
||||
let mut db_options = SqliteConnectOptions::new()
|
||||
.filename(cnf.key_data_base())
|
||||
.create_if_missing(true);
|
||||
|
|
|
@ -44,13 +44,7 @@ pub async fn read_entry(reader_lock: Arc<RwLock<StdinReader>>) -> Option<Result<
|
|||
let line_res = reader.read_line().await;
|
||||
drop(reader);
|
||||
log::trace!("reader lock on stdin released");
|
||||
match line_res {
|
||||
Some(line) => match Entry::from_bytes(&line) {
|
||||
Ok(entry) => Some(Ok(entry)),
|
||||
Err(err) => Some(Err(err)),
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
line_res.map(|line| Entry::from_bytes(&line))
|
||||
}
|
||||
|
||||
fn is_eol(c: u8) -> bool {
|
||||
|
|
45
src/key.rs
45
src/key.rs
|
@ -1,5 +1,6 @@
|
|||
use crate::config::Config;
|
||||
use crate::Algorithm;
|
||||
use anyhow::Result;
|
||||
use sqlx::types::time::OffsetDateTime;
|
||||
use sqlx::SqlitePool;
|
||||
use std::path::Path;
|
||||
|
@ -30,37 +31,34 @@ pub async fn key_rotation(db: &SqlitePool, cnf: &Config) -> Duration {
|
|||
durations[durations.len() - 1]
|
||||
}
|
||||
|
||||
async fn publish_expired_keys(db: &SqlitePool, file_path: &Path) -> Result<Duration, String> {
|
||||
async fn publish_expired_keys(db: &SqlitePool, file_path: &Path) -> Result<Duration> {
|
||||
let res: Vec<(String, String, String, String)> = sqlx::query_as(crate::db::SELECT_EXPIRED_KEYS)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
.await?;
|
||||
if !res.is_empty() {
|
||||
let rev_file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(file_path)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
.await?;
|
||||
let mut buff = BufWriter::new(rev_file);
|
||||
for (selector, sdid, algorithm, private_key) in res {
|
||||
buff.write_all(algorithm.as_bytes()).await.unwrap();
|
||||
buff.write_all(b" ").await.unwrap();
|
||||
buff.write_all(private_key.as_bytes()).await.unwrap();
|
||||
buff.write_all(b" ").await.unwrap();
|
||||
buff.write_all(selector.as_bytes()).await.unwrap();
|
||||
buff.write_all(b"._domainkey.").await.unwrap();
|
||||
buff.write_all(sdid.as_bytes()).await.unwrap();
|
||||
buff.write_all(b"\n").await.unwrap();
|
||||
buff.flush().await.unwrap();
|
||||
buff.write_all(algorithm.as_bytes()).await?;
|
||||
buff.write_all(b" ").await?;
|
||||
buff.write_all(private_key.as_bytes()).await?;
|
||||
buff.write_all(b" ").await?;
|
||||
buff.write_all(selector.as_bytes()).await?;
|
||||
buff.write_all(b"._domainkey.").await?;
|
||||
buff.write_all(sdid.as_bytes()).await?;
|
||||
buff.write_all(b"\n").await?;
|
||||
buff.flush().await?;
|
||||
sqlx::query(crate::db::UPDATE_PUBLISHED_KEY)
|
||||
.bind(&selector)
|
||||
.bind(&sdid)
|
||||
.bind(&algorithm)
|
||||
.execute(db)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
.await?;
|
||||
log::info!(
|
||||
"{algorithm} private key for {selector}._domainkey.{sdid} has been published"
|
||||
);
|
||||
|
@ -68,8 +66,7 @@ async fn publish_expired_keys(db: &SqlitePool, file_path: &Path) -> Result<Durat
|
|||
}
|
||||
let res: Option<(i64,)> = sqlx::query_as(crate::db::SELECT_NEAREST_KEY_PUBLICATION)
|
||||
.fetch_optional(db)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
.await?;
|
||||
match res {
|
||||
Some((next_pub_ts,)) => {
|
||||
let now_ts = OffsetDateTime::now_utc().unix_timestamp();
|
||||
|
@ -86,16 +83,15 @@ async fn renew_key_if_expired(
|
|||
domain: &str,
|
||||
algorithm: Algorithm,
|
||||
expiration: Duration,
|
||||
) -> Result<Duration, ()> {
|
||||
) -> Result<Duration> {
|
||||
let res: Option<(i64,)> = sqlx::query_as(crate::db::SELECT_LATEST_KEY)
|
||||
.bind(domain)
|
||||
.bind(algorithm.to_string())
|
||||
.fetch_optional(db)
|
||||
.await
|
||||
.map_err(|_| ())?;
|
||||
.await?;
|
||||
match res {
|
||||
Some((not_after,)) => {
|
||||
let not_after = OffsetDateTime::from_unix_timestamp(not_after).map_err(|_| ())?;
|
||||
let not_after = OffsetDateTime::from_unix_timestamp(not_after)?;
|
||||
log::debug!("{domain}: key is valid until {not_after}");
|
||||
if not_after - expiration <= OffsetDateTime::now_utc() {
|
||||
generate_key(db, cnf, domain, algorithm).await?;
|
||||
|
@ -114,7 +110,7 @@ async fn generate_key(
|
|||
cnf: &Config,
|
||||
domain: &str,
|
||||
algorithm: Algorithm,
|
||||
) -> Result<(), ()> {
|
||||
) -> Result<()> {
|
||||
let selector = format!("dkim-{}", Uuid::new_v4().simple());
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let not_after = now + Duration::from_secs(cnf.cryptoperiod().get());
|
||||
|
@ -130,8 +126,7 @@ async fn generate_key(
|
|||
.bind(priv_key)
|
||||
.bind(pub_key)
|
||||
.execute(db)
|
||||
.await
|
||||
.map_err(|_| ())?;
|
||||
.await?;
|
||||
// TODO: dns_update_cmd
|
||||
log::debug!("{domain}: new {} key generated", algorithm.to_string());
|
||||
Ok(())
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::config::Config;
|
||||
use crate::entry::Entry;
|
||||
use crate::parsed_message::ParsedMessage;
|
||||
use anyhow::Result;
|
||||
use tokio::io::{AsyncWriteExt, BufWriter};
|
||||
|
||||
pub const RETURN_SEP: &[u8] = b"|";
|
||||
|
@ -80,28 +81,32 @@ impl Message {
|
|||
log::error!("{}: unable to parse message", self.session_id);
|
||||
}
|
||||
}
|
||||
self.print_msg().await;
|
||||
if let Err(err) = self.print_msg().await {
|
||||
log::error!("unable to write message: {err}");
|
||||
}
|
||||
get_msg_id(&self.session_id, &self.token)
|
||||
}
|
||||
|
||||
async fn print_msg(&self) {
|
||||
async fn print_msg(&self) -> Result<()> {
|
||||
let i = self.content.len() - 1;
|
||||
for line in self.content[0..i].split(|&b| b == b'\n') {
|
||||
self.print_line(line).await;
|
||||
self.print_line(line).await?;
|
||||
}
|
||||
self.print_line(b".").await;
|
||||
self.print_line(b".").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn print_line(&self, line: &[u8]) {
|
||||
async fn print_line(&self, line: &[u8]) -> Result<()> {
|
||||
let mut stdout = BufWriter::new(tokio::io::stdout());
|
||||
stdout.write_all(RETURN_START).await.unwrap();
|
||||
stdout.write_all(self.session_id.as_bytes()).await.unwrap();
|
||||
stdout.write_all(RETURN_SEP).await.unwrap();
|
||||
stdout.write_all(self.token.as_bytes()).await.unwrap();
|
||||
stdout.write_all(RETURN_SEP).await.unwrap();
|
||||
stdout.write_all(line).await.unwrap();
|
||||
stdout.write_all(b"\n").await.unwrap();
|
||||
stdout.flush().await.unwrap();
|
||||
stdout.write_all(RETURN_START).await?;
|
||||
stdout.write_all(self.session_id.as_bytes()).await?;
|
||||
stdout.write_all(RETURN_SEP).await?;
|
||||
stdout.write_all(self.token.as_bytes()).await?;
|
||||
stdout.write_all(RETURN_SEP).await?;
|
||||
stdout.write_all(line).await?;
|
||||
stdout.write_all(b"\n").await?;
|
||||
stdout.flush().await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue