mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
List devices API working
This commit is contained in:
Generated
+1
@@ -1548,6 +1548,7 @@ dependencies = [
|
|||||||
"rusqlite",
|
"rusqlite",
|
||||||
"rusqlite_migration",
|
"rusqlite_migration",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio 1.49.0",
|
"tokio 1.49.0",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ log = "0.4.29"
|
|||||||
pnet = "0.35.0"
|
pnet = "0.35.0"
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
tokio = { version = "1.0", features = ["full"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
rusqlite = { version = "0.38.0", features = ["bundled", "chrono"] }
|
rusqlite = { version = "0.38.0", features = ["bundled", "chrono"] }
|
||||||
rusqlite_migration = { version = "2.4.1", features = ["from-directory"] }
|
rusqlite_migration = { version = "2.4.1", features = ["from-directory"] }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ mod mac_vendor_finder;
|
|||||||
mod model;
|
mod model;
|
||||||
mod scanner;
|
mod scanner;
|
||||||
mod settings;
|
mod settings;
|
||||||
|
mod utils;
|
||||||
mod web_server;
|
mod web_server;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use chrono::{DateTime, Utc, serde::ts_seconds};
|
use crate::utils::date_serializer;
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
@@ -7,7 +8,7 @@ pub struct Device {
|
|||||||
pub mac_address: String,
|
pub mac_address: String,
|
||||||
pub ipv4_address: String,
|
pub ipv4_address: String,
|
||||||
pub vendor: String,
|
pub vendor: String,
|
||||||
#[serde(with = "ts_seconds")]
|
#[serde(with = "date_serializer")]
|
||||||
pub last_seen: DateTime<Utc>,
|
pub last_seen: DateTime<Utc>,
|
||||||
pub is_registered: bool,
|
pub is_registered: bool,
|
||||||
pub owner: String,
|
pub owner: String,
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod date_serializer;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
|
||||||
|
|
||||||
|
fn time_to_json(t: DateTime<Utc>) -> String {
|
||||||
|
t.to_rfc3339()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serialize<S: Serializer>(
|
||||||
|
datetime: &DateTime<Utc>,
|
||||||
|
serializer: S,
|
||||||
|
) -> Result<S::Ok, S::Error> {
|
||||||
|
time_to_json(datetime.clone()).serialize(serializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<DateTime<Utc>, D::Error> {
|
||||||
|
let datetime: String = Deserialize::deserialize(deserializer)?;
|
||||||
|
Ok(DateTime::parse_from_str(&datetime, "%Y-%m-%d %H:%M:%S")
|
||||||
|
.map_err(D::Error::custom)?
|
||||||
|
.to_utc())
|
||||||
|
}
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
use std::error::Error;
|
use std::{collections::HashMap, error::Error};
|
||||||
|
|
||||||
use axum::{Json, Router, extract::Path, http::StatusCode, routing::get};
|
use axum::{
|
||||||
use log::{debug, error, info};
|
Json, Router,
|
||||||
|
extract::{Path, Query},
|
||||||
|
http::StatusCode,
|
||||||
|
routing::get,
|
||||||
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use log::{debug, error, info, warn};
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -15,7 +21,7 @@ pub async fn serve() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
let router = Router::new()
|
let router = Router::new()
|
||||||
.route("/", get(|| async { "hello" }))
|
.route("/", get(|| async { "hello" }))
|
||||||
.route("/api/devices", get(get_devices))
|
.route("/api/devices", get(list_devices))
|
||||||
.route("/api/notifications", get(list_notifications))
|
.route("/api/notifications", get(list_notifications))
|
||||||
.route("/api/notifications/{id}", get(read_notification))
|
.route("/api/notifications/{id}", get(read_notification))
|
||||||
.route(
|
.route(
|
||||||
@@ -33,8 +39,75 @@ pub async fn serve() -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_devices() -> Result<Json<Vec<Device>>, StatusCode> {
|
fn parse_parameter_bool(params: &HashMap<String, String>, name: &str) -> Option<bool> {
|
||||||
unimplemented!();
|
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::<bool>() {
|
||||||
|
Ok(value) => Some(value),
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_parameter_string(params: &HashMap<String, String>, name: &str) -> Option<String> {
|
||||||
|
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<String, String>, name: &str) -> Option<DateTime<Utc>> {
|
||||||
|
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<HashMap<String, String>>,
|
||||||
|
) -> Result<Json<Vec<Device>>, StatusCode> {
|
||||||
|
let is_registered: Option<bool> = parse_parameter_bool(¶ms, "is_registered");
|
||||||
|
let last_seen_from: Option<DateTime<Utc>> = parse_parameter_date(¶ms, "last_seen_from");
|
||||||
|
let last_seen_to: Option<DateTime<Utc>> = parse_parameter_date(¶ms, "last_seen_to");
|
||||||
|
let owner: Option<String> = parse_parameter_string(¶ms, "owner");
|
||||||
|
let device_type: Option<String> = parse_parameter_string(¶ms, "device_type");
|
||||||
|
let vendor: Option<String> = 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<i64>) -> Result<Json<Notification>, StatusCode> {
|
async fn read_notification(Path(id): Path<i64>) -> Result<Json<Notification>, StatusCode> {
|
||||||
|
|||||||
Reference in New Issue
Block a user