Feature Flags and shit codex did idfk
This commit is contained in:
+145
@@ -0,0 +1,145 @@
|
||||
use serde::Serialize;
|
||||
use wakey_core::parse::mac;
|
||||
use wakey_core::{
|
||||
DeviceFilters, DhcpLeaseWithState, NeighborEntry, Status, WakeResult, WakeTargetResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct LegacyStatusRow {
|
||||
pub ip: std::net::IpAddr,
|
||||
pub dev: Option<String>,
|
||||
#[serde(with = "mac::option_mac")]
|
||||
pub mac: Option<macaddr::MacAddr>,
|
||||
pub state: wakey_core::NeighborState,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct LegacyStatusResponse {
|
||||
pub name: Option<String>,
|
||||
pub table: Vec<LegacyStatusRow>,
|
||||
pub filters: DeviceFilters,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct LegacyLeaseRow {
|
||||
pub expires_epoch: u64,
|
||||
pub ip: std::net::IpAddr,
|
||||
#[serde(with = "mac")]
|
||||
pub mac: macaddr::MacAddr,
|
||||
pub name: Option<String>,
|
||||
pub nud_state: Option<wakey_core::NeighborState>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct LegacyWakeResult {
|
||||
pub result: Vec<LegacyWakeResultRow>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize)]
|
||||
pub struct LegacyWakeResultRow {
|
||||
#[serde(flatten)]
|
||||
pub target: wakey_core::WakeTarget,
|
||||
pub status: wakey_core::WakeStatus,
|
||||
}
|
||||
|
||||
pub fn legacy_status_from_domain(status: Status<NeighborEntry>) -> LegacyStatusResponse {
|
||||
LegacyStatusResponse {
|
||||
name: status.name,
|
||||
table: status.table.into_iter().map(legacy_status_row).collect(),
|
||||
filters: status.filters,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn legacy_status_row(row: NeighborEntry) -> LegacyStatusRow {
|
||||
LegacyStatusRow {
|
||||
ip: row.ip,
|
||||
dev: row.dev,
|
||||
mac: row.mac,
|
||||
state: row.state,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn legacy_leases_from_domain(leases: Vec<DhcpLeaseWithState>) -> Vec<LegacyLeaseRow> {
|
||||
leases.into_iter().map(legacy_lease_row).collect()
|
||||
}
|
||||
|
||||
pub fn legacy_lease_row(lease: DhcpLeaseWithState) -> LegacyLeaseRow {
|
||||
LegacyLeaseRow {
|
||||
expires_epoch: lease.lease_line.expires_epoch,
|
||||
ip: lease.lease_line.ip,
|
||||
mac: lease.lease_line.mac,
|
||||
name: lease.lease_line.name,
|
||||
nud_state: lease.nud_state,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn legacy_wake_from_domain(result: WakeResult) -> LegacyWakeResult {
|
||||
LegacyWakeResult {
|
||||
result: result.result.into_iter().map(legacy_wake_row).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn legacy_wake_row(row: WakeTargetResult) -> LegacyWakeResultRow {
|
||||
LegacyWakeResultRow {
|
||||
target: row.target,
|
||||
status: row.status,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use wakey_core::{DhcpLease, NeighborState, WakeStatus, WakeTarget};
|
||||
|
||||
#[test]
|
||||
fn maps_status_to_legacy_shape() {
|
||||
let status = Status {
|
||||
name: Some("pc".into()),
|
||||
table: vec![NeighborEntry {
|
||||
ip: IpAddr::V4(Ipv4Addr::new(192, 168, 1, 10)),
|
||||
dev: Some("br-lan".into()),
|
||||
mac: Some("aa:bb:cc:dd:ee:ff".parse().expect("mac")),
|
||||
state: NeighborState::Reachable,
|
||||
}],
|
||||
filters: DeviceFilters::default(),
|
||||
};
|
||||
let legacy = legacy_status_from_domain(status);
|
||||
assert_eq!(legacy.name.as_deref(), Some("pc"));
|
||||
assert_eq!(legacy.table.len(), 1);
|
||||
assert_eq!(legacy.table[0].state, NeighborState::Reachable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maps_leases_to_legacy_shape() {
|
||||
let leases = vec![DhcpLeaseWithState {
|
||||
lease_line: DhcpLease {
|
||||
expires_epoch: 42,
|
||||
ip: IpAddr::V4(Ipv4Addr::LOCALHOST),
|
||||
mac: "aa:bb:cc:dd:ee:ff".parse().expect("mac"),
|
||||
name: Some("pc".into()),
|
||||
},
|
||||
nud_state: Some(NeighborState::Reachable),
|
||||
}];
|
||||
let legacy = legacy_leases_from_domain(leases);
|
||||
assert_eq!(legacy.len(), 1);
|
||||
assert_eq!(legacy[0].name.as_deref(), Some("pc"));
|
||||
assert_eq!(legacy[0].nud_state, Some(NeighborState::Reachable));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn maps_wake_to_legacy_shape() {
|
||||
let result = WakeResult {
|
||||
result: vec![WakeTargetResult {
|
||||
target: WakeTarget {
|
||||
ip: Some(IpAddr::V4(Ipv4Addr::LOCALHOST)),
|
||||
mac: Some("aa:bb:cc:dd:ee:ff".parse().expect("mac")),
|
||||
},
|
||||
status: WakeStatus::Succeed,
|
||||
}],
|
||||
};
|
||||
let legacy = legacy_wake_from_domain(result);
|
||||
assert_eq!(legacy.result.len(), 1);
|
||||
assert_eq!(legacy.result[0].status, WakeStatus::Succeed);
|
||||
}
|
||||
}
|
||||
+40
-36
@@ -1,4 +1,5 @@
|
||||
pub mod arpparse;
|
||||
pub mod compat;
|
||||
pub mod dhcpparse;
|
||||
pub mod route;
|
||||
pub mod utils;
|
||||
@@ -17,40 +18,42 @@ use wakey_core::{
|
||||
pub type StatusResponse = Status<NeighborEntry>;
|
||||
|
||||
pub async fn resolve_query(input: impl Into<String>) -> Result<DeviceQuery> {
|
||||
Ok(match wakey_linux::devices::classify_query(input.into()).await {
|
||||
QueryInput::Ip(ip_addr) => DeviceQuery {
|
||||
filter: DeviceFilters {
|
||||
ips: vec![ip_addr],
|
||||
Ok(
|
||||
match wakey_linux::devices::classify_query(input.into()).await {
|
||||
QueryInput::Ip(ip_addr) => DeviceQuery {
|
||||
filter: DeviceFilters {
|
||||
ips: vec![ip_addr],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
QueryInput::Mac(mac_addr) => DeviceQuery {
|
||||
filter: DeviceFilters {
|
||||
macs: vec![mac_addr],
|
||||
QueryInput::Mac(mac_addr) => DeviceQuery {
|
||||
filter: DeviceFilters {
|
||||
macs: vec![mac_addr],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
QueryInput::Dev(dev) => DeviceQuery {
|
||||
filter: DeviceFilters {
|
||||
devs: vec![dev],
|
||||
QueryInput::Dev(dev) => DeviceQuery {
|
||||
filter: DeviceFilters {
|
||||
devs: vec![dev],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
QueryInput::Nud(state) => DeviceQuery {
|
||||
filter: DeviceFilters {
|
||||
nuds: vec![state],
|
||||
QueryInput::Nud(state) => DeviceQuery {
|
||||
filter: DeviceFilters {
|
||||
nuds: vec![state],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
QueryInput::Name(name) => DeviceQuery {
|
||||
name: Some(name),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
QueryInput::Name(name) => DeviceQuery {
|
||||
name: Some(name),
|
||||
..Default::default()
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn get_status(query: DeviceQuery) -> Result<StatusResponse> {
|
||||
@@ -117,16 +120,14 @@ pub async fn get_ips(name: impl AsRef<str>) -> Result<Vec<std::net::IpAddr>> {
|
||||
pub fn http_app(static_root: std::path::PathBuf) -> Router {
|
||||
Router::new()
|
||||
.nest("/api", route::api_router())
|
||||
.fallback_service(
|
||||
axum::routing::get_service(
|
||||
ServeDir::new(static_root)
|
||||
.append_index_html_on_directories(true)
|
||||
.precompressed_br()
|
||||
.precompressed_deflate()
|
||||
.precompressed_gzip()
|
||||
.precompressed_zstd(),
|
||||
),
|
||||
)
|
||||
.fallback_service(axum::routing::get_service(
|
||||
ServeDir::new(static_root)
|
||||
.append_index_html_on_directories(true)
|
||||
.precompressed_br()
|
||||
.precompressed_deflate()
|
||||
.precompressed_gzip()
|
||||
.precompressed_zstd(),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn serve_http(addr: SocketAddr, static_root: std::path::PathBuf) -> io::Result<()> {
|
||||
@@ -161,7 +162,10 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn resolve_query_parses_ip() {
|
||||
let query = resolve_query("192.168.1.10").await.expect("resolve query");
|
||||
assert_eq!(query.filter.ips, vec![IpAddr::V4(Ipv4Addr::new(192, 168, 1, 10))]);
|
||||
assert_eq!(
|
||||
query.filter.ips,
|
||||
vec![IpAddr::V4(Ipv4Addr::new(192, 168, 1, 10))]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
+5
-1
@@ -13,7 +13,11 @@ pub async fn get_dhcp_leases(
|
||||
let include_state = include_state.as_deref().map(boolish_str).unwrap_or(false);
|
||||
|
||||
match crate::get_leases(include_state).await {
|
||||
Ok(leases) => (StatusCode::OK, Json(leases)).into_response(),
|
||||
Ok(leases) => (
|
||||
StatusCode::OK,
|
||||
Json(crate::compat::legacy_leases_from_domain(leases)),
|
||||
)
|
||||
.into_response(),
|
||||
Err(e) => ApiError {
|
||||
error: e.to_string(),
|
||||
code: StatusCode::BAD_GATEWAY,
|
||||
|
||||
+6
-2
@@ -1,11 +1,15 @@
|
||||
use crate::route::error::ApiError;
|
||||
use axum::{Json, http::StatusCode, response::IntoResponse};
|
||||
use axum_extra::extract::Query;
|
||||
pub use wakey_core::{DeviceQuery, NamePath, Status};
|
||||
pub use wakey_core::{DeviceQuery, NamePath};
|
||||
|
||||
pub async fn get_status_json(Query(query): Query<DeviceQuery>) -> impl IntoResponse {
|
||||
match crate::get_status(query).await {
|
||||
Ok(status) => (StatusCode::OK, Json(status)).into_response(),
|
||||
Ok(status) => (
|
||||
StatusCode::OK,
|
||||
Json(crate::compat::legacy_status_from_domain(status)),
|
||||
)
|
||||
.into_response(),
|
||||
Err(error) => ApiError {
|
||||
code: StatusCode::BAD_GATEWAY,
|
||||
error: error
|
||||
|
||||
+6
-2
@@ -1,10 +1,14 @@
|
||||
use crate::route::error::ApiError;
|
||||
use axum::{extract::Json, http::StatusCode, response::IntoResponse};
|
||||
pub use wakey_core::{WakeResult, WakeTarget};
|
||||
pub use wakey_core::WakeTarget;
|
||||
|
||||
pub async fn wake_multi(Json(req): Json<Vec<WakeTarget>>) -> impl IntoResponse {
|
||||
match crate::wake_targets(req).await {
|
||||
Ok(result) => (StatusCode::OK, Json(result)).into_response(),
|
||||
Ok(result) => (
|
||||
StatusCode::OK,
|
||||
Json(crate::compat::legacy_wake_from_domain(result)),
|
||||
)
|
||||
.into_response(),
|
||||
Err(error) => {
|
||||
let error = format!("Error: {}", error);
|
||||
ApiError::ise(error).into_response()
|
||||
|
||||
Reference in New Issue
Block a user