mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 19:04:23 +08:00
先提交上去
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
use parking_lot::RwLock;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tauri::State;
|
||||
|
||||
use crate::db::connection::{create_postgres_connection, create_sqlite_connection};
|
||||
use crate::services::permission::PermissionLevel;
|
||||
use crate::state::AppState;
|
||||
|
||||
use super::response::IpcResponse;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct TestConnectionResult {
|
||||
pub success: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SwitchConnectionResult {
|
||||
#[serde(rename = "type")]
|
||||
pub db_type: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DatabaseStatus {
|
||||
#[serde(rename = "type")]
|
||||
pub db_type: String,
|
||||
pub connected: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SyncResult {
|
||||
pub success: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub message: Option<String>,
|
||||
}
|
||||
|
||||
fn check_admin_permission(state: &Arc<RwLock<AppState>>) -> Result<(), String> {
|
||||
let state_guard = state.read();
|
||||
let mut permissions = state_guard.permissions.write();
|
||||
let sender_id = 0;
|
||||
if !permissions.require_permission(sender_id, PermissionLevel::Admin) {
|
||||
return Err("Permission denied: Admin required".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn db_test_connection(
|
||||
connection_string: String,
|
||||
_state: State<'_, Arc<RwLock<AppState>>>,
|
||||
) -> Result<IpcResponse<TestConnectionResult>, String> {
|
||||
let result = if connection_string.starts_with("sqlite://") {
|
||||
let path = connection_string
|
||||
.strip_prefix("sqlite://")
|
||||
.unwrap_or(&connection_string);
|
||||
match create_sqlite_connection(path).await {
|
||||
Ok(conn) => {
|
||||
let _ = conn.close().await;
|
||||
TestConnectionResult {
|
||||
success: true,
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
Err(e) => TestConnectionResult {
|
||||
success: false,
|
||||
error: Some(e.to_string()),
|
||||
},
|
||||
}
|
||||
} else if connection_string.starts_with("postgres://")
|
||||
|| connection_string.starts_with("postgresql://")
|
||||
{
|
||||
match create_postgres_connection(&connection_string).await {
|
||||
Ok(conn) => {
|
||||
let _ = conn.close().await;
|
||||
TestConnectionResult {
|
||||
success: true,
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
Err(e) => TestConnectionResult {
|
||||
success: false,
|
||||
error: Some(e.to_string()),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
let path = connection_string.as_str();
|
||||
match create_sqlite_connection(path).await {
|
||||
Ok(conn) => {
|
||||
let _ = conn.close().await;
|
||||
TestConnectionResult {
|
||||
success: true,
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
Err(e) => TestConnectionResult {
|
||||
success: false,
|
||||
error: Some(e.to_string()),
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
Ok(IpcResponse::success(result))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn db_switch_connection(
|
||||
connection_string: String,
|
||||
state: State<'_, Arc<RwLock<AppState>>>,
|
||||
) -> Result<IpcResponse<SwitchConnectionResult>, String> {
|
||||
check_admin_permission(&state)?;
|
||||
|
||||
let db_type = if connection_string.starts_with("postgres://")
|
||||
|| connection_string.starts_with("postgresql://")
|
||||
{
|
||||
let conn = create_postgres_connection(&connection_string)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let state_guard = state.read();
|
||||
let mut db_guard = state_guard.db.write();
|
||||
*db_guard = Some(conn);
|
||||
|
||||
"postgresql".to_string()
|
||||
} else {
|
||||
let path = if connection_string.starts_with("sqlite://") {
|
||||
connection_string
|
||||
.strip_prefix("sqlite://")
|
||||
.unwrap_or(&connection_string)
|
||||
.to_string()
|
||||
} else {
|
||||
connection_string
|
||||
};
|
||||
|
||||
let conn = create_sqlite_connection(&path)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let state_guard = state.read();
|
||||
let mut db_guard = state_guard.db.write();
|
||||
*db_guard = Some(conn);
|
||||
|
||||
"sqlite".to_string()
|
||||
};
|
||||
|
||||
Ok(IpcResponse::success(SwitchConnectionResult { db_type }))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn db_get_status(
|
||||
state: State<'_, Arc<RwLock<AppState>>>,
|
||||
) -> Result<IpcResponse<DatabaseStatus>, String> {
|
||||
let state_guard = state.read();
|
||||
let db_guard = state_guard.db.read();
|
||||
let connected = db_guard.is_some();
|
||||
|
||||
let db_type = if connected {
|
||||
let settings = state_guard.settings.read();
|
||||
let status_json =
|
||||
settings.get_value(crate::services::settings::SettingsKey::PgConnectionStatus);
|
||||
match status_json {
|
||||
crate::services::settings::SettingsValue::Json(json) => json
|
||||
.get("type")
|
||||
.and_then(|t| t.as_str())
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(|| "sqlite".to_string()),
|
||||
_ => "sqlite".to_string(),
|
||||
}
|
||||
} else {
|
||||
"sqlite".to_string()
|
||||
};
|
||||
|
||||
Ok(IpcResponse::success(DatabaseStatus {
|
||||
db_type,
|
||||
connected,
|
||||
error: None,
|
||||
}))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn db_sync(
|
||||
state: State<'_, Arc<RwLock<AppState>>>,
|
||||
) -> Result<IpcResponse<SyncResult>, String> {
|
||||
check_admin_permission(&state)?;
|
||||
|
||||
let state_guard = state.read();
|
||||
let db_guard = state_guard.db.read();
|
||||
if let Some(conn) = db_guard.as_ref() {
|
||||
match conn.ping().await {
|
||||
Ok(_) => Ok(IpcResponse::success(SyncResult {
|
||||
success: true,
|
||||
message: Some("Database synchronized successfully".to_string()),
|
||||
})),
|
||||
Err(e) => Ok(IpcResponse::success(SyncResult {
|
||||
success: false,
|
||||
message: Some(format!("Sync failed: {}", e)),
|
||||
})),
|
||||
}
|
||||
} else {
|
||||
Ok(IpcResponse::success(SyncResult {
|
||||
success: false,
|
||||
message: Some("No database connection".to_string()),
|
||||
}))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user