Menu
Public repository / master
AkurAI-Drive / backend/src/main.rs
Latest change beff27fc3a062a220cde556e7bb28da49f6d04ea - Drive login: recover oidc.rs (IdP PKCE + introspection) from deployed binary by AkurAI Agent
pub mod api;
pub mod auth;
pub mod config;
pub mod db;
pub mod device;
pub mod idp;
pub mod mcp;
pub mod oauth;
pub mod oidc;
pub mod pages;
pub mod session;
pub mod sigv4;
pub mod telemetry;
pub mod util;
use axum::{
Json, Router,
extract::Request,
http::StatusCode,
middleware::{self, Next},
response::{IntoResponse, Response},
routing::{get, post},
};
use serde_json::json;
#[tokio::main]
async fn main() {
akurai_log::init("akurai-drive-api");
tracing::info!("akurai-drive-api starting up");
let missing = config::missing_required(config::get());
if !missing.is_empty() {
tracing::error!(
"refusing to start: missing required environment variables: {}",
missing.join(", ")
);
std::process::exit(1);
}
// Trigger DB initialization (opens the connection, sets pragmas, creates tables).
db::with_db(|_conn| {});
let cfg = config::get();
let app = Router::new()
.route("/healthz", get(healthz))
.route("/api/health", get(api_health))
.route("/auth/login", get(auth::login))
.route("/auth/password", post(auth::password))
.route("/auth/callback", get(auth::callback))
.route("/auth/logout", get(auth::logout))
.route("/auth/device", get(auth::device))
.route("/mcp", post(mcp::handle))
.route("/.well-known/oauth-protected-resource", get(mcp::metadata))
.route(
"/.well-known/oauth-protected-resource/mcp",
get(mcp::metadata),
)
.route("/api/me", get(api::me))
.route(
"/api/storage",
get(api::storage_list).post(api::storage_create),
)
.route("/api/buckets", get(api::buckets))
.route("/api/files", get(api::files_list).delete(api::files_delete))
.route("/api/files/presign", post(api::files_presign))
.route("/api/client-logs", post(api::client_logs))
.route("/js/monitor-client.js", get(pages::monitor_client))
.route("/theme.js", get(pages::theme_js))
.route("/themes.css", get(pages::themes_css))
.route("/shared-shell.css", get(pages::shared_shell_css))
.route("/themes.json", get(pages::themes_json))
.route("/favicon.svg", get(pages::favicon))
.route("/apple-touch-icon.png", get(pages::apple_touch_icon))
.route("/app", get(pages::app))
.fallback(not_found)
.layer(middleware::from_fn(request_logger));
tracing::info!("listening on {}", cfg.listen_addr);
let listener = tokio::net::TcpListener::bind(&cfg.listen_addr)
.await
.expect("failed to bind listener");
axum::serve(listener, app).await.expect("server error");
}
async fn request_logger(req: Request, next: Next) -> Response {
let method = req.method().clone();
let path = req.uri().path().to_owned();
let response = next.run(req).await;
let status = response.status();
tracing::info!(%method, %path, %status, "request");
response
}
async fn healthz() -> impl IntoResponse {
Json(json!({"ok": true, "service": "akurai-drive-api"}))
}
// Fleet ops contract: GET /api/health -> {app, version, status}.
async fn api_health() -> impl IntoResponse {
Json(json!({
"app": "akurai-drive-api",
"version": env!("CARGO_PKG_VERSION"),
"status": "ok",
}))
}
async fn not_found() -> impl IntoResponse {
(StatusCode::NOT_FOUND, Json(json!({"error": "not found"})))
}