refactor(web): consolidate routing and expose auth handler

- Add `*.log` to `.gitignore` to exclude log files from version control.
- Change `auth_handler` to `pub` in `src/auth/mod.rs` to make the endpoint publicly accessible.
- Remove unused `bot_index` import and route; replace direct service registration with `web_server::configure_app` in `src/main.rs`.
- Refactor `src/web_server/mod.rs`:
  - Remove the `bot_index` handler.
  - Introduce `serve_html` helper for loading HTML pages.
  - Simplify static file serving by configuring separate routes for JS and CSS assets.
  - Centralize all route and static file configuration in `configure_app`.
- Clean up related imports and improve error handling for missing pages.
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-11-17 10:00:12 -03:00
parent 737f934d68
commit f9a1e3a8c0
7 changed files with 772 additions and 774 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
*.log
target*
.env
*.env

View file

@ -11,7 +11,7 @@ impl AuthService {
}
}
#[actix_web::get("/api/auth")]
async fn auth_handler(
pub async fn auth_handler(
_req: HttpRequest,
data: web::Data<AppState>,
web::Query(params): web::Query<HashMap<String, String>>,

View file

@ -46,7 +46,6 @@ use crate::session::{create_session, get_session_history, get_sessions, start_se
use crate::shared::state::AppState;
use crate::shared::utils::create_conn;
use crate::shared::utils::create_s3_operator;
use crate::web_server::{bot_index};
#[derive(Debug, Clone)]
pub enum BootstrapProgress {
StartingBootstrap,
@ -306,7 +305,6 @@ async fn main() -> std::io::Result<()> {
.wrap(Logger::default())
.wrap(Logger::new("HTTP REQUEST: %a %{User-Agent}i"))
.app_data(web::Data::from(app_state_clone))
.configure(web_server::configure_app)
.service(auth_handler)
.service(create_session)
.service(get_session_history)
@ -332,7 +330,8 @@ async fn main() -> std::io::Result<()> {
.service(save_draft)
.service(save_click);
}
app = app.service(bot_index);
app = app.configure(web_server::configure_app);
app
})
.workers(worker_count)

View file

@ -14,15 +14,12 @@ async fn index() -> Result<HttpResponse> {
}
}
#[actix_web::get("/{botname}")]
async fn bot_index(req: HttpRequest) -> Result<HttpResponse> {
let botname = req.match_info().query("botname");
debug!("Serving bot interface for: {}", botname);
match fs::read_to_string("web/desktop/index.html") {
async fn serve_html(path: &str) -> Result<HttpResponse> {
match fs::read_to_string(format!("web/desktop/{}", path)) {
Ok(html) => Ok(HttpResponse::Ok().content_type("text/html").body(html)),
Err(e) => {
error!("Failed to load index page for bot {}: {}", botname, e);
Ok(HttpResponse::InternalServerError().body("Failed to load index page"))
error!("Failed to load page {}: {}", path, e);
Ok(HttpResponse::InternalServerError().body("Failed to load page"))
}
}
}
@ -30,16 +27,6 @@ async fn bot_index(req: HttpRequest) -> Result<HttpResponse> {
pub fn configure_app(cfg: &mut actix_web::web::ServiceConfig) {
let static_path = Path::new("./web/desktop");
// Serve all static files from desktop directory
cfg.service(
Files::new("/", static_path)
.index_file("index.html")
.prefer_utf8(true)
.use_last_modified(true)
.use_etag(true)
.show_files_listing()
);
// Serve all JS files
cfg.service(
Files::new("/js", static_path.join("js"))
@ -48,17 +35,42 @@ pub fn configure_app(cfg: &mut actix_web::web::ServiceConfig) {
.use_etag(true)
);
// Serve all component directories
["drive", "tasks", "mail"].iter().for_each(|dir| {
// Serve CSS files
cfg.service(
Files::new(&format!("/{}", dir), static_path.join(dir))
Files::new("/css", static_path.join("css"))
.prefer_utf8(true)
.use_last_modified(true)
.use_etag(true)
);
});
// Serve index routes
cfg.service(
Files::new("/drive", static_path.join("drive"))
.prefer_utf8(true)
.use_last_modified(true)
.use_etag(true)
);
cfg.service(
Files::new("/chat", static_path.join("chat"))
.prefer_utf8(true)
.use_last_modified(true)
.use_etag(true)
);
cfg.service(
Files::new("/mail", static_path.join("mail"))
.prefer_utf8(true)
.use_last_modified(true)
.use_etag(true)
);
cfg.service(
Files::new("/tasks", static_path.join("tasks"))
.prefer_utf8(true)
.use_last_modified(true)
.use_etag(true)
);
cfg.service(index);
cfg.service(bot_index);
}

View file

@ -1,111 +1,23 @@
<!doctype html>
<html lang="pt-br">
<head>
<meta charset="utf-8"/>
<title>General Bots Chat</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<link rel="stylesheet" href="chat.css">
</head>
<body>
<div class="connection-status connecting" id="connectionStatus"></div>
<div class="flash-overlay" id="flashOverlay"></div>
<div class="float-menu">
<div class="float-logo" id="floatLogo" title="Menu"></div>
<div class="menu-button" id="themeBtn" title="Theme"></div>
</div>
<div class="sidebar" id="sidebar">
<div class="sidebar-header">
<div class="sidebar-logo"></div>
<div class="sidebar-title" id="sidebarTitle">General Bots Chat</div>
</div>
<button class="sidebar-button" id="voiceToggle" onclick="toggleVoiceMode()">🎤 Voice Mode</button>
<div class="history-section">
<div class="history-title">History</div>
<div id="history"></div>
</div>
</div>
<!-- Chat layout analogous to Drive layout -->
<div class="chat-layout" x-data="chatApp()" x-cloak>
<div class="panel chat-sidebar">
<div style="padding: 1rem; border-bottom: 1px solid #334155;">
<h3>General Bots Chat</h3>
</div>
<template x-for="item in navItems" :key="item.name">
<div class="nav-item"
:class="{ active: current === item.name }"
@click="current = item.name">
<span x-text="item.icon"></span>
<span x-text="item.name"></span>
</div>
</template>
</div>
<div class="panel chat-main">
<div style="padding: 1rem; border-bottom: 1px solid #334155;">
<h2 x-text="current"></h2>
<input type="text" x-model="search" placeholder="Search chats..."
style="width: 100%; margin-top: 0.5rem; padding: 0.5rem; background: #0f172a; border: 1px solid #334155; border-radius: 0.375rem; color: #e2e8f0;">
<div id="connectionStatus" class="connection-status disconnected"></div>
<main id="messages"></main>
<footer>
<div class="suggestions-container" id="suggestions"></div>
<div class="input-container">
<input id="messageInput" type="text" placeholder="Message..." autofocus />
<button id="voiceBtn" title="Voice">🎤</button>
<button id="sendBtn" title="Send"></button>
</div>
<div class="chat-list">
<template x-for="chat in filteredChats" :key="chat.id">
<div class="chat-item"
:class="{ selected: selectedChat?.id === chat.id }"
@click="selectedChat = chat">
<span class="chat-icon" x-text="chat.icon"></span>
<div style="flex: 1;">
<div style="font-weight: 600;" x-text="chat.name"></div>
<div class="text-xs text-gray" x-text="chat.lastMessage"></div>
</div>
<div class="text-sm text-gray" x-text="chat.time"></div>
</div>
</template>
</footer>
<button class="scroll-to-bottom" id="scrollToBottom"></button>
<div class="context-indicator" id="contextIndicator">
<div>Context</div>
<div id="contextPercentage">0%</div>
<div class="context-progress">
<div class="context-progress-bar" id="contextProgressBar" style="width:0%"></div>
</div>
</div>
<div class="panel chat-details">
<template x-if="selectedChat">
<div style="padding: 2rem;">
<div style="text-align: center; margin-bottom: 2rem;">
<div style="font-size: 4rem; margin-bottom: 1rem;" x-text="selectedChat.icon"></div>
<h3 x-text="selectedChat.name"></h3>
<p class="text-sm text-gray" x-text="selectedChat.status"></p>
</div>
<div style="margin-bottom: 1rem;">
<div class="text-sm" style="margin-bottom: 0.5rem;">Last Message</div>
<div class="text-gray" x-text="selectedChat.lastMessage"></div>
</div>
<div style="margin-bottom: 1rem;">
<div class="text-sm" style="margin-bottom: 0.5rem;">Time</div>
<div class="text-gray" x-text="selectedChat.time"></div>
</div>
<div style="display: flex; gap: 0.5rem; margin-top: 2rem;">
<button style="flex: 1; padding: 0.75rem; background: #3b82f6; color: white; border: none; border-radius: 0.375rem; cursor: pointer;">Reply</button>
<button style="flex: 1; padding: 0.75rem; background: #10b981; color: white; border: none; border-radius: 0.375rem; cursor: pointer;">Close</button>
</div>
</div>
</template>
<template x-if="!selectedChat">
<div style="padding: 2rem; text-align: center; color: #64748b;">
<div style="font-size: 4rem; margin-bottom: 1rem;">💬</div>
<p>Select a chat to view details</p>
</div>
</template>
</div>
</div>
<footer>
<div class="suggestions-container" id="suggestions"></div>
<div class="input-container">
<input id="messageInput" type="text" placeholder="Message..." autofocus/>
<button id="voiceBtn" title="Voice">🎤</button>
<button id="sendBtn" title="Send"></button>
</div>
</footer>
<script src="chat.js"></script>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>General Bots Desktop</title>
<title>General Bots</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="stylesheet" href="css/app.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script defer src="js/alpine.js"></script>
</head>
<body>
<nav x-data="{ current: 'drive' }">
<div class="logo">⚡ General Bots</div>
@ -27,16 +33,11 @@
<!-- Load Module Scripts -->
<script src="js/layout.js"></script>
<script src="chat/chat.js"></script>
<script src="drive/drive.js"></script>
<script src="tasks/tasks.js"></script>
<script src="mail/mail.js"></script>
<script src="dashboard/dashboard.js"></script>
<script src="editor/editor.js"></script>
<script src="player/player.js"></script>
<script src="paper/paper.js"></script>
<script src="settings/settings.js"></script>
<script src="tables/tables.js"></script>
<script src="news/news.js"></script>
</body>
</html>