aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs13
-rw-r--r--src/routes/device.rs4
-rw-r--r--src/routes/start.rs76
3 files changed, 80 insertions, 13 deletions
diff --git a/src/main.rs b/src/main.rs
index 00fc6ce..75f491a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -11,8 +11,8 @@ use axum::{
11}; 11};
12use dashmap::DashMap; 12use dashmap::DashMap;
13use sqlx::PgPool; 13use sqlx::PgPool;
14use time::UtcOffset;
15use std::{env, sync::Arc}; 14use std::{env, sync::Arc};
15use time::UtcOffset;
16use tokio::sync::broadcast::{channel, Sender}; 16use tokio::sync::broadcast::{channel, Sender};
17use tracing::{info, level_filters::LevelFilter}; 17use tracing::{info, level_filters::LevelFilter};
18use tracing_subscriber::{ 18use tracing_subscriber::{
@@ -38,13 +38,15 @@ mod wol;
38#[openapi( 38#[openapi(
39 paths( 39 paths(
40 start::start, 40 start::start,
41 start::start_payload,
41 device::get, 42 device::get,
42 device::get_path, 43 device::get_payload,
43 device::post, 44 device::post,
44 device::put, 45 device::put,
45 ), 46 ),
46 components( 47 components(
47 schemas( 48 schemas(
49 start::PayloadOld,
48 start::Payload, 50 start::Payload,
49 start::Response, 51 start::Response,
50 device::PutDevicePayload, 52 device::PutDevicePayload,
@@ -116,12 +118,13 @@ async fn main() -> color_eyre::eyre::Result<()> {
116 }; 118 };
117 119
118 let app = Router::new() 120 let app = Router::new()
119 .route("/start", post(start::start)) 121 .route("/start", post(start::start_payload))
122 .route("/start/:id", post(start::start))
120 .route( 123 .route(
121 "/device", 124 "/device",
122 post(device::post).get(device::get).put(device::put), 125 post(device::post).get(device::get_payload).put(device::put),
123 ) 126 )
124 .route("/device/:id", get(device::get_path)) 127 .route("/device/:id", get(device::get))
125 .route("/status", get(status::status)) 128 .route("/status", get(status::status))
126 .route_layer(from_fn_with_state(shared_state.clone(), extractors::auth)) 129 .route_layer(from_fn_with_state(shared_state.clone(), extractors::auth))
127 .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi())) 130 .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi()))
diff --git a/src/routes/device.rs b/src/routes/device.rs
index d01d9f0..bbc832d 100644
--- a/src/routes/device.rs
+++ b/src/routes/device.rs
@@ -20,7 +20,7 @@ use utoipa::ToSchema;
20 security(("api_key" = [])) 20 security(("api_key" = []))
21)] 21)]
22#[deprecated] 22#[deprecated]
23pub async fn get( 23pub async fn get_payload(
24 State(state): State<Arc<crate::AppState>>, 24 State(state): State<Arc<crate::AppState>>,
25 Json(payload): Json<GetDevicePayload>, 25 Json(payload): Json<GetDevicePayload>,
26) -> Result<Json<Value>, Error> { 26) -> Result<Json<Value>, Error> {
@@ -53,7 +53,7 @@ pub async fn get(
53 ), 53 ),
54 security(("api_key" = [])) 54 security(("api_key" = []))
55)] 55)]
56pub async fn get_path( 56pub async fn get(
57 State(state): State<Arc<crate::AppState>>, 57 State(state): State<Arc<crate::AppState>>,
58 Path(path): Path<String>, 58 Path(path): Path<String>,
59) -> Result<Json<Value>, Error> { 59) -> Result<Json<Value>, Error> {
diff --git a/src/routes/start.rs b/src/routes/start.rs
index ef6e8f2..fa226d8 100644
--- a/src/routes/start.rs
+++ b/src/routes/start.rs
@@ -2,27 +2,28 @@ use crate::db::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::{create_buffer, send_packet};
5use axum::extract::State; 5use axum::extract::{Path, State};
6use axum::Json; 6use axum::Json;
7use serde::{Deserialize, Serialize}; 7use serde::{Deserialize, Serialize};
8use serde_json::{json, Value}; 8use serde_json::{json, Value};
9use utoipa::ToSchema;
10use std::sync::Arc; 9use std::sync::Arc;
11use tracing::{debug, info}; 10use tracing::{debug, info};
11use utoipa::ToSchema;
12use uuid::Uuid; 12use uuid::Uuid;
13 13
14#[utoipa::path( 14#[utoipa::path(
15 post, 15 post,
16 path = "/start", 16 path = "/start",
17 request_body = Payload, 17 request_body = PayloadOld,
18 responses( 18 responses(
19 (status = 200, description = "List matching todos by query", body = [Response]) 19 (status = 200, description = "List matching todos by query", body = [Response])
20 ), 20 ),
21 security(("api_key" = [])) 21 security(("api_key" = []))
22)] 22)]
23pub async fn start( 23#[deprecated]
24pub async fn start_payload(
24 State(state): State<Arc<crate::AppState>>, 25 State(state): State<Arc<crate::AppState>>,
25 Json(payload): Json<Payload>, 26 Json(payload): Json<PayloadOld>,
26) -> Result<Json<Value>, Error> { 27) -> Result<Json<Value>, Error> {
27 info!("POST request"); 28 info!("POST request");
28 let device = sqlx::query_as!( 29 let device = sqlx::query_as!(
@@ -59,6 +60,63 @@ pub async fn start(
59 }))) 60 })))
60} 61}
61 62
63#[utoipa::path(
64 post,
65 path = "/start/{id}",
66 request_body = Payload,
67 responses(
68 (status = 200, description = "Start the device with the given id", body = [Response])
69 ),
70 params(
71 ("id" = String, Path, description = "Device id")
72 ),
73 security(("api_key" = []))
74)]
75pub async fn start(
76 State(state): State<Arc<crate::AppState>>,
77 Path(id): Path<String>,
78 payload: Option<Json<Payload>>,
79) -> Result<Json<Value>, Error> {
80 info!("Start request for {id}");
81 let device = sqlx::query_as!(
82 Device,
83 r#"
84 SELECT id, mac, broadcast_addr, ip, times
85 FROM devices
86 WHERE id = $1;
87 "#,
88 id
89 )
90 .fetch_one(&state.db)
91 .await?;
92
93 info!("starting {}", device.id);
94
95 let bind_addr = "0.0.0.0:0";
96
97 let _ = send_packet(
98 bind_addr,
99 &device.broadcast_addr,
100 &create_buffer(&device.mac.to_string())?,
101 )?;
102 let dev_id = device.id.clone();
103 let uuid = if let Some(pl) = payload {
104 if pl.ping.is_some_and(|ping| ping) {
105 Some(setup_ping(state, device))
106 } else {
107 None
108 }
109 } else {
110 None
111 };
112
113 Ok(Json(json!(Response {
114 id: dev_id,
115 boot: true,
116 uuid
117 })))
118}
119
62fn setup_ping(state: Arc<crate::AppState>, device: Device) -> String { 120fn setup_ping(state: Arc<crate::AppState>, device: Device) -> String {
63 let mut uuid: Option<String> = None; 121 let mut uuid: Option<String> = None;
64 for (key, value) in state.ping_map.clone() { 122 for (key, value) in state.ping_map.clone() {
@@ -99,11 +157,17 @@ fn setup_ping(state: Arc<crate::AppState>, device: Device) -> String {
99} 157}
100 158
101#[derive(Deserialize, ToSchema)] 159#[derive(Deserialize, ToSchema)]
102pub struct Payload { 160#[deprecated]
161pub struct PayloadOld {
103 id: String, 162 id: String,
104 ping: Option<bool>, 163 ping: Option<bool>,
105} 164}
106 165
166#[derive(Deserialize, ToSchema)]
167pub struct Payload {
168 ping: Option<bool>,
169}
170
107#[derive(Serialize, ToSchema)] 171#[derive(Serialize, ToSchema)]
108pub struct Response { 172pub struct Response {
109 id: String, 173 id: String,