use axum::{ Router, routing::{get, post}, }; use axum_client_ip::ClientIpSource; use based::auth::User; use owl::{prelude::*, set_global_db}; use rand::RngCore; use std::{net::SocketAddr, path::PathBuf}; mod api; mod herd_core; use crate::herd_core::mqtt::{handle_mqtt, listen_to_devices}; use herd_core::model::Machine; use herd_core::{ config::Config, route::{join_device, login_user}, }; use sage::Identity; use tokio::sync::OnceCell; pub static IDENTITY: OnceCell = OnceCell::const_new(); pub static CONFIG: OnceCell = OnceCell::const_new(); fn generate_token() -> String { let mut rng = rand::rng(); let mut token = vec![0u8; 32]; rng.fill_bytes(&mut token); hex::encode(token) } #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); let i = if let Some(i) = Identity::try_load(&PathBuf::from("./herd")) { i } else { let i = Identity::new(); i.save(&PathBuf::from("./herd")); i }; let _ = crate::IDENTITY.set(i); let config = Config::default(); let _ = crate::CONFIG.set(config); let db = Database::filesystem("./herd/db"); set_global_db!(db); let _ = User::create("admin".to_string(), "admin", based::auth::UserRole::Admin).await; let device = Router::new() .route("/join", post(join_device)) .layer(ClientIpSource::ConnectInfo.into_extension()); // Direct IP // .layer(ClientIpSource::XRealIp.into_extension()) // Proxy let user = Router::new().route("/login", post(login_user)); let app = Router::new().merge(device).merge(user); log::info!("Starting server"); let (client, eventloop) = api::mqtt_connect("server", &crate::CONFIG.get().unwrap().mqtt); listen_to_devices(&client).await; tokio::spawn(async { let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap(); axum::serve( listener, app.into_make_service_with_connect_info::(), ) .await .unwrap(); }); api::run_event_loop(eventloop, handle_mqtt).await; }