summaryrefslogtreecommitdiff
path: root/src/routes
diff options
context:
space:
mode:
authorFxQnLr <[email protected]>2024-04-10 00:16:55 +0200
committerFxQnLr <[email protected]>2024-04-10 00:16:55 +0200
commit3428a637ce420baef9aa9f9803e71bd587867005 (patch)
treea1ad8234ae9bf3709794324a41e38c2f7fa58d0d /src/routes
parent907e5cb5bc48899b444f7fedd85af7b5974d9a2e (diff)
downloadwebol-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.rs118
-rw-r--r--src/routes/start.rs92
-rw-r--r--src/routes/status.rs24
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 @@
1use crate::db::Device;
2use crate::error::Error; 1use crate::error::Error;
3use axum::extract::{Path, State}; 2use crate::storage::Device;
3use axum::extract::Path;
4use axum::Json; 4use axum::Json;
5use ipnetwork::IpNetwork;
5use mac_address::MacAddress; 6use mac_address::MacAddress;
6use serde::Deserialize; 7use serde::Deserialize;
7use serde_json::{json, Value}; 8use serde_json::{json, Value};
8use sqlx::types::ipnetwork::IpNetwork; 9use std::str::FromStr;
9use std::{str::FromStr, sync::Arc};
10use tracing::{debug, info}; 10use tracing::{debug, info};
11use utoipa::ToSchema; 11use 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]
23pub 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)]
56pub async fn get( 24pub 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] 35pub struct Payload {
80pub struct GetDevicePayload {
81 id: String,
82}
83
84#[derive(Deserialize, ToSchema)]
85pub 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)]
101pub async fn put( 51pub 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)]
139pub async fn post( 82pub 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 @@
1use crate::db::Device; 1use crate::storage::Device;
2use crate::error::Error; 2use crate::error::Error;
3use crate::services::ping::Value as PingValue; 3use crate::services::ping::Value as PingValue;
4use crate::wol::{create_buffer, send_packet}; 4use crate::wol::send_packet;
5use axum::extract::{Path, State}; 5use axum::extract::{Path, State};
6use axum::Json; 6use axum::Json;
7use serde::{Deserialize, Serialize}; 7use 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]
24pub 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
101async fn send_wol( 52fn 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)] 126fn get_eta(times: Option<Vec<i64>>) -> i64 {
186#[deprecated] 127 let times = if let Some(times) = times {
187pub 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;
3use axum::extract::ws::{Message, WebSocket}; 3use axum::extract::ws::{Message, WebSocket};
4use axum::extract::{State, WebSocketUpgrade}; 4use axum::extract::{State, WebSocketUpgrade};
5use axum::response::Response; 5use axum::response::Response;
6use sqlx::PgPool;
7use std::sync::Arc; 6use std::sync::Arc;
8use tracing::{debug, trace}; 7use 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
66async 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}