use std::sync::Arc; use axum::{ extract::State, routing::{get, post, put}, Json, Router, }; use crate::db; use crate::middleware::auth::AuthUser; use crate::models::error::{ApiError, ApiResult}; use crate::AppState; pub fn router() -> Router> { Router::new() .route("/", get(get_server_overview)) .route("/connection", get(get_connection)) .route("/config", get(get_config)) .route("/config", put(update_config)) .route("/command", post(send_command)) .route("/admins", get(get_admins)) .route("/start", post(start_server)) .route("/stop", post(stop_server)) .route("/restart", post(restart_server)) } /// GET /api/servers — returns combined server overview (connection + config) async fn get_server_overview( auth: AuthUser, State(state): State>, ) -> ApiResult> { let license_id = auth.license_id.ok_or(ApiError::LicenseInvalid)?; let connection = db::servers::get_server_connection(&state.db, license_id) .await .map_err(|e| ApiError::Internal(e.to_string()))?; let config = db::servers::get_server_config(&state.db, license_id) .await .map_err(|e| ApiError::Internal(e.to_string()))?; Ok(Json(serde_json::json!({ "connection": connection, "config": config, }))) } /// GET /api/servers/connection async fn get_connection( auth: AuthUser, State(state): State>, ) -> ApiResult> { let license_id = auth.license_id.ok_or(ApiError::LicenseInvalid)?; let connection = db::servers::get_server_connection(&state.db, license_id) .await .map_err(|e| ApiError::Internal(e.to_string()))?; Ok(Json(serde_json::json!({ "connection": connection }))) } /// GET /api/servers/config async fn get_config( auth: AuthUser, State(state): State>, ) -> ApiResult> { let license_id = auth.license_id.ok_or(ApiError::LicenseInvalid)?; let config = db::servers::get_server_config(&state.db, license_id) .await .map_err(|e| ApiError::Internal(e.to_string()))?; Ok(Json(serde_json::json!({ "config": config }))) } #[derive(serde::Deserialize)] struct UpdateConfigRequest { server_name: Option, max_players: Option, world_size: Option, current_seed: Option, } /// PUT /api/servers/config async fn update_config( auth: AuthUser, State(state): State>, Json(body): Json, ) -> ApiResult> { let license_id = auth.license_id.ok_or(ApiError::LicenseInvalid)?; db::servers::update_server_config( &state.db, license_id, body.server_name.as_deref(), body.max_players, body.world_size, body.current_seed, ) .await .map_err(|e| ApiError::Internal(e.to_string()))?; Ok(Json(serde_json::json!({ "message": "Config updated" }))) } /// GET /api/servers/admins async fn get_admins( auth: AuthUser, State(state): State>, ) -> ApiResult> { let license_id = auth.license_id.ok_or(ApiError::LicenseInvalid)?; let admins = db::servers::get_game_admins(&state.db, license_id) .await .map_err(|e| ApiError::Internal(e.to_string()))?; Ok(Json(serde_json::json!({ "admins": admins }))) } /// POST /api/servers/command async fn send_command( _auth: AuthUser, State(_state): State>, ) -> ApiResult> { // TODO: Route command through PanelAdapter or NATS to game server Err(ApiError::BadRequest("Server command not yet implemented".to_string())) } /// POST /api/servers/start async fn start_server( _auth: AuthUser, State(_state): State>, ) -> ApiResult> { // TODO: Route through PanelAdapter Err(ApiError::BadRequest("Server start not yet implemented".to_string())) } /// POST /api/servers/stop async fn stop_server( _auth: AuthUser, State(_state): State>, ) -> ApiResult> { // TODO: Route through PanelAdapter Err(ApiError::BadRequest("Server stop not yet implemented".to_string())) } /// POST /api/servers/restart async fn restart_server( _auth: AuthUser, State(_state): State>, ) -> ApiResult> { // TODO: Route through PanelAdapter Err(ApiError::BadRequest("Server restart not yet implemented".to_string())) }