mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Refactored errors from String to custom error types
This commit is contained in:
+3
-3
@@ -10,7 +10,7 @@ use r2d2_sqlite::SqliteConnectionManager;
|
||||
use rusqlite_migration::Migrations;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::settings::get_settings;
|
||||
use crate::{db::error::DbError, settings::get_settings};
|
||||
|
||||
static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/database_migrations");
|
||||
static INITIALISED: Mutex<bool> = Mutex::const_new(false);
|
||||
@@ -40,7 +40,7 @@ pub fn get_db_connection() -> PooledConnection<SqliteConnectionManager> {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init_db() -> Result<(), String> {
|
||||
pub async fn init_db() -> Result<(), DbError> {
|
||||
let mut initialised = INITIALISED.lock().await;
|
||||
if *initialised {
|
||||
return Ok(());
|
||||
@@ -59,7 +59,7 @@ pub async fn init_db() -> Result<(), String> {
|
||||
}
|
||||
Err(error) => {
|
||||
error!("Error updating database: {error}");
|
||||
Err(format!("Error updating database: {error}"))
|
||||
Err(DbError::from(error))
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use log::{debug, error};
|
||||
use rusqlite::params;
|
||||
|
||||
use crate::{db, model::devices::Device};
|
||||
use crate::{
|
||||
db::{self, error::DbError},
|
||||
model::devices::Device,
|
||||
};
|
||||
|
||||
// Read device from its MAC address
|
||||
pub fn read(mac_address: String) -> Option<Device> {
|
||||
@@ -34,7 +37,7 @@ pub fn read(mac_address: String) -> Option<Device> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(device: Device) -> Result<(), String> {
|
||||
pub fn insert(device: Device) -> Result<(), DbError> {
|
||||
let conn = db::get_db_connection();
|
||||
|
||||
match conn.execute(
|
||||
@@ -46,12 +49,12 @@ pub fn insert(device: Device) -> Result<(), String> {
|
||||
},
|
||||
Err(error) => {
|
||||
error!("Error inserting device ({device}) into database: {error}");
|
||||
Err(format!("Error inserting device ({device}) into database: {error}").to_string())
|
||||
Err(DbError::from(error))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(device: Device) -> Result<(), String> {
|
||||
pub fn update(device: Device) -> Result<(), DbError> {
|
||||
let conn = db::get_db_connection();
|
||||
match conn.execute(
|
||||
"UPDATE devices SET ipv4_address=?1, vendor=?2, last_seen=?3 WHERE mac_address=?4",
|
||||
@@ -68,7 +71,7 @@ pub fn update(device: Device) -> Result<(), String> {
|
||||
}
|
||||
Err(error) => {
|
||||
error!("Error updating device ({device}) in database: {error}");
|
||||
Err(format!("Error updating device ({device}) in database: {error}").to_string())
|
||||
Err(DbError::from(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-4
@@ -2,13 +2,15 @@ use std::{error, fmt};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DbError {
|
||||
Parse(rusqlite::Error),
|
||||
ParseRusqlite(rusqlite::Error),
|
||||
ParseRusqliteMigration(rusqlite_migration::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for DbError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
DbError::Parse(..) => write!(f, "Database access error"),
|
||||
DbError::ParseRusqlite(..) => write!(f, "Database access error"),
|
||||
DbError::ParseRusqliteMigration(..) => write!(f, "Database migration error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,13 +18,19 @@ impl fmt::Display for DbError {
|
||||
impl error::Error for DbError {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match *self {
|
||||
DbError::Parse(ref e) => Some(e),
|
||||
DbError::ParseRusqlite(ref e) => Some(e),
|
||||
DbError::ParseRusqliteMigration(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<rusqlite::Error> for DbError {
|
||||
fn from(err: rusqlite::Error) -> DbError {
|
||||
DbError::Parse(err)
|
||||
DbError::ParseRusqlite(err)
|
||||
}
|
||||
}
|
||||
impl From<rusqlite_migration::Error> for DbError {
|
||||
fn from(err: rusqlite_migration::Error) -> DbError {
|
||||
DbError::ParseRusqliteMigration(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
pub mod arp;
|
||||
pub mod error;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
mod packet_send_receive;
|
||||
|
||||
use crate::device_finders::error::{
|
||||
DataChannelError, InvalidDeviceError, NoIPAddressError, NoMACAddressError,
|
||||
};
|
||||
use crate::model::devices::Device;
|
||||
use crate::settings::get_settings;
|
||||
use duration_string::DurationString;
|
||||
@@ -11,7 +14,7 @@ use pnet::{
|
||||
};
|
||||
use tokio::time::{Duration, timeout};
|
||||
|
||||
pub async fn find(interface: String) -> Result<Vec<Device>, String> {
|
||||
pub async fn find(interface: String) -> Result<Vec<Device>, Box<dyn std::error::Error>> {
|
||||
debug!("Looking up devices via ARP using interface {}", interface);
|
||||
|
||||
// Get the network device to use
|
||||
@@ -24,7 +27,7 @@ pub async fn find(interface: String) -> Result<Vec<Device>, String> {
|
||||
Some(value) => value.clone(),
|
||||
None => {
|
||||
error!("Interface ({interface}) not found or not active.");
|
||||
return Err(format!("Interface ({interface}) not found or not active.").to_string());
|
||||
return Err(InvalidDeviceError.into());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,9 +44,7 @@ pub async fn find(interface: String) -> Result<Vec<Device>, String> {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
error!("No IP address found for selected interface ({interface}).");
|
||||
return Err(
|
||||
format!("No IP address found for selected interface ({interface}).").to_string(),
|
||||
);
|
||||
return Err(NoIPAddressError.into());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,10 +53,7 @@ pub async fn find(interface: String) -> Result<Vec<Device>, String> {
|
||||
Some(mac) => mac,
|
||||
None => {
|
||||
error!("Could not get MAC address for selected interface ({interface}).");
|
||||
return Err(
|
||||
format!("Could not get MAC address for selected interface ({interface}).")
|
||||
.to_string(),
|
||||
);
|
||||
return Err(NoMACAddressError.into());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -68,7 +66,7 @@ pub async fn find(interface: String) -> Result<Vec<Device>, String> {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
error!("Could not create data channel: {error}");
|
||||
return Err(format!("Could not create data channel: {error}").to_string());
|
||||
return Err(DataChannelError.into());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -76,7 +74,7 @@ pub async fn find(interface: String) -> Result<Vec<Device>, String> {
|
||||
Channel::Ethernet(tx, rx) => (tx, rx),
|
||||
_ => {
|
||||
error!("Unsupported data channel type");
|
||||
return Err("Unsupported data channel type".to_string());
|
||||
return Err(DataChannelError.into());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
use std::{error, fmt};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InvalidDeviceError;
|
||||
|
||||
impl fmt::Display for InvalidDeviceError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Invalid network device")
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for InvalidDeviceError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NoIPAddressError;
|
||||
|
||||
impl fmt::Display for NoIPAddressError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "No IP address found for device")
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for NoIPAddressError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NoMACAddressError;
|
||||
|
||||
impl fmt::Display for NoMACAddressError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "No MAC address found for device")
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for NoMACAddressError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DataChannelError;
|
||||
|
||||
impl fmt::Display for DataChannelError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Error creating or using network data channel")
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for DataChannelError {}
|
||||
@@ -1,15 +1,16 @@
|
||||
mod error;
|
||||
mod pushover;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::model::devices::Device;
|
||||
use crate::settings::get_settings;
|
||||
use crate::{events::error::DeliveryError, model::devices::Device};
|
||||
use chrono::Local;
|
||||
use duration_string::DurationString;
|
||||
use log::{debug, info, warn};
|
||||
|
||||
// Private helper function to deliver messages
|
||||
fn send_message(body: String) -> Result<(), String> {
|
||||
fn send_message(body: String) -> Result<(), DeliveryError> {
|
||||
debug!("About to send notification ({body}).");
|
||||
|
||||
match get_settings().notifications.method.as_str() {
|
||||
@@ -25,12 +26,15 @@ fn send_message(body: String) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn trigger_new_device(device: Device) -> Result<(), String> {
|
||||
pub fn trigger_new_device(device: Device) -> Result<(), DeliveryError> {
|
||||
send_message(format!("New device found in your network: {device}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn trigger_existing_device(existing_device: Device, new_device: Device) -> Result<(), String> {
|
||||
pub fn trigger_existing_device(
|
||||
existing_device: Device,
|
||||
new_device: Device,
|
||||
) -> Result<(), DeliveryError> {
|
||||
// Notify if the device comes back online after not being seen for the configured period
|
||||
let elapsed_since_last_seen: Duration = (Local::now().to_utc() - existing_device.last_seen)
|
||||
.to_std()
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
use std::{error, fmt};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DeliveryError {
|
||||
ParsePushover(pushover::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for DeliveryError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
DeliveryError::ParsePushover(..) => {
|
||||
write!(f, "Error delivering notification via Pushover")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for DeliveryError {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match *self {
|
||||
DeliveryError::ParsePushover(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pushover::Error> for DeliveryError {
|
||||
fn from(err: pushover::Error) -> DeliveryError {
|
||||
DeliveryError::ParsePushover(err)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
use log::{debug, error};
|
||||
use pushover::API;
|
||||
use pushover::requests::message::SendMessage;
|
||||
use pushover::{API, Error};
|
||||
|
||||
use crate::settings::get_settings;
|
||||
|
||||
pub fn send_message(body: String) -> Result<(), String> {
|
||||
pub fn send_message(body: String) -> Result<(), Error> {
|
||||
debug!("About to send message via pushover ({body})");
|
||||
let api = API::new();
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn send_message(body: String) -> Result<(), String> {
|
||||
}
|
||||
Err(error) => {
|
||||
error!("Error sending message via pushover: {error}");
|
||||
Err(format!("Error sending message via pushover: {error}"))
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ struct Args {
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), String> {
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Parse command line parameters and init settings
|
||||
// this is not thread safe so it needs to run just once
|
||||
let args = Args::parse();
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::settings::get_settings;
|
||||
use log::{debug, info};
|
||||
use tokio::time::{Duration, sleep};
|
||||
|
||||
pub async fn scan() -> Result<(), String> {
|
||||
pub async fn scan() -> Result<(), Box<dyn std::error::Error>> {
|
||||
loop {
|
||||
// Find online devices via ARP
|
||||
let devices =
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::error::Error;
|
||||
|
||||
use axum::{Json, Router, http::StatusCode, routing::get};
|
||||
use chrono::Local;
|
||||
use log::{error, info};
|
||||
use log::{debug, error, info};
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
use crate::{
|
||||
@@ -8,7 +10,7 @@ use crate::{
|
||||
model::{devices::Device, notifications::Notification},
|
||||
};
|
||||
|
||||
pub async fn serve() -> Result<(), String> {
|
||||
pub async fn serve() -> Result<(), Box<dyn Error>> {
|
||||
info!("Starting web server");
|
||||
let static_files = ServeDir::new("./web");
|
||||
|
||||
@@ -17,10 +19,13 @@ pub async fn serve() -> Result<(), String> {
|
||||
.route("/devices", get(get_devices))
|
||||
.route("/notifications", get(list_notifications))
|
||||
.nest_service("/web", static_files);
|
||||
info!("Server running at http://0.0.0.0:3000");
|
||||
info!("Web server starting at http://0.0.0.0:3000");
|
||||
// Start the server
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||
axum::serve(listener, router).await.unwrap();
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
|
||||
|
||||
debug!("Web server bound to IP and port");
|
||||
|
||||
axum::serve(listener, router).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user