Implement status.corrosionmgmt.com public status page showcasing all Corrosion servers that opt-in. Drives platform visibility and attracts new customers. Backend: - Migration 007: status_page_description TEXT column - models/public.rs: PublicServerStatus, PlatformHealth, StatusPageResponse - db/public.rs: get_public_servers() with uptime calculations (24h/7d/30d) - api/public.rs: GET /api/public/status (no auth) - api/settings.rs: public site config endpoints (auth required) Frontend: - StatusPageView.vue: Server grid with live stats, uptime badges, wipe schedules - Platform health header: total servers, online count, total players - Auto-refresh every 10 seconds via polling - Mobile-responsive design - SettingsView.vue: Public Status tab with opt-in toggle Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
86 lines
2.8 KiB
Rust
86 lines
2.8 KiB
Rust
use std::sync::Arc;
|
|
|
|
use axum::{
|
|
extract::State,
|
|
routing::{get, put},
|
|
Json, Router,
|
|
};
|
|
|
|
use crate::db;
|
|
use crate::middleware::auth::AuthUser;
|
|
use crate::models::error::{ApiError, ApiResult};
|
|
use crate::models::public::{PublicSiteConfig, UpdatePublicSiteRequest};
|
|
use crate::AppState;
|
|
|
|
pub fn router() -> Router<Arc<AppState>> {
|
|
Router::new()
|
|
.route("/public-site", get(get_public_site_settings))
|
|
.route("/public-site", put(update_public_site_settings))
|
|
}
|
|
|
|
/// GET /api/settings/public-site — Get public site configuration
|
|
async fn get_public_site_settings(
|
|
auth: AuthUser,
|
|
State(state): State<Arc<AppState>>,
|
|
) -> ApiResult<Json<PublicSiteConfig>> {
|
|
let license_id = auth.license_id.ok_or(ApiError::LicenseInvalid)?;
|
|
|
|
let config = db::public::get_public_site_config(&state.db, license_id)
|
|
.await
|
|
.map_err(|e| ApiError::Internal(format!("Failed to fetch config: {}", e)))?;
|
|
|
|
match config {
|
|
Some(cfg) => Ok(Json(cfg)),
|
|
None => {
|
|
// Create default config if none exists
|
|
let config_id = db::public::create_public_site_config(&state.db, license_id)
|
|
.await
|
|
.map_err(|e| ApiError::Internal(format!("Failed to create config: {}", e)))?;
|
|
|
|
// Fetch the newly created config
|
|
let new_config = db::public::get_public_site_config(&state.db, license_id)
|
|
.await
|
|
.map_err(|e| ApiError::Internal(format!("Failed to fetch new config: {}", e)))?
|
|
.ok_or_else(|| ApiError::Internal("Config creation failed".to_string()))?;
|
|
|
|
Ok(Json(new_config))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// PUT /api/settings/public-site — Update public site configuration
|
|
async fn update_public_site_settings(
|
|
auth: AuthUser,
|
|
State(state): State<Arc<AppState>>,
|
|
Json(req): Json<UpdatePublicSiteRequest>,
|
|
) -> ApiResult<Json<serde_json::Value>> {
|
|
let license_id = auth.license_id.ok_or(ApiError::LicenseInvalid)?;
|
|
|
|
// Ensure config exists
|
|
let config_exists = db::public::get_public_site_config(&state.db, license_id)
|
|
.await
|
|
.map_err(|e| ApiError::Internal(format!("Failed to check config: {}", e)))?;
|
|
|
|
if config_exists.is_none() {
|
|
db::public::create_public_site_config(&state.db, license_id)
|
|
.await
|
|
.map_err(|e| ApiError::Internal(format!("Failed to create config: {}", e)))?;
|
|
}
|
|
|
|
// Update fields
|
|
db::public::update_public_site_config(
|
|
&state.db,
|
|
license_id,
|
|
req.show_on_status_page,
|
|
req.status_page_description,
|
|
req.site_enabled,
|
|
)
|
|
.await
|
|
.map_err(|e| ApiError::Internal(format!("Failed to update config: {}", e)))?;
|
|
|
|
Ok(Json(serde_json::json!({
|
|
"success": true,
|
|
"message": "Public site settings updated"
|
|
})))
|
|
}
|