diff options
author | FxQnLr <[email protected]> | 2024-04-10 00:16:55 +0200 |
---|---|---|
committer | FxQnLr <[email protected]> | 2024-04-10 00:16:55 +0200 |
commit | 3428a637ce420baef9aa9f9803e71bd587867005 (patch) | |
tree | a1ad8234ae9bf3709794324a41e38c2f7fa58d0d /src/routes | |
parent | 907e5cb5bc48899b444f7fedd85af7b5974d9a2e (diff) | |
download | webol-3428a637ce420baef9aa9f9803e71bd587867005.tar webol-3428a637ce420baef9aa9f9803e71bd587867005.tar.gz webol-3428a637ce420baef9aa9f9803e71bd587867005.zip |
Closes #24. Changed postgres to json directory storage
Diffstat (limited to 'src/routes')
-rw-r--r-- | src/routes/device.rs | 118 | ||||
-rw-r--r-- | src/routes/start.rs | 92 | ||||
-rw-r--r-- | src/routes/status.rs | 24 |
3 files changed, 50 insertions, 184 deletions
diff --git a/src/routes/device.rs b/src/routes/device.rs index 40b5cd8..b6bd9d0 100644 --- a/src/routes/device.rs +++ b/src/routes/device.rs | |||
@@ -1,49 +1,17 @@ | |||
1 | use crate::db::Device; | ||
2 | use crate::error::Error; | 1 | use crate::error::Error; |
3 | use axum::extract::{Path, State}; | 2 | use crate::storage::Device; |
3 | use axum::extract::Path; | ||
4 | use axum::Json; | 4 | use axum::Json; |
5 | use ipnetwork::IpNetwork; | ||
5 | use mac_address::MacAddress; | 6 | use mac_address::MacAddress; |
6 | use serde::Deserialize; | 7 | use serde::Deserialize; |
7 | use serde_json::{json, Value}; | 8 | use serde_json::{json, Value}; |
8 | use sqlx::types::ipnetwork::IpNetwork; | 9 | use std::str::FromStr; |
9 | use std::{str::FromStr, sync::Arc}; | ||
10 | use tracing::{debug, info}; | 10 | use tracing::{debug, info}; |
11 | use utoipa::ToSchema; | 11 | use utoipa::ToSchema; |
12 | 12 | ||
13 | #[utoipa::path( | 13 | #[utoipa::path( |
14 | get, | 14 | get, |
15 | path = "/device", | ||
16 | request_body = GetDevicePayload, | ||
17 | responses( | ||
18 | (status = 200, description = "Get `Device` information", body = [Device]) | ||
19 | ), | ||
20 | security(("api_key" = [])) | ||
21 | )] | ||
22 | #[deprecated] | ||
23 | pub async fn get_payload( | ||
24 | State(state): State<Arc<crate::AppState>>, | ||
25 | Json(payload): Json<GetDevicePayload>, | ||
26 | ) -> Result<Json<Value>, Error> { | ||
27 | info!("get device {}", payload.id); | ||
28 | let device = sqlx::query_as!( | ||
29 | Device, | ||
30 | r#" | ||
31 | SELECT id, mac, broadcast_addr, ip, times | ||
32 | FROM devices | ||
33 | WHERE id = $1; | ||
34 | "#, | ||
35 | payload.id | ||
36 | ) | ||
37 | .fetch_one(&state.db) | ||
38 | .await?; | ||
39 | |||
40 | debug!("got device {:?}", device); | ||
41 | |||
42 | Ok(Json(json!(device))) | ||
43 | } | ||
44 | |||
45 | #[utoipa::path( | ||
46 | get, | ||
47 | path = "/device/{id}", | 15 | path = "/device/{id}", |
48 | responses( | 16 | responses( |
49 | (status = 200, description = "Get `Device` information", body = [Device]) | 17 | (status = 200, description = "Get `Device` information", body = [Device]) |
@@ -53,22 +21,10 @@ pub async fn get_payload( | |||
53 | ), | 21 | ), |
54 | security((), ("api_key" = [])) | 22 | security((), ("api_key" = [])) |
55 | )] | 23 | )] |
56 | pub async fn get( | 24 | pub async fn get(Path(id): Path<String>) -> Result<Json<Value>, Error> { |
57 | State(state): State<Arc<crate::AppState>>, | 25 | info!("get device from path {}", id); |
58 | Path(path): Path<String>, | 26 | |
59 | ) -> Result<Json<Value>, Error> { | 27 | let device = Device::read(&id)?; |
60 | info!("get device from path {}", path); | ||
61 | let device = sqlx::query_as!( | ||
62 | Device, | ||
63 | r#" | ||
64 | SELECT id, mac, broadcast_addr, ip, times | ||
65 | FROM devices | ||
66 | WHERE id = $1; | ||
67 | "#, | ||
68 | path | ||
69 | ) | ||
70 | .fetch_one(&state.db) | ||
71 | .await?; | ||
72 | 28 | ||
73 | debug!("got device {:?}", device); | 29 | debug!("got device {:?}", device); |
74 | 30 | ||
@@ -76,13 +32,7 @@ pub async fn get( | |||
76 | } | 32 | } |
77 | 33 | ||
78 | #[derive(Deserialize, ToSchema)] | 34 | #[derive(Deserialize, ToSchema)] |
79 | #[deprecated] | 35 | pub struct Payload { |
80 | pub struct GetDevicePayload { | ||
81 | id: String, | ||
82 | } | ||
83 | |||
84 | #[derive(Deserialize, ToSchema)] | ||
85 | pub struct DevicePayload { | ||
86 | id: String, | 36 | id: String, |
87 | mac: String, | 37 | mac: String, |
88 | broadcast_addr: String, | 38 | broadcast_addr: String, |
@@ -92,15 +42,14 @@ pub struct DevicePayload { | |||
92 | #[utoipa::path( | 42 | #[utoipa::path( |
93 | put, | 43 | put, |
94 | path = "/device", | 44 | path = "/device", |
95 | request_body = DevicePayload, | 45 | request_body = Payload, |
96 | responses( | 46 | responses( |
97 | (status = 200, description = "add device to storage", body = [DeviceSchema]) | 47 | (status = 200, description = "add device to storage", body = [DeviceSchema]) |
98 | ), | 48 | ), |
99 | security((), ("api_key" = [])) | 49 | security((), ("api_key" = [])) |
100 | )] | 50 | )] |
101 | pub async fn put( | 51 | pub async fn put( |
102 | State(state): State<Arc<crate::AppState>>, | 52 | Json(payload): Json<Payload>, |
103 | Json(payload): Json<DevicePayload>, | ||
104 | ) -> Result<Json<Value>, Error> { | 53 | ) -> Result<Json<Value>, Error> { |
105 | info!( | 54 | info!( |
106 | "add device {} ({}, {}, {})", | 55 | "add device {} ({}, {}, {})", |
@@ -109,20 +58,14 @@ pub async fn put( | |||
109 | 58 | ||
110 | let ip = IpNetwork::from_str(&payload.ip)?; | 59 | let ip = IpNetwork::from_str(&payload.ip)?; |
111 | let mac = MacAddress::from_str(&payload.mac)?; | 60 | let mac = MacAddress::from_str(&payload.mac)?; |
112 | let device = sqlx::query_as!( | 61 | let device = Device { |
113 | Device, | 62 | id: payload.id, |
114 | r#" | ||
115 | INSERT INTO devices (id, mac, broadcast_addr, ip) | ||
116 | VALUES ($1, $2, $3, $4) | ||
117 | RETURNING id, mac, broadcast_addr, ip, times; | ||
118 | "#, | ||
119 | payload.id, | ||
120 | mac, | 63 | mac, |
121 | payload.broadcast_addr, | 64 | broadcast_addr: payload.broadcast_addr, |
122 | ip | 65 | ip, |
123 | ) | 66 | times: None, |
124 | .fetch_one(&state.db) | 67 | }; |
125 | .await?; | 68 | device.write()?; |
126 | 69 | ||
127 | Ok(Json(json!(device))) | 70 | Ok(Json(json!(device))) |
128 | } | 71 | } |
@@ -130,15 +73,14 @@ pub async fn put( | |||
130 | #[utoipa::path( | 73 | #[utoipa::path( |
131 | post, | 74 | post, |
132 | path = "/device", | 75 | path = "/device", |
133 | request_body = DevicePayload, | 76 | request_body = Payload, |
134 | responses( | 77 | responses( |
135 | (status = 200, description = "update device in storage", body = [DeviceSchema]) | 78 | (status = 200, description = "update device in storage", body = [DeviceSchema]) |
136 | ), | 79 | ), |
137 | security((), ("api_key" = [])) | 80 | security((), ("api_key" = [])) |
138 | )] | 81 | )] |
139 | pub async fn post( | 82 | pub async fn post( |
140 | State(state): State<Arc<crate::AppState>>, | 83 | Json(payload): Json<Payload>, |
141 | Json(payload): Json<DevicePayload>, | ||
142 | ) -> Result<Json<Value>, Error> { | 84 | ) -> Result<Json<Value>, Error> { |
143 | info!( | 85 | info!( |
144 | "edit device {} ({}, {}, {})", | 86 | "edit device {} ({}, {}, {})", |
@@ -146,20 +88,16 @@ pub async fn post( | |||
146 | ); | 88 | ); |
147 | let ip = IpNetwork::from_str(&payload.ip)?; | 89 | let ip = IpNetwork::from_str(&payload.ip)?; |
148 | let mac = MacAddress::from_str(&payload.mac)?; | 90 | let mac = MacAddress::from_str(&payload.mac)?; |
149 | let device = sqlx::query_as!( | 91 | let times = Device::read(&payload.id)?.times; |
150 | Device, | 92 | |
151 | r#" | 93 | let device = Device { |
152 | UPDATE devices | 94 | id: payload.id, |
153 | SET mac = $1, broadcast_addr = $2, ip = $3 WHERE id = $4 | ||
154 | RETURNING id, mac, broadcast_addr, ip, times; | ||
155 | "#, | ||
156 | mac, | 95 | mac, |
157 | payload.broadcast_addr, | 96 | broadcast_addr: payload.broadcast_addr, |
158 | ip, | 97 | ip, |
159 | payload.id | 98 | times, |
160 | ) | 99 | }; |
161 | .fetch_one(&state.db) | 100 | device.write()?; |
162 | .await?; | ||
163 | 101 | ||
164 | Ok(Json(json!(device))) | 102 | Ok(Json(json!(device))) |
165 | } | 103 | } |
diff --git a/src/routes/start.rs b/src/routes/start.rs index ff3d1be..6907193 100644 --- a/src/routes/start.rs +++ b/src/routes/start.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use crate::db::Device; | 1 | use crate::storage::Device; |
2 | use crate::error::Error; | 2 | use crate::error::Error; |
3 | use crate::services::ping::Value as PingValue; | 3 | use crate::services::ping::Value as PingValue; |
4 | use crate::wol::{create_buffer, send_packet}; | 4 | use crate::wol::send_packet; |
5 | use axum::extract::{Path, State}; | 5 | use axum::extract::{Path, State}; |
6 | use axum::Json; | 6 | use axum::Json; |
7 | use serde::{Deserialize, Serialize}; | 7 | use serde::{Deserialize, Serialize}; |
@@ -13,55 +13,6 @@ use uuid::Uuid; | |||
13 | 13 | ||
14 | #[utoipa::path( | 14 | #[utoipa::path( |
15 | post, | 15 | post, |
16 | path = "/start", | ||
17 | request_body = PayloadOld, | ||
18 | responses( | ||
19 | (status = 200, description = "DEP", body = [Response]) | ||
20 | ), | ||
21 | security((), ("api_key" = [])) | ||
22 | )] | ||
23 | #[deprecated] | ||
24 | pub async fn start_payload( | ||
25 | State(state): State<Arc<crate::AppState>>, | ||
26 | Json(payload): Json<PayloadOld>, | ||
27 | ) -> Result<Json<Value>, Error> { | ||
28 | info!("POST request"); | ||
29 | let device = sqlx::query_as!( | ||
30 | Device, | ||
31 | r#" | ||
32 | SELECT id, mac, broadcast_addr, ip, times | ||
33 | FROM devices | ||
34 | WHERE id = $1; | ||
35 | "#, | ||
36 | payload.id | ||
37 | ) | ||
38 | .fetch_one(&state.db) | ||
39 | .await?; | ||
40 | |||
41 | info!("starting {}", device.id); | ||
42 | |||
43 | let bind_addr = "0.0.0.0:0"; | ||
44 | |||
45 | let _ = send_packet( | ||
46 | bind_addr, | ||
47 | &device.broadcast_addr, | ||
48 | &create_buffer(&device.mac.to_string())?, | ||
49 | )?; | ||
50 | let dev_id = device.id.clone(); | ||
51 | let uuid = if payload.ping.is_some_and(|ping| ping) { | ||
52 | Some(setup_ping(state, device)) | ||
53 | } else { | ||
54 | None | ||
55 | }; | ||
56 | Ok(Json(json!(Response { | ||
57 | id: dev_id, | ||
58 | boot: true, | ||
59 | uuid | ||
60 | }))) | ||
61 | } | ||
62 | |||
63 | #[utoipa::path( | ||
64 | post, | ||
65 | path = "/start/{id}", | 16 | path = "/start/{id}", |
66 | request_body = Option<Payload>, | 17 | request_body = Option<Payload>, |
67 | responses( | 18 | responses( |
@@ -77,7 +28,7 @@ pub async fn post( | |||
77 | Path(id): Path<String>, | 28 | Path(id): Path<String>, |
78 | payload: Option<Json<Payload>>, | 29 | payload: Option<Json<Payload>>, |
79 | ) -> Result<Json<Value>, Error> { | 30 | ) -> Result<Json<Value>, Error> { |
80 | send_wol(state, &id, payload).await | 31 | send_wol(state, &id, payload) |
81 | } | 32 | } |
82 | 33 | ||
83 | #[utoipa::path( | 34 | #[utoipa::path( |
@@ -95,26 +46,16 @@ pub async fn get( | |||
95 | State(state): State<Arc<crate::AppState>>, | 46 | State(state): State<Arc<crate::AppState>>, |
96 | Path(id): Path<String>, | 47 | Path(id): Path<String>, |
97 | ) -> Result<Json<Value>, Error> { | 48 | ) -> Result<Json<Value>, Error> { |
98 | send_wol(state, &id, None).await | 49 | send_wol(state, &id, None) |
99 | } | 50 | } |
100 | 51 | ||
101 | async fn send_wol( | 52 | fn send_wol( |
102 | state: Arc<crate::AppState>, | 53 | state: Arc<crate::AppState>, |
103 | id: &str, | 54 | id: &str, |
104 | payload: Option<Json<Payload>>, | 55 | payload: Option<Json<Payload>>, |
105 | ) -> Result<Json<Value>, Error> { | 56 | ) -> Result<Json<Value>, Error> { |
106 | info!("Start request for {id}"); | 57 | info!("start request for {id}"); |
107 | let device = sqlx::query_as!( | 58 | let device = Device::read(id)?; |
108 | Device, | ||
109 | r#" | ||
110 | SELECT id, mac, broadcast_addr, ip, times | ||
111 | FROM devices | ||
112 | WHERE id = $1; | ||
113 | "#, | ||
114 | id | ||
115 | ) | ||
116 | .fetch_one(&state.db) | ||
117 | .await?; | ||
118 | 59 | ||
119 | info!("starting {}", device.id); | 60 | info!("starting {}", device.id); |
120 | 61 | ||
@@ -122,8 +63,8 @@ async fn send_wol( | |||
122 | 63 | ||
123 | let _ = send_packet( | 64 | let _ = send_packet( |
124 | bind_addr, | 65 | bind_addr, |
125 | &device.broadcast_addr, | 66 | &device.broadcast_addr.to_string(), |
126 | &create_buffer(&device.mac.to_string())?, | 67 | &device.mac.bytes() |
127 | )?; | 68 | )?; |
128 | let dev_id = device.id.clone(); | 69 | let dev_id = device.id.clone(); |
129 | let uuid = if let Some(pl) = payload { | 70 | let uuid = if let Some(pl) = payload { |
@@ -163,6 +104,7 @@ fn setup_ping(state: Arc<crate::AppState>, device: Device) -> String { | |||
163 | uuid_gen.clone(), | 104 | uuid_gen.clone(), |
164 | PingValue { | 105 | PingValue { |
165 | ip: device.ip, | 106 | ip: device.ip, |
107 | eta: get_eta(device.clone().times), | ||
166 | online: false, | 108 | online: false, |
167 | }, | 109 | }, |
168 | ); | 110 | ); |
@@ -174,7 +116,6 @@ fn setup_ping(state: Arc<crate::AppState>, device: Device) -> String { | |||
174 | device, | 116 | device, |
175 | uuid_gen, | 117 | uuid_gen, |
176 | &state.ping_map, | 118 | &state.ping_map, |
177 | &state.db, | ||
178 | ) | 119 | ) |
179 | .await; | 120 | .await; |
180 | }); | 121 | }); |
@@ -182,11 +123,14 @@ fn setup_ping(state: Arc<crate::AppState>, device: Device) -> String { | |||
182 | uuid_ret | 123 | uuid_ret |
183 | } | 124 | } |
184 | 125 | ||
185 | #[derive(Deserialize, ToSchema)] | 126 | fn get_eta(times: Option<Vec<i64>>) -> i64 { |
186 | #[deprecated] | 127 | let times = if let Some(times) = times { |
187 | pub struct PayloadOld { | 128 | times |
188 | id: String, | 129 | } else { |
189 | ping: Option<bool>, | 130 | vec![0] |
131 | }; | ||
132 | |||
133 | times.iter().sum::<i64>() / i64::try_from(times.len()).unwrap() | ||
190 | } | 134 | } |
191 | 135 | ||
192 | #[derive(Deserialize, ToSchema)] | 136 | #[derive(Deserialize, ToSchema)] |
diff --git a/src/routes/status.rs b/src/routes/status.rs index 0e25f7d..b38202b 100644 --- a/src/routes/status.rs +++ b/src/routes/status.rs | |||
@@ -3,7 +3,6 @@ use crate::AppState; | |||
3 | use axum::extract::ws::{Message, WebSocket}; | 3 | use axum::extract::ws::{Message, WebSocket}; |
4 | use axum::extract::{State, WebSocketUpgrade}; | 4 | use axum::extract::{State, WebSocketUpgrade}; |
5 | use axum::response::Response; | 5 | use axum::response::Response; |
6 | use sqlx::PgPool; | ||
7 | use std::sync::Arc; | 6 | use std::sync::Arc; |
8 | use tracing::{debug, trace}; | 7 | use tracing::{debug, trace}; |
9 | 8 | ||
@@ -18,13 +17,13 @@ pub async fn websocket(mut socket: WebSocket, state: Arc<AppState>) { | |||
18 | 17 | ||
19 | trace!("Search for uuid: {}", uuid); | 18 | trace!("Search for uuid: {}", uuid); |
20 | 19 | ||
21 | let eta = get_eta(&state.db).await; | ||
22 | let _ = socket | ||
23 | .send(Message::Text(format!("eta_{eta}_{uuid}"))) | ||
24 | .await; | ||
25 | 20 | ||
26 | let device_exists = state.ping_map.contains_key(&uuid); | 21 | let device_exists = state.ping_map.contains_key(&uuid); |
27 | if device_exists { | 22 | if device_exists { |
23 | let eta = state.ping_map.get(&uuid).unwrap().eta; | ||
24 | let _ = socket | ||
25 | .send(Message::Text(format!("eta_{eta}_{uuid}"))) | ||
26 | .await; | ||
28 | let _ = socket | 27 | let _ = socket |
29 | .send(receive_ping_broadcast(state.clone(), uuid).await) | 28 | .send(receive_ping_broadcast(state.clone(), uuid).await) |
30 | .await; | 29 | .await; |
@@ -62,18 +61,3 @@ async fn receive_ping_broadcast(state: Arc<AppState>, uuid: String) -> Message { | |||
62 | } | 61 | } |
63 | } | 62 | } |
64 | } | 63 | } |
65 | |||
66 | async fn get_eta(db: &PgPool) -> i64 { | ||
67 | let query = sqlx::query!(r#"SELECT times FROM devices;"#) | ||
68 | .fetch_one(db) | ||
69 | .await | ||
70 | .unwrap(); | ||
71 | |||
72 | let times = if let Some(times) = query.times { | ||
73 | times | ||
74 | } else { | ||
75 | vec![0] | ||
76 | }; | ||
77 | |||
78 | times.iter().sum::<i64>() / i64::try_from(times.len()).unwrap() | ||
79 | } | ||