diff --git a/backend/src/db/devices.rs b/backend/src/db/devices.rs index fbd7d09..b603fa0 100644 --- a/backend/src/db/devices.rs +++ b/backend/src/db/devices.rs @@ -1,6 +1,6 @@ use chrono::{DateTime, Utc}; use log::{debug, error}; -use rusqlite::{ToSql, params, params_from_iter}; +use rusqlite::{params, params_from_iter}; use crate::{ db::{self, error::DbError}, diff --git a/backend/src/web_server.rs b/backend/src/web_server.rs index d8947dc..6a875df 100644 --- a/backend/src/web_server.rs +++ b/backend/src/web_server.rs @@ -1,21 +1,12 @@ -use std::{collections::HashMap, error::Error}; +use std::error::Error; -use axum::{ - Json, Router, - extract::{Path, Query}, - http::StatusCode, - routing::get, -}; -use chrono::{DateTime, Utc}; -use log::{debug, error, info, warn}; +use axum::{Router, routing::get}; +use log::{debug, info}; use tower_http::services::ServeDir; -use crate::{ - db, - model::{devices::Device, notifications::Notification}, -}; - -// TODO: Split into modules by object and utils +pub mod devices; +pub mod notifications; +pub mod utils; pub async fn serve() -> Result<(), Box> { info!("Starting web server"); @@ -23,12 +14,15 @@ pub async fn serve() -> Result<(), Box> { let router = Router::new() .route("/", get(|| async { "hello" })) - .route("/api/devices", get(list_devices)) - .route("/api/notifications", get(list_notifications)) - .route("/api/notifications/{id}", get(read_notification)) + .route("/api/devices", get(devices::list_devices)) + .route("/api/notifications", get(notifications::list_notifications)) + .route( + "/api/notifications/{id}", + get(notifications::read_notification), + ) .route( "/api/notifications/{id}/read_without_flagging", - get(read_notification_without_flagging), + get(notifications::read_notification_without_flagging), ) .nest_service("/web", static_files); info!("Web server starting at http://0.0.0.0:3000"); @@ -40,108 +34,3 @@ pub async fn serve() -> Result<(), Box> { axum::serve(listener, router).await?; Ok(()) } - -fn parse_parameter_bool(params: &HashMap, name: &str) -> Option { - if params.contains_key(name) { - let param_value = params.get(name).unwrap().as_str(); - debug!("Found parameter {name} with value {}", param_value); - match param_value.parse::() { - Ok(value) => Some(value), - Err(_) => None, - } - } else { - None - } -} - -fn parse_parameter_string(params: &HashMap, name: &str) -> Option { - if params.contains_key(name) { - let param_value = params.get(name).unwrap().as_str(); - debug!("Found parameter {name} with value {}", param_value); - Some(param_value.to_string()) - } else { - None - } -} - -fn parse_parameter_date(params: &HashMap, name: &str) -> Option> { - if params.contains_key(name) { - let mut param_value = params.get(name).unwrap().to_ascii_uppercase(); - if !param_value.ends_with("Z") { - param_value.push('Z'); - } - debug!("Found parameter {name} with value {}", param_value); - match DateTime::parse_from_rfc3339(param_value.as_str()) { - Ok(value) => { - debug!("Date parsed to {}", value.to_utc().to_rfc3339()); - Some(value.to_utc()) - } - Err(err) => { - warn!("Error parsing date from parameters: {}", err); - None - } - } - } else { - None - } -} - -async fn list_devices( - Query(params): Query>, -) -> Result>, StatusCode> { - let is_registered: Option = parse_parameter_bool(¶ms, "is_registered"); - let last_seen_from: Option> = parse_parameter_date(¶ms, "last_seen_from"); - let last_seen_to: Option> = parse_parameter_date(¶ms, "last_seen_to"); - let owner: Option = parse_parameter_string(¶ms, "owner"); - let device_type: Option = parse_parameter_string(¶ms, "device_type"); - let vendor: Option = parse_parameter_string(¶ms, "vendor"); - - match db::devices::list_devices( - is_registered, - last_seen_from, - last_seen_to, - owner, - device_type, - vendor, - ) { - Ok(value) => Ok(Json(value)), - Err(err) => { - error!("Error listing devices: {}", err); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } - } -} - -async fn read_notification(Path(id): Path) -> Result, StatusCode> { - match db::notifications::mark_as_old(id) { - Ok(_) => {} - Err(err) => { - error!("Error marking notification (id={id}) as old: {}", err); - return Err(StatusCode::INTERNAL_SERVER_ERROR); - } - }; - - match db::notifications::read(id) { - Some(value) => Ok(Json(value)), - None => Err(StatusCode::NOT_FOUND), - } -} - -async fn read_notification_without_flagging( - Path(id): Path, -) -> Result, StatusCode> { - match db::notifications::read(id) { - Some(value) => Ok(Json(value)), - None => Err(StatusCode::NOT_FOUND), - } -} - -async fn list_notifications() -> Result>, StatusCode> { - match db::notifications::list() { - Ok(value) => Ok(Json(value)), - Err(err) => { - error!("Error listing notifications: {}", err); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } - } -} diff --git a/backend/src/web_server/devices.rs b/backend/src/web_server/devices.rs new file mode 100644 index 0000000..375b407 --- /dev/null +++ b/backend/src/web_server/devices.rs @@ -0,0 +1,36 @@ +use std::collections::HashMap; + +use axum::{Json, extract::Query, http::StatusCode}; +use chrono::{DateTime, Utc}; +use log::error; + +use crate::{db, model::devices::Device}; + +use crate::web_server::utils; + +pub async fn list_devices( + Query(params): Query>, +) -> Result>, StatusCode> { + let is_registered: Option = utils::parse_parameter_bool(¶ms, "is_registered"); + let last_seen_from: Option> = + utils::parse_parameter_date(¶ms, "last_seen_from"); + let last_seen_to: Option> = utils::parse_parameter_date(¶ms, "last_seen_to"); + let owner: Option = utils::parse_parameter_string(¶ms, "owner"); + let device_type: Option = utils::parse_parameter_string(¶ms, "device_type"); + let vendor: Option = utils::parse_parameter_string(¶ms, "vendor"); + + match db::devices::list_devices( + is_registered, + last_seen_from, + last_seen_to, + owner, + device_type, + vendor, + ) { + Ok(value) => Ok(Json(value)), + Err(err) => { + error!("Error listing devices: {}", err); + Err(StatusCode::INTERNAL_SERVER_ERROR) + } + } +} diff --git a/backend/src/web_server/notifications.rs b/backend/src/web_server/notifications.rs new file mode 100644 index 0000000..f29dd2a --- /dev/null +++ b/backend/src/web_server/notifications.rs @@ -0,0 +1,38 @@ +use axum::{Json, extract::Path, http::StatusCode}; +use log::error; + +use crate::{db, model::notifications::Notification}; + +pub async fn read_notification(Path(id): Path) -> Result, StatusCode> { + match db::notifications::mark_as_old(id) { + Ok(_) => {} + Err(err) => { + error!("Error marking notification (id={id}) as old: {}", err); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + } + }; + + match db::notifications::read(id) { + Some(value) => Ok(Json(value)), + None => Err(StatusCode::NOT_FOUND), + } +} + +pub async fn read_notification_without_flagging( + Path(id): Path, +) -> Result, StatusCode> { + match db::notifications::read(id) { + Some(value) => Ok(Json(value)), + None => Err(StatusCode::NOT_FOUND), + } +} + +pub async fn list_notifications() -> Result>, StatusCode> { + match db::notifications::list() { + Ok(value) => Ok(Json(value)), + Err(err) => { + error!("Error listing notifications: {}", err); + Err(StatusCode::INTERNAL_SERVER_ERROR) + } + } +} diff --git a/backend/src/web_server/utils.rs b/backend/src/web_server/utils.rs new file mode 100644 index 0000000..56d1211 --- /dev/null +++ b/backend/src/web_server/utils.rs @@ -0,0 +1,49 @@ +use std::collections::HashMap; + +use chrono::{DateTime, Utc}; +use log::{debug, warn}; + +pub fn parse_parameter_bool(params: &HashMap, name: &str) -> Option { + if params.contains_key(name) { + let param_value = params.get(name).unwrap().as_str(); + debug!("Found parameter {name} with value {}", param_value); + match param_value.parse::() { + Ok(value) => Some(value), + Err(_) => None, + } + } else { + None + } +} + +pub fn parse_parameter_string(params: &HashMap, name: &str) -> Option { + if params.contains_key(name) { + let param_value = params.get(name).unwrap().as_str(); + debug!("Found parameter {name} with value {}", param_value); + Some(param_value.to_string()) + } else { + None + } +} + +pub fn parse_parameter_date(params: &HashMap, name: &str) -> Option> { + if params.contains_key(name) { + let mut param_value = params.get(name).unwrap().to_ascii_uppercase(); + if !param_value.ends_with("Z") { + param_value.push('Z'); + } + debug!("Found parameter {name} with value {}", param_value); + match DateTime::parse_from_rfc3339(param_value.as_str()) { + Ok(value) => { + debug!("Date parsed to {}", value.to_utc().to_rfc3339()); + Some(value.to_utc()) + } + Err(err) => { + warn!("Error parsing date from parameters: {}", err); + None + } + } + } else { + None + } +}