This commit is contained in:
2026-07-06 16:21:06 +08:00
commit bb9f685221
41 changed files with 4333 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
// Package db manages the SQLite database connection, schema migrations,
// and data access for server profiles and connection logs.
//
// It uses modernc.org/sqlite (a pure-Go driver) so the binary has no
// CGO dependency and cross-compiles trivially.
package db
import (
"database/sql"
"fmt"
"lmvpn/internal/paths"
_ "modernc.org/sqlite"
)
// Store wraps the database handle and provides data access methods.
type Store struct {
db *sql.DB
}
// Open creates or opens the SQLite database and runs migrations.
func Open() (*Store, error) {
db, err := sql.Open("sqlite", paths.DBPath()+"?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000)")
if err != nil {
return nil, fmt.Errorf("open db: %w", err)
}
db.SetMaxOpenConns(1) // sqlite serialises writes
s := &Store{db: db}
if err := s.migrate(); err != nil {
db.Close()
return nil, fmt.Errorf("migrate: %w", err)
}
return s, nil
}
// Close closes the database connection.
func (s *Store) Close() error {
return s.db.Close()
}
func (s *Store) migrate() error {
_, err := s.db.Exec(schema)
return err
}
const schema = `
CREATE TABLE IF NOT EXISTS server_profiles (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
server_url TEXT NOT NULL,
username TEXT NOT NULL,
auth_mode TEXT NOT NULL DEFAULT 'both',
routing_mode TEXT NOT NULL DEFAULT 'full',
custom_cidrs TEXT NOT NULL DEFAULT '',
mtu_override INTEGER NOT NULL DEFAULT 0,
auto_connect INTEGER NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
last_connected_at DATETIME
);
CREATE TABLE IF NOT EXISTS connection_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
profile_id INTEGER NOT NULL,
started_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ended_at DATETIME,
assigned_ip TEXT NOT NULL DEFAULT '',
rx_bytes INTEGER NOT NULL DEFAULT 0,
tx_bytes INTEGER NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'connected',
error_msg TEXT NOT NULL DEFAULT '',
FOREIGN KEY (profile_id) REFERENCES server_profiles(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_logs_profile ON connection_logs(profile_id);
`