diff options
Diffstat (limited to 'src/routes')
-rw-r--r-- | src/routes/device.rs | 34 | ||||
-rw-r--r-- | src/routes/mod.rs | 3 | ||||
-rw-r--r-- | src/routes/start.rs | 39 | ||||
-rw-r--r-- | src/routes/status.rs | 10 |
4 files changed, 60 insertions, 26 deletions
diff --git a/src/routes/device.rs b/src/routes/device.rs index 025c7d0..1eeff0b 100644 --- a/src/routes/device.rs +++ b/src/routes/device.rs | |||
@@ -4,24 +4,26 @@ use axum::headers::HeaderMap; | |||
4 | use axum::Json; | 4 | use axum::Json; |
5 | use serde::{Deserialize, Serialize}; | 5 | use serde::{Deserialize, Serialize}; |
6 | use serde_json::{json, Value}; | 6 | use serde_json::{json, Value}; |
7 | use tracing::info; | 7 | use tracing::{debug, info}; |
8 | use crate::auth::auth; | 8 | use crate::auth::auth; |
9 | use crate::db::Device; | 9 | use crate::db::Device; |
10 | use crate::error::WebolError; | 10 | use crate::error::WebolError; |
11 | 11 | ||
12 | pub async fn get_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<GetDevicePayload>) -> Result<Json<Value>, WebolError> { | 12 | pub async fn get_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<GetDevicePayload>) -> Result<Json<Value>, WebolError> { |
13 | info!("GET request"); | 13 | info!("add device {}", payload.id); |
14 | let secret = headers.get("authorization"); | 14 | let secret = headers.get("authorization"); |
15 | if auth(secret).map_err(WebolError::Auth)? { | 15 | if auth(secret).map_err(WebolError::Auth)? { |
16 | let device = sqlx::query_as!( | 16 | let device = sqlx::query_as!( |
17 | Device, | 17 | Device, |
18 | r#" | 18 | r#" |
19 | SELECT id, mac, broadcast_addr | 19 | SELECT id, mac, broadcast_addr, ip |
20 | FROM devices | 20 | FROM devices |
21 | WHERE id = $1; | 21 | WHERE id = $1; |
22 | "#, | 22 | "#, |
23 | payload.id | 23 | payload.id |
24 | ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?; | 24 | ).fetch_one(&state.db).await.map_err(WebolError::DB)?; |
25 | |||
26 | debug!("got device {:?}", device); | ||
25 | 27 | ||
26 | Ok(Json(json!(device))) | 28 | Ok(Json(json!(device))) |
27 | } else { | 29 | } else { |
@@ -35,18 +37,19 @@ pub struct GetDevicePayload { | |||
35 | } | 37 | } |
36 | 38 | ||
37 | pub async fn put_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PutDevicePayload>) -> Result<Json<Value>, WebolError> { | 39 | pub async fn put_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PutDevicePayload>) -> Result<Json<Value>, WebolError> { |
38 | info!("PUT request"); | 40 | info!("add device {} ({}, {}, {})", payload.id, payload.mac, payload.broadcast_addr, payload.ip); |
39 | let secret = headers.get("authorization"); | 41 | let secret = headers.get("authorization"); |
40 | if auth(secret).map_err(WebolError::Auth)? { | 42 | if auth(secret).map_err(WebolError::Auth)? { |
41 | sqlx::query!( | 43 | sqlx::query!( |
42 | r#" | 44 | r#" |
43 | INSERT INTO devices (id, mac, broadcast_addr) | 45 | INSERT INTO devices (id, mac, broadcast_addr, ip) |
44 | VALUES ($1, $2, $3); | 46 | VALUES ($1, $2, $3, $4); |
45 | "#, | 47 | "#, |
46 | payload.id, | 48 | payload.id, |
47 | payload.mac, | 49 | payload.mac, |
48 | payload.broadcast_addr | 50 | payload.broadcast_addr, |
49 | ).execute(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?; | 51 | payload.ip |
52 | ).execute(&state.db).await.map_err(WebolError::DB)?; | ||
50 | 53 | ||
51 | Ok(Json(json!(PutDeviceResponse { success: true }))) | 54 | Ok(Json(json!(PutDeviceResponse { success: true }))) |
52 | } else { | 55 | } else { |
@@ -59,6 +62,7 @@ pub struct PutDevicePayload { | |||
59 | id: String, | 62 | id: String, |
60 | mac: String, | 63 | mac: String, |
61 | broadcast_addr: String, | 64 | broadcast_addr: String, |
65 | ip: String | ||
62 | } | 66 | } |
63 | 67 | ||
64 | #[derive(Serialize)] | 68 | #[derive(Serialize)] |
@@ -67,20 +71,21 @@ pub struct PutDeviceResponse { | |||
67 | } | 71 | } |
68 | 72 | ||
69 | pub async fn post_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PostDevicePayload>) -> Result<Json<Value>, WebolError> { | 73 | pub async fn post_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PostDevicePayload>) -> Result<Json<Value>, WebolError> { |
70 | info!("POST request"); | 74 | info!("edit device {} ({}, {}, {})", payload.id, payload.mac, payload.broadcast_addr, payload.ip); |
71 | let secret = headers.get("authorization"); | 75 | let secret = headers.get("authorization"); |
72 | if auth(secret).map_err(WebolError::Auth)? { | 76 | if auth(secret).map_err(WebolError::Auth)? { |
73 | let device = sqlx::query_as!( | 77 | let device = sqlx::query_as!( |
74 | Device, | 78 | Device, |
75 | r#" | 79 | r#" |
76 | UPDATE devices | 80 | UPDATE devices |
77 | SET mac = $1, broadcast_addr = $2 WHERE id = $3 | 81 | SET mac = $1, broadcast_addr = $2, ip = $3 WHERE id = $4 |
78 | RETURNING id, mac, broadcast_addr; | 82 | RETURNING id, mac, broadcast_addr, ip; |
79 | "#, | 83 | "#, |
80 | payload.mac, | 84 | payload.mac, |
81 | payload.broadcast_addr, | 85 | payload.broadcast_addr, |
86 | payload.ip, | ||
82 | payload.id | 87 | payload.id |
83 | ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?; | 88 | ).fetch_one(&state.db).await.map_err(WebolError::DB)?; |
84 | 89 | ||
85 | Ok(Json(json!(device))) | 90 | Ok(Json(json!(device))) |
86 | } else { | 91 | } else { |
@@ -93,4 +98,5 @@ pub struct PostDevicePayload { | |||
93 | id: String, | 98 | id: String, |
94 | mac: String, | 99 | mac: String, |
95 | broadcast_addr: String, | 100 | broadcast_addr: String, |
96 | } \ No newline at end of file | 101 | ip: String, |
102 | } | ||
diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 12fbfab..d5ab0d6 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs | |||
@@ -1,2 +1,3 @@ | |||
1 | pub mod start; | 1 | pub mod start; |
2 | pub mod device; \ No newline at end of file | 2 | pub mod device; |
3 | pub mod status; \ No newline at end of file | ||
diff --git a/src/routes/start.rs b/src/routes/start.rs index 163d58c..271f924 100644 --- a/src/routes/start.rs +++ b/src/routes/start.rs | |||
@@ -4,26 +4,30 @@ use serde::{Deserialize, Serialize}; | |||
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | use axum::extract::State; | 5 | use axum::extract::State; |
6 | use serde_json::{json, Value}; | 6 | use serde_json::{json, Value}; |
7 | use tracing::info; | 7 | use tracing::{debug, info}; |
8 | use uuid::Uuid; | ||
8 | use crate::auth::auth; | 9 | use crate::auth::auth; |
9 | use crate::config::SETTINGS; | 10 | use crate::config::SETTINGS; |
10 | use crate::wol::{create_buffer, send_packet}; | 11 | use crate::wol::{create_buffer, send_packet}; |
11 | use crate::db::Device; | 12 | use crate::db::Device; |
12 | use crate::error::WebolError; | 13 | use crate::error::WebolError; |
14 | use crate::services::ping::PingValue; | ||
13 | 15 | ||
16 | #[axum_macros::debug_handler] | ||
14 | pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<StartPayload>) -> Result<Json<Value>, WebolError> { | 17 | pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<StartPayload>) -> Result<Json<Value>, WebolError> { |
15 | info!("POST request"); | 18 | info!("POST request"); |
16 | let secret = headers.get("authorization"); | 19 | let secret = headers.get("authorization"); |
17 | if auth(secret).map_err(WebolError::Auth)? { | 20 | let authorized = auth(secret).map_err(WebolError::Auth)?; |
21 | if authorized { | ||
18 | let device = sqlx::query_as!( | 22 | let device = sqlx::query_as!( |
19 | Device, | 23 | Device, |
20 | r#" | 24 | r#" |
21 | SELECT id, mac, broadcast_addr | 25 | SELECT id, mac, broadcast_addr, ip |
22 | FROM devices | 26 | FROM devices |
23 | WHERE id = $1; | 27 | WHERE id = $1; |
24 | "#, | 28 | "#, |
25 | payload.id | 29 | payload.id |
26 | ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?; | 30 | ).fetch_one(&state.db).await.map_err(WebolError::DB)?; |
27 | 31 | ||
28 | info!("starting {}", device.id); | 32 | info!("starting {}", device.id); |
29 | 33 | ||
@@ -32,11 +36,23 @@ pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap | |||
32 | .unwrap_or("0.0.0.0:1111".to_string()); | 36 | .unwrap_or("0.0.0.0:1111".to_string()); |
33 | 37 | ||
34 | let _ = send_packet( | 38 | let _ = send_packet( |
35 | &bind_addr.parse().map_err(|err| WebolError::Server(Box::new(err)))?, | 39 | &bind_addr.parse().map_err(WebolError::IpParse)?, |
36 | &device.broadcast_addr.parse().map_err(|err| WebolError::Server(Box::new(err)))?, | 40 | &device.broadcast_addr.parse().map_err(WebolError::IpParse)?, |
37 | create_buffer(&device.mac).map_err(|err| WebolError::Server(Box::new(err)))? | 41 | create_buffer(&device.mac)? |
38 | ).map_err(|err| WebolError::Server(Box::new(err))); | 42 | )?; |
39 | Ok(Json(json!(StartResponse { id: device.id, boot: true }))) | 43 | |
44 | let uuid = if payload.ping.is_some_and(|ping| ping) { | ||
45 | let uuid_gen = Uuid::new_v4().to_string(); | ||
46 | let uuid_genc = uuid_gen.clone(); | ||
47 | tokio::spawn(async move { | ||
48 | debug!("init ping service"); | ||
49 | state.ping_map.insert(uuid_gen.clone(), PingValue { ip: device.ip.clone(), online: false }); | ||
50 | |||
51 | crate::services::ping::spawn(state.ping_send.clone(), device.ip, uuid_gen.clone(), &state.ping_map).await | ||
52 | }); | ||
53 | Some(uuid_genc) | ||
54 | } else { None }; | ||
55 | Ok(Json(json!(StartResponse { id: device.id, boot: true, uuid }))) | ||
40 | } else { | 56 | } else { |
41 | Err(WebolError::Generic) | 57 | Err(WebolError::Generic) |
42 | } | 58 | } |
@@ -45,11 +61,12 @@ pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap | |||
45 | #[derive(Deserialize)] | 61 | #[derive(Deserialize)] |
46 | pub struct StartPayload { | 62 | pub struct StartPayload { |
47 | id: String, | 63 | id: String, |
48 | _test: Option<bool>, | 64 | ping: Option<bool>, |
49 | } | 65 | } |
50 | 66 | ||
51 | #[derive(Serialize)] | 67 | #[derive(Serialize)] |
52 | struct StartResponse { | 68 | struct StartResponse { |
53 | id: String, | 69 | id: String, |
54 | boot: bool, | 70 | boot: bool, |
55 | } \ No newline at end of file | 71 | uuid: Option<String>, |
72 | } | ||
diff --git a/src/routes/status.rs b/src/routes/status.rs new file mode 100644 index 0000000..45f3e51 --- /dev/null +++ b/src/routes/status.rs | |||
@@ -0,0 +1,10 @@ | |||
1 | use std::sync::Arc; | ||
2 | use axum::extract::{State, WebSocketUpgrade}; | ||
3 | use axum::response::Response; | ||
4 | use crate::AppState; | ||
5 | use crate::services::ping::status_websocket; | ||
6 | |||
7 | #[axum_macros::debug_handler] | ||
8 | pub async fn status(State(state): State<Arc<AppState>>, ws: WebSocketUpgrade) -> Response { | ||
9 | ws.on_upgrade(move |socket| status_websocket(socket, state)) | ||
10 | } \ No newline at end of file | ||