freshblu_server/handlers/
mod.rs1pub mod auth;
2pub mod devices;
3pub mod messages;
4pub mod status;
5pub mod subscriptions;
6pub mod tokens;
7
8use axum::{
9 extract::FromRequestParts,
10 http::request::Parts,
11 response::{IntoResponse, Response},
12};
13use freshblu_core::{auth::parse_basic_auth, device::Device, error::FreshBluError};
14use uuid::Uuid;
15
16use crate::{ApiError, AppState};
17
18pub struct AuthenticatedDevice(pub Device, pub Option<Uuid>);
20
21#[axum::async_trait]
22impl FromRequestParts<AppState> for AuthenticatedDevice {
23 type Rejection = Response;
24
25 async fn from_request_parts(
26 parts: &mut Parts,
27 state: &AppState,
28 ) -> Result<Self, Self::Rejection> {
29 let headers = &parts.headers;
30
31 let creds = headers
33 .get("authorization")
34 .and_then(|v| v.to_str().ok())
35 .and_then(parse_basic_auth);
36
37 let creds = creds.or_else(|| {
39 headers
40 .get("skynet_auth_uuid")
41 .zip(headers.get("skynet_auth_token"))
42 .and_then(|(u, t)| {
43 Some((
44 u.to_str().ok()?.to_string(),
45 t.to_str().ok()?.to_string(),
46 ))
47 })
48 });
49
50 let (uuid_str, token) = creds.ok_or_else(|| {
51 ApiError::from(FreshBluError::Unauthorized).into_response()
52 })?;
53
54 let uuid = Uuid::parse_str(&uuid_str).map_err(|_| {
55 ApiError::from(FreshBluError::Unauthorized).into_response()
56 })?;
57
58 let device = state
59 .store
60 .authenticate(&uuid, &token)
61 .await
62 .map_err(|e| ApiError::from(e).into_response())?
63 .ok_or_else(|| ApiError::from(FreshBluError::Unauthorized).into_response())?;
64
65 let as_uuid = headers
67 .get("x-meshblu-as")
68 .and_then(|v| v.to_str().ok())
69 .and_then(|v| Uuid::parse_str(v).ok());
70
71 Ok(AuthenticatedDevice(device, as_uuid))
72 }
73}