1pub mod bus;
2pub mod config;
3pub mod handlers;
4pub mod hub;
5pub mod local_bus;
6pub mod metrics;
7pub mod mqtt;
8pub mod nats_bus;
9pub mod presence;
10pub mod rate_limit;
11pub mod webhook;
12pub mod ws;
13
14use axum::{
15 http::StatusCode,
16 response::{IntoResponse, Response},
17 routing::{delete, get, post, put},
18 Json, Router,
19};
20use freshblu_core::error::FreshBluError;
21use freshblu_store::DynStore;
22use serde_json::json;
23use std::sync::Arc;
24use tower_http::{cors::CorsLayer, trace::TraceLayer};
25
26pub use bus::DynBus;
27pub use config::ServerConfig;
28pub use hub::MessageHub;
29pub use rate_limit::RateLimiter;
30pub use webhook::WebhookExecutor;
31
32pub struct ApiError(pub FreshBluError);
34
35impl From<FreshBluError> for ApiError {
36 fn from(e: FreshBluError) -> Self {
37 ApiError(e)
38 }
39}
40
41impl IntoResponse for ApiError {
42 fn into_response(self) -> Response {
43 let status =
44 StatusCode::from_u16(self.0.http_status()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
45 let body = json!({ "error": self.0.to_string() });
46 (status, Json(body)).into_response()
47 }
48}
49
50#[derive(Clone)]
52pub struct AppState {
53 pub store: DynStore,
54 pub bus: DynBus,
55 pub config: ServerConfig,
56 pub rate_limiter: Arc<RateLimiter>,
57 pub webhook_executor: Arc<WebhookExecutor>,
58}
59
60pub fn build_router(state: AppState) -> Router {
61 Router::new()
62 .route("/status", get(handlers::status::status))
64 .route("/healthcheck", get(handlers::status::healthcheck))
65 .route("/authenticate", post(handlers::auth::authenticate))
67 .route("/devices", post(handlers::devices::register))
69 .route("/devices/search", post(handlers::devices::search))
70 .route("/devices/:uuid", get(handlers::devices::get_device))
71 .route("/devices/:uuid", put(handlers::devices::update_device))
72 .route("/devices/:uuid", delete(handlers::devices::unregister))
73 .route("/v2/devices", post(handlers::devices::register))
75 .route("/v2/devices/:uuid", get(handlers::devices::get_device))
76 .route("/v2/devices/:uuid", put(handlers::devices::update_device))
77 .route("/v2/devices/:uuid", delete(handlers::devices::unregister))
78 .route("/v2/devices/search", post(handlers::devices::search))
79 .route("/v3/devices/:uuid", get(handlers::devices::get_device))
81 .route("/whoami", get(handlers::devices::whoami))
83 .route("/v2/whoami", get(handlers::devices::whoami))
84 .route("/messages", post(handlers::messages::send_message))
86 .route("/v2/messages", post(handlers::messages::send_message))
87 .route("/broadcasts", post(handlers::messages::broadcast))
89 .route("/mydevices", get(handlers::devices::my_devices))
91 .route(
93 "/claimdevice/:uuid",
94 post(handlers::devices::claim_device),
95 )
96 .route(
98 "/devices/:uuid/publickey",
99 get(handlers::devices::get_public_key),
100 )
101 .route("/publickey", get(handlers::status::server_public_key))
102 .route(
104 "/devices/:uuid/subscriptions",
105 post(handlers::subscriptions::create_subscription),
106 )
107 .route(
108 "/devices/:uuid/subscriptions",
109 get(handlers::subscriptions::list_subscriptions),
110 )
111 .route(
112 "/devices/:uuid/subscriptions/:emitter_uuid/:sub_type",
113 delete(handlers::subscriptions::delete_subscription),
114 )
115 .route(
117 "/devices/:uuid/tokens",
118 post(handlers::tokens::generate_token),
119 )
120 .route(
121 "/devices/:uuid/tokens/:token",
122 delete(handlers::tokens::revoke_token),
123 )
124 .route(
125 "/devices/:uuid/token",
126 post(handlers::tokens::reset_token),
127 )
128 .route(
130 "/search/tokens",
131 post(handlers::tokens::search_tokens),
132 )
133 .route("/subscribe", get(handlers::subscribe::subscribe))
135 .route("/ws", get(ws::ws_handler))
137 .route("/socket.io", get(ws::ws_handler))
138 .route("/metrics", get(metrics::metrics_handler))
140 .layer(CorsLayer::permissive())
142 .layer(TraceLayer::new_for_http())
143 .with_state(state)
144}