Some checks failed
BotServer CI / build (push) Failing after 1m34s
Split 20+ files over 1000 lines into focused subdirectories for better maintainability and code organization. All changes maintain backward compatibility through re-export wrappers. Major splits: - attendance/llm_assist.rs (2074→7 modules) - basic/keywords/face_api.rs → face_api/ (7 modules) - basic/keywords/file_operations.rs → file_ops/ (8 modules) - basic/keywords/hear_talk.rs → hearing/ (6 modules) - channels/wechat.rs → wechat/ (10 modules) - channels/youtube.rs → youtube/ (5 modules) - contacts/mod.rs → contacts_api/ (6 modules) - core/bootstrap/mod.rs → bootstrap/ (5 modules) - core/shared/admin.rs → admin_*.rs (5 modules) - designer/canvas.rs → canvas_api/ (6 modules) - designer/mod.rs → designer_api/ (6 modules) - docs/handlers.rs → handlers_api/ (11 modules) - drive/mod.rs → drive_handlers.rs, drive_types.rs - learn/mod.rs → types.rs - main.rs → main_module/ (7 modules) - meet/webinar.rs → webinar_api/ (8 modules) - paper/mod.rs → (10 modules) - security/auth.rs → auth_api/ (7 modules) - security/passkey.rs → (4 modules) - sources/mod.rs → sources_api/ (5 modules) - tasks/mod.rs → task_api/ (5 modules) Stats: 38,040 deletions, 1,315 additions across 318 files Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
329 lines
10 KiB
Rust
329 lines
10 KiB
Rust
use crate::security::protection::{ProtectionManager, ProtectionTool};
|
|
use crate::security::protection::manager::ProtectionConfig;
|
|
use crate::core::shared::state::AppState;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::sync::Arc;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct SecurityToolResult {
|
|
pub tool: String,
|
|
pub success: bool,
|
|
pub installed: bool,
|
|
pub version: Option<String>,
|
|
pub running: Option<bool>,
|
|
pub message: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct SecurityScanResult {
|
|
pub tool: String,
|
|
pub success: bool,
|
|
pub status: String,
|
|
pub findings_count: usize,
|
|
pub warnings_count: usize,
|
|
pub score: Option<i32>,
|
|
pub report_path: Option<String>,
|
|
}
|
|
|
|
pub async fn security_tool_status(
|
|
_state: Arc<AppState>,
|
|
tool_name: &str,
|
|
) -> Result<SecurityToolResult, String> {
|
|
let tool = parse_tool_name(tool_name)?;
|
|
let manager = ProtectionManager::new(ProtectionConfig::default());
|
|
|
|
match manager.check_tool_status(tool).await {
|
|
Ok(status) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: true,
|
|
installed: status.installed,
|
|
version: status.version,
|
|
running: status.service_running,
|
|
message: if status.installed {
|
|
"Tool is installed".to_string()
|
|
} else {
|
|
"Tool is not installed".to_string()
|
|
},
|
|
}),
|
|
Err(e) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: false,
|
|
installed: false,
|
|
version: None,
|
|
running: None,
|
|
message: format!("Failed to check status: {e}"),
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub async fn security_run_scan(
|
|
_state: Arc<AppState>,
|
|
tool_name: &str,
|
|
) -> Result<SecurityScanResult, String> {
|
|
let tool = parse_tool_name(tool_name)?;
|
|
let manager = ProtectionManager::new(ProtectionConfig::default());
|
|
|
|
match manager.run_scan(tool).await {
|
|
Ok(result) => Ok(SecurityScanResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: true,
|
|
status: format!("{:?}", result.status),
|
|
findings_count: result.findings.len(),
|
|
warnings_count: result.warnings as usize,
|
|
score: None,
|
|
report_path: result.report_path,
|
|
}),
|
|
Err(error) => {
|
|
log::error!("Security scan failed for {tool_name}: {error}");
|
|
Ok(SecurityScanResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: false,
|
|
status: format!("error: {error}"),
|
|
findings_count: 0,
|
|
warnings_count: 0,
|
|
score: None,
|
|
report_path: None,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn security_get_report(
|
|
_state: Arc<AppState>,
|
|
tool_name: &str,
|
|
) -> Result<String, String> {
|
|
let tool = parse_tool_name(tool_name)?;
|
|
let manager = ProtectionManager::new(ProtectionConfig::default());
|
|
|
|
manager
|
|
.get_report(tool)
|
|
.await
|
|
.map_err(|e| format!("Failed to get report: {e}"))
|
|
}
|
|
|
|
pub async fn security_update_definitions(
|
|
_state: Arc<AppState>,
|
|
tool_name: &str,
|
|
) -> Result<SecurityToolResult, String> {
|
|
let tool = parse_tool_name(tool_name)?;
|
|
let manager = ProtectionManager::new(ProtectionConfig::default());
|
|
|
|
match manager.update_definitions(tool).await {
|
|
Ok(()) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: true,
|
|
installed: true,
|
|
version: None,
|
|
running: None,
|
|
message: "Definitions updated successfully".to_string(),
|
|
}),
|
|
Err(e) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: false,
|
|
installed: true,
|
|
version: None,
|
|
running: None,
|
|
message: format!("Failed to update definitions: {e}"),
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub async fn security_start_service(
|
|
_state: Arc<AppState>,
|
|
tool_name: &str,
|
|
) -> Result<SecurityToolResult, String> {
|
|
let tool = parse_tool_name(tool_name)?;
|
|
let manager = ProtectionManager::new(ProtectionConfig::default());
|
|
|
|
match manager.start_service(tool).await {
|
|
Ok(()) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: true,
|
|
installed: true,
|
|
version: None,
|
|
running: Some(true),
|
|
message: "Service started successfully".to_string(),
|
|
}),
|
|
Err(e) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: false,
|
|
installed: true,
|
|
version: None,
|
|
running: Some(false),
|
|
message: format!("Failed to start service: {e}"),
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub async fn security_stop_service(
|
|
_state: Arc<AppState>,
|
|
tool_name: &str,
|
|
) -> Result<SecurityToolResult, String> {
|
|
let tool = parse_tool_name(tool_name)?;
|
|
let manager = ProtectionManager::new(ProtectionConfig::default());
|
|
|
|
match manager.stop_service(tool).await {
|
|
Ok(()) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: true,
|
|
installed: true,
|
|
version: None,
|
|
running: Some(false),
|
|
message: "Service stopped successfully".to_string(),
|
|
}),
|
|
Err(e) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: false,
|
|
installed: true,
|
|
version: None,
|
|
running: None,
|
|
message: format!("Failed to stop service: {e}"),
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub async fn security_install_tool(
|
|
_state: Arc<AppState>,
|
|
tool_name: &str,
|
|
) -> Result<SecurityToolResult, String> {
|
|
let tool = parse_tool_name(tool_name)?;
|
|
let manager = ProtectionManager::new(ProtectionConfig::default());
|
|
|
|
match manager.install_tool(tool).await {
|
|
Ok(()) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: true,
|
|
installed: true,
|
|
version: None,
|
|
running: None,
|
|
message: "Tool installed successfully".to_string(),
|
|
}),
|
|
Err(e) => Ok(SecurityToolResult {
|
|
tool: tool_name.to_lowercase(),
|
|
success: false,
|
|
installed: false,
|
|
version: None,
|
|
running: None,
|
|
message: format!("Failed to install tool: {e}"),
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub async fn security_hardening_score(_state: Arc<AppState>) -> Result<i32, String> {
|
|
let manager = ProtectionManager::new(ProtectionConfig::default());
|
|
|
|
match manager.run_scan(ProtectionTool::Lynis).await {
|
|
Ok(_result) => Ok(0),
|
|
Err(e) => Err(format!("Failed to get hardening score: {e}")),
|
|
}
|
|
}
|
|
|
|
pub fn security_tool_is_installed(status: &SecurityToolResult) -> bool {
|
|
status.installed
|
|
}
|
|
|
|
pub fn security_service_is_running(status: &SecurityToolResult) -> bool {
|
|
status.running.unwrap_or(false)
|
|
}
|
|
|
|
fn parse_tool_name(name: &str) -> Result<ProtectionTool, String> {
|
|
ProtectionTool::from_str(name)
|
|
.ok_or_else(|| format!("Unknown security tool: {name}. Valid tools: lynis, rkhunter, chkrootkit, suricata, lmd, clamav"))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_parse_tool_name_valid() {
|
|
assert!(parse_tool_name("lynis").is_ok());
|
|
assert!(parse_tool_name("LYNIS").is_ok());
|
|
assert!(parse_tool_name("Lynis").is_ok());
|
|
assert!(parse_tool_name("rkhunter").is_ok());
|
|
assert!(parse_tool_name("chkrootkit").is_ok());
|
|
assert!(parse_tool_name("suricata").is_ok());
|
|
assert!(parse_tool_name("lmd").is_ok());
|
|
assert!(parse_tool_name("clamav").is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_tool_name_invalid() {
|
|
assert!(parse_tool_name("unknown").is_err());
|
|
assert!(parse_tool_name("").is_err());
|
|
assert!(parse_tool_name("invalid_tool").is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_security_tool_is_installed() {
|
|
let installed = SecurityToolResult {
|
|
tool: "lynis".to_string(),
|
|
success: true,
|
|
installed: true,
|
|
version: Some("3.0.9".to_string()),
|
|
running: None,
|
|
message: "Tool is installed".to_string(),
|
|
};
|
|
assert!(security_tool_is_installed(&installed));
|
|
|
|
let not_installed = SecurityToolResult {
|
|
tool: "lynis".to_string(),
|
|
success: true,
|
|
installed: false,
|
|
version: None,
|
|
running: None,
|
|
message: "Tool is not installed".to_string(),
|
|
};
|
|
assert!(!security_tool_is_installed(¬_installed));
|
|
}
|
|
|
|
#[test]
|
|
fn test_security_service_is_running() {
|
|
let running = SecurityToolResult {
|
|
tool: "suricata".to_string(),
|
|
success: true,
|
|
installed: true,
|
|
version: None,
|
|
running: Some(true),
|
|
message: "Service running".to_string(),
|
|
};
|
|
assert!(security_service_is_running(&running));
|
|
|
|
let stopped = SecurityToolResult {
|
|
tool: "suricata".to_string(),
|
|
success: true,
|
|
installed: true,
|
|
version: None,
|
|
running: Some(false),
|
|
message: "Service stopped".to_string(),
|
|
};
|
|
assert!(!security_service_is_running(&stopped));
|
|
|
|
let unknown = SecurityToolResult {
|
|
tool: "lynis".to_string(),
|
|
success: true,
|
|
installed: true,
|
|
version: None,
|
|
running: None,
|
|
message: "No service".to_string(),
|
|
};
|
|
assert!(!security_service_is_running(&unknown));
|
|
}
|
|
|
|
#[test]
|
|
fn test_security_scan_result_serialization() {
|
|
let result = SecurityScanResult {
|
|
tool: "lynis".to_string(),
|
|
success: true,
|
|
status: "completed".to_string(),
|
|
findings_count: 5,
|
|
warnings_count: 12,
|
|
score: Some(78),
|
|
report_path: Some("/var/log/lynis-report.dat".to_string()),
|
|
};
|
|
|
|
let json = serde_json::to_string(&result).expect("Failed to serialize");
|
|
assert!(json.contains("\"tool\":\"lynis\""));
|
|
assert!(json.contains("\"score\":78"));
|
|
}
|
|
}
|