mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-07-29 08:31:45 +08:00
137 lines
3.6 KiB
Rust
137 lines
3.6 KiB
Rust
use sqlx::{sqlite::SqlitePoolOptions, Pool, Sqlite};
|
|
use std::path::Path;
|
|
use std::time::Duration;
|
|
|
|
use crate::error::Result;
|
|
|
|
#[derive(Clone)]
|
|
pub struct DatabasePool {
|
|
pool: Pool<Sqlite>,
|
|
}
|
|
|
|
impl DatabasePool {
|
|
pub async fn new(db_path: &Path) -> Result<Self> {
|
|
if let Some(parent) = db_path.parent() {
|
|
tokio::fs::create_dir_all(parent).await?;
|
|
}
|
|
|
|
let db_url = format!("sqlite:{}?mode=rwc", db_path.display());
|
|
|
|
let pool = SqlitePoolOptions::new()
|
|
.max_connections(4)
|
|
.acquire_timeout(Duration::from_secs(5))
|
|
.idle_timeout(Duration::from_secs(300))
|
|
.connect(&db_url)
|
|
.await?;
|
|
|
|
Ok(Self { pool })
|
|
}
|
|
|
|
pub async fn init_schema(&self) -> Result<()> {
|
|
self.create_config_table().await?;
|
|
self.create_users_table().await?;
|
|
self.create_user_totp_credentials_table().await?;
|
|
self.create_api_tokens_table().await?;
|
|
self.create_wol_history_table().await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn create_config_table(&self) -> Result<()> {
|
|
sqlx::query(
|
|
r#"
|
|
CREATE TABLE IF NOT EXISTS config (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
"#,
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn create_users_table(&self) -> Result<()> {
|
|
sqlx::query(
|
|
r#"
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
username TEXT NOT NULL UNIQUE,
|
|
password_hash TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
"#,
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn create_api_tokens_table(&self) -> Result<()> {
|
|
sqlx::query(
|
|
r#"
|
|
CREATE TABLE IF NOT EXISTS api_tokens (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
token_hash TEXT NOT NULL,
|
|
permissions TEXT NOT NULL,
|
|
expires_at TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
last_used TEXT
|
|
)
|
|
"#,
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn create_user_totp_credentials_table(&self) -> Result<()> {
|
|
sqlx::query(
|
|
r#"
|
|
CREATE TABLE IF NOT EXISTS user_totp_credentials (
|
|
user_id TEXT PRIMARY KEY,
|
|
secret TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
)
|
|
"#,
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn create_wol_history_table(&self) -> Result<()> {
|
|
sqlx::query(
|
|
r#"
|
|
CREATE TABLE IF NOT EXISTS wol_history (
|
|
mac_address TEXT PRIMARY KEY,
|
|
updated_at INTEGER NOT NULL
|
|
)
|
|
"#,
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
|
|
sqlx::query(
|
|
r#"
|
|
CREATE INDEX IF NOT EXISTS idx_wol_history_updated_at
|
|
ON wol_history(updated_at DESC)
|
|
"#,
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn pool(&self) -> &Pool<Sqlite> {
|
|
&self.pool
|
|
}
|
|
|
|
pub fn clone_pool(&self) -> Pool<Sqlite> {
|
|
self.pool.clone()
|
|
}
|
|
}
|