From 97fae5425246b46a985d5b847a0c2a22ed02a21c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolphe=20Br=C3=A9ard?= Date: Mon, 10 Apr 2023 13:09:56 +0200 Subject: [PATCH] Use anyhow for error handling --- Cargo.toml | 1 + src/action.rs | 2 +- src/db.rs | 7 ++----- src/entry.rs | 8 +------- src/key.rs | 45 ++++++++++++++++++++------------------------- src/message.rs | 31 ++++++++++++++++++------------- 6 files changed, 43 insertions(+), 51 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3814307..8847555 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } diff --git a/src/action.rs b/src/action.rs index fbf44a4..3e141bb 100644 --- a/src/action.rs +++ b/src/action.rs @@ -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, }, diff --git a/src/db.rs b/src/db.rs index e2aa766..4c19fee 100644 --- a/src/db.rs +++ b/src/db.rs @@ -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 { - do_init(cnf).await.map_err(|e| e.to_string()) -} - -async fn do_init(cnf: &Config) -> Result { +pub async fn init(cnf: &Config) -> Result { let mut db_options = SqliteConnectOptions::new() .filename(cnf.key_data_base()) .create_if_missing(true); diff --git a/src/entry.rs b/src/entry.rs index efd4b19..d117e06 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -44,13 +44,7 @@ pub async fn read_entry(reader_lock: Arc>) -> Option 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 { diff --git a/src/key.rs b/src/key.rs index d6424c5..0ce095e 100644 --- a/src/key.rs +++ b/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 { +async fn publish_expired_keys(db: &SqlitePool, file_path: &Path) -> Result { 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 = 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 { +) -> Result { 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(()) diff --git a/src/message.rs b/src/message.rs index bb31d32..b936283 100644 --- a/src/message.rs +++ b/src/message.rs @@ -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(()) } }