Implement real code, remove dead code
- AppState now uses BotServerClient directly - BOTSERVER_URL env var support for configuration - index() handler properly integrated into router - Removed unused web module (DTOs were never used) - Removed all #[allow(dead_code)] attributes - Zero warnings, cargo audit clean
This commit is contained in:
parent
38fc25b2a2
commit
0143ad49b1
7 changed files with 109 additions and 226 deletions
22
src/lib.rs
22
src/lib.rs
|
|
@ -8,25 +8,9 @@
|
||||||
//! For desktop/mobile native features, see the `botapp` crate which
|
//! For desktop/mobile native features, see the `botapp` crate which
|
||||||
//! wraps this pure web UI with Tauri.
|
//! wraps this pure web UI with Tauri.
|
||||||
|
|
||||||
// Re-export common types from botlib
|
|
||||||
pub use botlib::{
|
|
||||||
branding, error, init_branding, is_white_label, platform_name, platform_short, ApiResponse,
|
|
||||||
BotError, BotResponse, BotResult, MessageType, Session, Suggestion, UserMessage,
|
|
||||||
};
|
|
||||||
|
|
||||||
// HTTP client is always available via botlib
|
|
||||||
pub use botlib::BotServerClient;
|
|
||||||
|
|
||||||
pub mod shared;
|
pub mod shared;
|
||||||
|
|
||||||
#[cfg(feature = "ui-server")]
|
|
||||||
pub mod ui_server;
|
pub mod ui_server;
|
||||||
|
|
||||||
#[cfg(feature = "ui-server")]
|
// Re-export commonly used types
|
||||||
pub mod web;
|
pub use shared::AppState;
|
||||||
|
pub use ui_server::configure_router;
|
||||||
// Re-exports
|
|
||||||
pub use shared::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "ui-server")]
|
|
||||||
pub use ui_server::*;
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ use log::info;
|
||||||
|
|
||||||
mod shared;
|
mod shared;
|
||||||
mod ui_server;
|
mod ui_server;
|
||||||
mod web;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
//! Shared types and state management for BotUI
|
//! Shared types and state management for BotUI
|
||||||
//!
|
//!
|
||||||
//! This module re-exports common types from botlib and provides
|
//! This module provides shared application state and utilities
|
||||||
//! UI-specific shared functionality.
|
//! used across the UI server.
|
||||||
|
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
|
||||||
// Re-export from botlib for convenience
|
pub use state::AppState;
|
||||||
|
|
||||||
// Local re-exports
|
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,33 @@
|
||||||
//! Application state management
|
//! Application state management
|
||||||
//!
|
//!
|
||||||
//! This module contains the shared application state that is passed to all
|
//! This module contains the shared application state that is passed to all
|
||||||
//! route handlers and provides access to database connections, configuration,
|
//! route handlers and provides access to the BotServer client.
|
||||||
//! and other shared resources.
|
|
||||||
|
|
||||||
#![allow(dead_code)] // Prepared for future use
|
|
||||||
|
|
||||||
|
use botlib::http_client::BotServerClient;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
/// Database connection pool type
|
|
||||||
/// This would typically be a real connection pool in production
|
|
||||||
pub type DbPool = Arc<RwLock<()>>;
|
|
||||||
|
|
||||||
/// Application state shared across all handlers
|
/// Application state shared across all handlers
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
/// Database connection pool
|
/// HTTP client for communicating with BotServer
|
||||||
pub conn: Arc<std::sync::Mutex<()>>,
|
pub client: Arc<BotServerClient>,
|
||||||
/// Configuration cache
|
|
||||||
pub config: Arc<RwLock<std::collections::HashMap<String, String>>>,
|
|
||||||
/// Session store
|
|
||||||
pub sessions: Arc<RwLock<std::collections::HashMap<String, Session>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// User session information
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Session {
|
|
||||||
pub user_id: String,
|
|
||||||
pub username: String,
|
|
||||||
pub email: String,
|
|
||||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
|
||||||
pub expires_at: chrono::DateTime<chrono::Utc>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
/// Create a new application state
|
/// Create a new application state
|
||||||
|
///
|
||||||
|
/// Uses BOTSERVER_URL environment variable if set, otherwise defaults to localhost:8080
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
let url = std::env::var("BOTSERVER_URL").ok();
|
||||||
Self {
|
Self {
|
||||||
conn: Arc::new(std::sync::Mutex::new(())),
|
client: Arc::new(BotServerClient::new(url)),
|
||||||
config: Arc::new(RwLock::new(std::collections::HashMap::new())),
|
|
||||||
sessions: Arc::new(RwLock::new(std::collections::HashMap::new())),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the BotServer is healthy
|
||||||
|
pub async fn health_check(&self) -> bool {
|
||||||
|
self.client.health_check().await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AppState {
|
impl Default for AppState {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
//!
|
//!
|
||||||
//! Serves the web UI (suite, minimal) and handles API proxying.
|
//! Serves the web UI (suite, minimal) and handles API proxying.
|
||||||
|
|
||||||
#![allow(dead_code)] // Some functions prepared for future use
|
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::State,
|
extract::State,
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
|
|
@ -12,17 +10,16 @@ use axum::{
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::{fs, path::PathBuf, sync::Arc};
|
use std::{fs, path::PathBuf};
|
||||||
use tower_http::services::ServeDir;
|
|
||||||
|
|
||||||
use botlib::http_client::BotServerClient;
|
use crate::shared::AppState;
|
||||||
|
|
||||||
// Serve minimal UI (default at /)
|
/// Serve the index page (minimal UI)
|
||||||
pub async fn index() -> impl IntoResponse {
|
pub async fn index() -> impl IntoResponse {
|
||||||
serve_minimal().await
|
serve_minimal().await
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler for minimal UI
|
/// Handler for minimal UI
|
||||||
pub async fn serve_minimal() -> impl IntoResponse {
|
pub async fn serve_minimal() -> impl IntoResponse {
|
||||||
match fs::read_to_string("ui/minimal/index.html") {
|
match fs::read_to_string("ui/minimal/index.html") {
|
||||||
Ok(html) => (StatusCode::OK, [("content-type", "text/html")], Html(html)),
|
Ok(html) => (StatusCode::OK, [("content-type", "text/html")], Html(html)),
|
||||||
|
|
@ -37,7 +34,7 @@ pub async fn serve_minimal() -> impl IntoResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler for suite UI
|
/// Handler for suite UI
|
||||||
pub async fn serve_suite() -> impl IntoResponse {
|
pub async fn serve_suite() -> impl IntoResponse {
|
||||||
match fs::read_to_string("ui/suite/index.html") {
|
match fs::read_to_string("ui/suite/index.html") {
|
||||||
Ok(html) => (StatusCode::OK, [("content-type", "text/html")], Html(html)),
|
Ok(html) => (StatusCode::OK, [("content-type", "text/html")], Html(html)),
|
||||||
|
|
@ -52,49 +49,9 @@ pub async fn serve_suite() -> impl IntoResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn configure_router() -> Router {
|
/// Health check endpoint - checks BotServer connectivity
|
||||||
let suite_path = PathBuf::from("./ui/suite");
|
async fn health(State(state): State<AppState>) -> (StatusCode, axum::Json<serde_json::Value>) {
|
||||||
let minimal_path = PathBuf::from("./ui/minimal");
|
match state.health_check().await {
|
||||||
let client = Arc::new(BotServerClient::new(None));
|
|
||||||
|
|
||||||
Router::new()
|
|
||||||
// API health check
|
|
||||||
.route("/health", get(health))
|
|
||||||
.route("/api/health", get(api_health))
|
|
||||||
// Default route serves minimal UI
|
|
||||||
.route("/", get(root))
|
|
||||||
.route("/minimal", get(serve_minimal))
|
|
||||||
// Suite UI route
|
|
||||||
.route("/suite", get(serve_suite))
|
|
||||||
// Suite static assets (when accessing /suite/*)
|
|
||||||
.nest_service("/suite/js", ServeDir::new(suite_path.join("js")))
|
|
||||||
.nest_service("/suite/css", ServeDir::new(suite_path.join("css")))
|
|
||||||
.nest_service("/suite/public", ServeDir::new(suite_path.join("public")))
|
|
||||||
.nest_service("/suite/drive", ServeDir::new(suite_path.join("drive")))
|
|
||||||
.nest_service("/suite/chat", ServeDir::new(suite_path.join("chat")))
|
|
||||||
.nest_service("/suite/mail", ServeDir::new(suite_path.join("mail")))
|
|
||||||
.nest_service("/suite/tasks", ServeDir::new(suite_path.join("tasks")))
|
|
||||||
// Legacy paths for backward compatibility (serve suite assets)
|
|
||||||
.nest_service("/js", ServeDir::new(suite_path.join("js")))
|
|
||||||
.nest_service("/css", ServeDir::new(suite_path.join("css")))
|
|
||||||
.nest_service("/public", ServeDir::new(suite_path.join("public")))
|
|
||||||
.nest_service("/drive", ServeDir::new(suite_path.join("drive")))
|
|
||||||
.nest_service("/chat", ServeDir::new(suite_path.join("chat")))
|
|
||||||
.nest_service("/mail", ServeDir::new(suite_path.join("mail")))
|
|
||||||
.nest_service("/tasks", ServeDir::new(suite_path.join("tasks")))
|
|
||||||
// Fallback for other static files
|
|
||||||
.fallback_service(
|
|
||||||
ServeDir::new(minimal_path.clone()).fallback(
|
|
||||||
ServeDir::new(minimal_path.clone()).append_index_html_on_directories(true),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.with_state(client)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn health(
|
|
||||||
State(client): State<Arc<BotServerClient>>,
|
|
||||||
) -> (StatusCode, axum::Json<serde_json::Value>) {
|
|
||||||
match client.health_check().await {
|
|
||||||
true => (
|
true => (
|
||||||
StatusCode::OK,
|
StatusCode::OK,
|
||||||
axum::Json(serde_json::json!({
|
axum::Json(serde_json::json!({
|
||||||
|
|
@ -114,25 +71,95 @@ async fn health(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// API health check endpoint
|
||||||
async fn api_health() -> (StatusCode, axum::Json<serde_json::Value>) {
|
async fn api_health() -> (StatusCode, axum::Json<serde_json::Value>) {
|
||||||
(
|
(
|
||||||
StatusCode::OK,
|
StatusCode::OK,
|
||||||
axum::Json(serde_json::json!({
|
axum::Json(serde_json::json!({
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"version": "1.0.0"
|
"version": env!("CARGO_PKG_VERSION")
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn root() -> axum::Json<serde_json::Value> {
|
/// Configure and return the main router
|
||||||
axum::Json(serde_json::json!({
|
pub fn configure_router() -> Router {
|
||||||
"service": "BotUI",
|
let suite_path = PathBuf::from("./ui/suite");
|
||||||
"version": "1.0.0",
|
let minimal_path = PathBuf::from("./ui/minimal");
|
||||||
"description": "General Bots User Interface",
|
let state = AppState::new();
|
||||||
"endpoints": {
|
|
||||||
"health": "/health",
|
Router::new()
|
||||||
"api": "/api/health",
|
// Health check endpoints
|
||||||
"ui": "/"
|
.route("/health", get(health))
|
||||||
}
|
.route("/api/health", get(api_health))
|
||||||
}))
|
// UI routes
|
||||||
|
.route("/", get(index))
|
||||||
|
.route("/minimal", get(serve_minimal))
|
||||||
|
.route("/suite", get(serve_suite))
|
||||||
|
// Suite static assets (when accessing /suite/*)
|
||||||
|
.nest_service(
|
||||||
|
"/suite/js",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("js")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/suite/css",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("css")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/suite/public",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("public")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/suite/drive",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("drive")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/suite/chat",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("chat")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/suite/mail",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("mail")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/suite/tasks",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("tasks")),
|
||||||
|
)
|
||||||
|
// Legacy paths for backward compatibility (serve suite assets)
|
||||||
|
.nest_service(
|
||||||
|
"/js",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("js")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/css",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("css")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/public",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("public")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/drive",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("drive")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/chat",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("chat")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/mail",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("mail")),
|
||||||
|
)
|
||||||
|
.nest_service(
|
||||||
|
"/tasks",
|
||||||
|
tower_http::services::ServeDir::new(suite_path.join("tasks")),
|
||||||
|
)
|
||||||
|
// Fallback for other static files
|
||||||
|
.fallback_service(
|
||||||
|
tower_http::services::ServeDir::new(minimal_path.clone()).fallback(
|
||||||
|
tower_http::services::ServeDir::new(minimal_path)
|
||||||
|
.append_index_html_on_directories(true),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.with_state(state)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
#![cfg(not(feature = "desktop"))]
|
|
||||||
|
|
||||||
use axum::{extract::State, http::StatusCode, Json};
|
|
||||||
use serde_json::json;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::http_client::BotServerClient;
|
|
||||||
|
|
||||||
/// Health check endpoint
|
|
||||||
pub async fn health(
|
|
||||||
State(client): State<Arc<BotServerClient>>,
|
|
||||||
) -> (StatusCode, Json<serde_json::Value>) {
|
|
||||||
match client.health_check().await {
|
|
||||||
true => (
|
|
||||||
StatusCode::OK,
|
|
||||||
Json(json!({
|
|
||||||
"status": "healthy",
|
|
||||||
"service": "botui",
|
|
||||||
"mode": "web"
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
false => (
|
|
||||||
StatusCode::SERVICE_UNAVAILABLE,
|
|
||||||
Json(json!({
|
|
||||||
"status": "unhealthy",
|
|
||||||
"service": "botui",
|
|
||||||
"error": "botserver unreachable"
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// API health check endpoint
|
|
||||||
pub async fn api_health() -> (StatusCode, Json<serde_json::Value>) {
|
|
||||||
(
|
|
||||||
StatusCode::OK,
|
|
||||||
Json(json!({
|
|
||||||
"status": "ok",
|
|
||||||
"version": "1.0.0"
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Root endpoint
|
|
||||||
pub async fn root() -> Json<serde_json::Value> {
|
|
||||||
Json(json!({
|
|
||||||
"service": "BotUI",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "General Bots User Interface",
|
|
||||||
"endpoints": {
|
|
||||||
"health": "/health",
|
|
||||||
"api": "/api/health",
|
|
||||||
"ui": "/"
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
//! Web module with basic data structures
|
|
||||||
//!
|
|
||||||
//! Contains DTOs and types for the web API layer.
|
|
||||||
|
|
||||||
#![allow(dead_code)] // DTOs prepared for future use
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
/// Request/Response DTOs for web API
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
|
||||||
pub struct Message {
|
|
||||||
pub id: String,
|
|
||||||
pub session_id: String,
|
|
||||||
pub sender: String,
|
|
||||||
pub content: String,
|
|
||||||
pub timestamp: String,
|
|
||||||
pub is_user: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
pub struct ScanRequest {
|
|
||||||
pub bot_id: Option<String>,
|
|
||||||
pub include_info: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
pub struct IssueResponse {
|
|
||||||
pub id: String,
|
|
||||||
pub severity: String,
|
|
||||||
pub issue_type: String,
|
|
||||||
pub title: String,
|
|
||||||
pub description: String,
|
|
||||||
pub file_path: String,
|
|
||||||
pub line_number: Option<usize>,
|
|
||||||
pub code_snippet: Option<String>,
|
|
||||||
pub remediation: String,
|
|
||||||
pub category: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
pub struct ScanSummary {
|
|
||||||
pub total_issues: usize,
|
|
||||||
pub critical_count: usize,
|
|
||||||
pub high_count: usize,
|
|
||||||
pub total_files_scanned: usize,
|
|
||||||
pub compliance_score: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
pub struct ScanResponse {
|
|
||||||
pub scan_id: String,
|
|
||||||
pub issues: Vec<IssueResponse>,
|
|
||||||
pub summary: ScanSummary,
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue