From d8060da1180545df5d03a76cd2860191ecf87507 Mon Sep 17 00:00:00 2001 From: FxQnLr Date: Mon, 8 Apr 2024 10:42:47 +0200 Subject: Closes #23. Start request id parameter put in path --- src/main.rs | 13 +++++---- src/routes/device.rs | 4 +-- src/routes/start.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 80 insertions(+), 13 deletions(-) (limited to 'src') 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::{ }; use dashmap::DashMap; use sqlx::PgPool; -use time::UtcOffset; use std::{env, sync::Arc}; +use time::UtcOffset; use tokio::sync::broadcast::{channel, Sender}; use tracing::{info, level_filters::LevelFilter}; use tracing_subscriber::{ @@ -38,13 +38,15 @@ mod wol; #[openapi( paths( start::start, + start::start_payload, device::get, - device::get_path, + device::get_payload, device::post, device::put, ), components( schemas( + start::PayloadOld, start::Payload, start::Response, device::PutDevicePayload, @@ -116,12 +118,13 @@ async fn main() -> color_eyre::eyre::Result<()> { }; let app = Router::new() - .route("/start", post(start::start)) + .route("/start", post(start::start_payload)) + .route("/start/:id", post(start::start)) .route( "/device", - post(device::post).get(device::get).put(device::put), + post(device::post).get(device::get_payload).put(device::put), ) - .route("/device/:id", get(device::get_path)) + .route("/device/:id", get(device::get)) .route("/status", get(status::status)) .route_layer(from_fn_with_state(shared_state.clone(), extractors::auth)) .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; security(("api_key" = [])) )] #[deprecated] -pub async fn get( +pub async fn get_payload( State(state): State>, Json(payload): Json, ) -> Result, Error> { @@ -53,7 +53,7 @@ pub async fn get( ), security(("api_key" = [])) )] -pub async fn get_path( +pub async fn get( State(state): State>, Path(path): Path, ) -> Result, 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; use crate::error::Error; use crate::services::ping::Value as PingValue; use crate::wol::{create_buffer, send_packet}; -use axum::extract::State; +use axum::extract::{Path, State}; use axum::Json; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use utoipa::ToSchema; use std::sync::Arc; use tracing::{debug, info}; +use utoipa::ToSchema; use uuid::Uuid; #[utoipa::path( post, path = "/start", - request_body = Payload, + request_body = PayloadOld, responses( (status = 200, description = "List matching todos by query", body = [Response]) ), security(("api_key" = [])) )] -pub async fn start( +#[deprecated] +pub async fn start_payload( State(state): State>, - Json(payload): Json, + Json(payload): Json, ) -> Result, Error> { info!("POST request"); let device = sqlx::query_as!( @@ -59,6 +60,63 @@ pub async fn start( }))) } +#[utoipa::path( + post, + path = "/start/{id}", + request_body = Payload, + responses( + (status = 200, description = "Start the device with the given id", body = [Response]) + ), + params( + ("id" = String, Path, description = "Device id") + ), + security(("api_key" = [])) +)] +pub async fn start( + State(state): State>, + Path(id): Path, + payload: Option>, +) -> Result, Error> { + info!("Start request for {id}"); + let device = sqlx::query_as!( + Device, + r#" + SELECT id, mac, broadcast_addr, ip, times + FROM devices + WHERE id = $1; + "#, + id + ) + .fetch_one(&state.db) + .await?; + + info!("starting {}", device.id); + + let bind_addr = "0.0.0.0:0"; + + let _ = send_packet( + bind_addr, + &device.broadcast_addr, + &create_buffer(&device.mac.to_string())?, + )?; + let dev_id = device.id.clone(); + let uuid = if let Some(pl) = payload { + if pl.ping.is_some_and(|ping| ping) { + Some(setup_ping(state, device)) + } else { + None + } + } else { + None + }; + + Ok(Json(json!(Response { + id: dev_id, + boot: true, + uuid + }))) +} + fn setup_ping(state: Arc, device: Device) -> String { let mut uuid: Option = None; for (key, value) in state.ping_map.clone() { @@ -99,11 +157,17 @@ fn setup_ping(state: Arc, device: Device) -> String { } #[derive(Deserialize, ToSchema)] -pub struct Payload { +#[deprecated] +pub struct PayloadOld { id: String, ping: Option, } +#[derive(Deserialize, ToSchema)] +pub struct Payload { + ping: Option, +} + #[derive(Serialize, ToSchema)] pub struct Response { id: String, -- cgit v1.2.3