summaryrefslogtreecommitdiff
path: root/src/routes
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes')
-rw-r--r--src/routes/device.rs92
-rw-r--r--src/routes/mod.rs3
-rw-r--r--src/routes/start.rs52
3 files changed, 107 insertions, 40 deletions
diff --git a/src/routes/device.rs b/src/routes/device.rs
new file mode 100644
index 0000000..d5d7144
--- /dev/null
+++ b/src/routes/device.rs
@@ -0,0 +1,92 @@
1use std::sync::Arc;
2use axum::extract::State;
3use axum::headers::HeaderMap;
4use axum::Json;
5use serde::{Deserialize, Serialize};
6use serde_json::{json, Value};
7use crate::auth::auth;
8use crate::db::Device;
9use crate::error::WebolError;
10
11pub async fn get_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<GetDevicePayload>) -> Result<Json<Value>, WebolError> {
12 let secret = headers.get("authorization");
13 if auth(secret).map_err(WebolError::Auth)? {
14 let device = sqlx::query_as!(
15 Device,
16 r#"
17 SELECT id, mac, broadcast_addr
18 FROM devices
19 WHERE id = $1;
20 "#,
21 payload.id
22 ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?;
23
24 Ok(Json(json!(device)))
25 } else {
26 Err(WebolError::Generic)
27 }
28}
29
30#[derive(Deserialize)]
31pub struct GetDevicePayload {
32 id: String,
33}
34
35pub async fn put_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PutDevicePayload>) -> Result<Json<Value>, WebolError> {
36 let secret = headers.get("authorization");
37 if auth(secret).map_err(WebolError::Auth)? {
38 sqlx::query!(
39 r#"
40 INSERT INTO devices (id, mac, broadcast_addr)
41 VALUES ($1, $2, $3);
42 "#,
43 payload.id,
44 payload.mac,
45 payload.broadcast_addr
46 ).execute(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?;
47
48 Ok(Json(json!(PutDeviceResponse { success: true })))
49 } else {
50 Err(WebolError::Generic)
51 }
52}
53
54#[derive(Deserialize)]
55pub struct PutDevicePayload {
56 id: String,
57 mac: String,
58 broadcast_addr: String,
59}
60
61#[derive(Serialize)]
62pub struct PutDeviceResponse {
63 success: bool
64}
65
66pub async fn post_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PostDevicePayload>) -> Result<Json<Value>, WebolError> {
67 let secret = headers.get("authorization");
68 if auth(secret).map_err(WebolError::Auth)? {
69 let device = sqlx::query_as!(
70 Device,
71 r#"
72 UPDATE devices
73 SET mac = $1, broadcast_addr = $2 WHERE id = $3
74 RETURNING id, mac, broadcast_addr;
75 "#,
76 payload.mac,
77 payload.broadcast_addr,
78 payload.id
79 ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?;
80
81 Ok(Json(json!(device)))
82 } else {
83 Err(WebolError::Generic)
84 }
85}
86
87#[derive(Deserialize)]
88pub struct PostDevicePayload {
89 id: String,
90 mac: String,
91 broadcast_addr: String,
92} \ No newline at end of file
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index 78d4375..12fbfab 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -1 +1,2 @@
1pub mod start; \ No newline at end of file 1pub mod start;
2pub mod device; \ No newline at end of file
diff --git a/src/routes/start.rs b/src/routes/start.rs
index 2d505fc..d16ea4e 100644
--- a/src/routes/start.rs
+++ b/src/routes/start.rs
@@ -1,45 +1,43 @@
1use axum::headers::HeaderMap; 1use axum::headers::HeaderMap;
2use axum::http::StatusCode;
3use axum::Json; 2use axum::Json;
4use axum::response::{IntoResponse, Response};
5use serde::{Deserialize, Serialize}; 3use serde::{Deserialize, Serialize};
6use std::error::Error;
7use std::sync::Arc; 4use std::sync::Arc;
8use axum::extract::State; 5use axum::extract::State;
9use serde_json::{json, Value}; 6use serde_json::{json, Value};
10use tracing::{error, info}; 7use tracing::info;
11use crate::auth::{auth, AuthError}; 8use crate::auth::auth;
12use crate::config::SETTINGS; 9use crate::config::SETTINGS;
13use crate::wol::{create_buffer, send_packet}; 10use crate::wol::{create_buffer, send_packet};
14use crate::db::Device; 11use crate::db::Device;
12use crate::error::WebolError;
15 13
16pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<StartPayload>) -> Result<Json<Value>, StartError> { 14pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<StartPayload>) -> Result<Json<Value>, WebolError> {
17 let secret = headers.get("authorization"); 15 let secret = headers.get("authorization");
18 if auth(secret).map_err(StartError::Auth)? { 16 if auth(secret).map_err(WebolError::Auth)? {
19 let device = sqlx::query_as!( 17 let device = sqlx::query_as!(
20 Device, 18 Device,
21 r#" 19 r#"
22 SELECT id, mac, broadcast_addr 20 SELECT id, mac, broadcast_addr
23 FROM devices 21 FROM devices
24 WHERE id = ?1; 22 WHERE id = $1;
25 "#, 23 "#,
26 payload.id 24 payload.id
27 ).fetch_one(&state.db).await.map_err(|err| StartError::Server(Box::new(err)))?; 25 ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?;
28 26
29 info!("starting {}", device.id); 27 info!("starting {}", device.id);
30 28
31 let bind_addr = SETTINGS 29 let bind_addr = SETTINGS
32 .get_string("bindaddr") 30 .get_string("bindaddr")
33 .map_err(|err| StartError::Server(Box::new(err)))?; 31 .map_err(|err| WebolError::Server(Box::new(err)))?;
34 32
35 let _ = send_packet( 33 let _ = send_packet(
36 &bind_addr.parse().map_err(|err| StartError::Server(Box::new(err)))?, 34 &bind_addr.parse().map_err(|err| WebolError::Server(Box::new(err)))?,
37 &device.broadcast_addr.parse().map_err(|err| StartError::Server(Box::new(err)))?, 35 &device.broadcast_addr.parse().map_err(|err| WebolError::Server(Box::new(err)))?,
38 create_buffer(&device.mac).map_err(|err| StartError::Server(Box::new(err)))? 36 create_buffer(&device.mac).map_err(|err| WebolError::Server(Box::new(err)))?
39 ).map_err(|err| StartError::Server(Box::new(err))); 37 ).map_err(|err| WebolError::Server(Box::new(err)));
40 Ok(Json(json!(StartResponse { id: device.id, boot: true }))) 38 Ok(Json(json!(StartResponse { id: device.id, boot: true })))
41 } else { 39 } else {
42 Err(StartError::Generic) 40 Err(WebolError::Generic)
43 } 41 }
44} 42}
45 43
@@ -53,28 +51,4 @@ pub struct StartPayload {
53struct StartResponse { 51struct StartResponse {
54 id: String, 52 id: String,
55 boot: bool, 53 boot: bool,
56}
57
58pub enum StartError {
59 Auth(AuthError),
60 Generic,
61 Server(Box<dyn Error>),
62}
63
64impl IntoResponse for StartError {
65 fn into_response(self) -> Response {
66 let (status, error_message) = match self {
67 StartError::Auth(err) => err.get(),
68 StartError::Generic => (StatusCode::INTERNAL_SERVER_ERROR, ""),
69 StartError::Server(err) => {
70 error!("server error: {}", err.to_string());
71 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
72 },
73
74 };
75 let body = Json(json!({
76 "error": error_message,
77 }));
78 (status, body).into_response()
79 }
80} \ No newline at end of file 54} \ No newline at end of file