This commit is contained in:
@@ -4,33 +4,50 @@ import "github.com/gotunnel/pkg/protocol"
|
||||
|
||||
// Client 客户端数据
|
||||
type Client struct {
|
||||
ID string `json:"id"`
|
||||
Rules []protocol.ProxyRule `json:"rules"`
|
||||
ID string `json:"id"`
|
||||
Nickname string `json:"nickname,omitempty"`
|
||||
Rules []protocol.ProxyRule `json:"rules"`
|
||||
}
|
||||
|
||||
// PluginData 插件数据
|
||||
type PluginData struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Type string `json:"type"`
|
||||
Source string `json:"source"`
|
||||
Description string `json:"description"`
|
||||
Author string `json:"author"`
|
||||
Checksum string `json:"checksum"`
|
||||
Size int64 `json:"size"`
|
||||
Enabled bool `json:"enabled"`
|
||||
WASMData []byte `json:"-"`
|
||||
}
|
||||
|
||||
// ClientStore 客户端存储接口
|
||||
type ClientStore interface {
|
||||
// GetAllClients 获取所有客户端
|
||||
GetAllClients() ([]Client, error)
|
||||
|
||||
// GetClient 获取单个客户端
|
||||
GetClient(id string) (*Client, error)
|
||||
|
||||
// CreateClient 创建客户端
|
||||
CreateClient(c *Client) error
|
||||
|
||||
// UpdateClient 更新客户端
|
||||
UpdateClient(c *Client) error
|
||||
|
||||
// DeleteClient 删除客户端
|
||||
DeleteClient(id string) error
|
||||
|
||||
// ClientExists 检查客户端是否存在
|
||||
ClientExists(id string) (bool, error)
|
||||
|
||||
// GetClientRules 获取客户端规则
|
||||
GetClientRules(id string) ([]protocol.ProxyRule, error)
|
||||
|
||||
// Close 关闭连接
|
||||
Close() error
|
||||
}
|
||||
|
||||
// PluginStore 插件存储接口
|
||||
type PluginStore interface {
|
||||
GetAllPlugins() ([]PluginData, error)
|
||||
GetPlugin(name string) (*PluginData, error)
|
||||
SavePlugin(p *PluginData) error
|
||||
DeletePlugin(name string) error
|
||||
SetPluginEnabled(name string, enabled bool) error
|
||||
GetPluginWASM(name string) ([]byte, error)
|
||||
}
|
||||
|
||||
// Store 统一存储接口
|
||||
type Store interface {
|
||||
ClientStore
|
||||
PluginStore
|
||||
Close() error
|
||||
}
|
||||
|
||||
@@ -34,11 +34,35 @@ func NewSQLiteStore(dbPath string) (*SQLiteStore, error) {
|
||||
|
||||
// init 初始化数据库表
|
||||
func (s *SQLiteStore) init() error {
|
||||
// 创建客户端表
|
||||
_, err := s.db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS clients (
|
||||
id TEXT PRIMARY KEY,
|
||||
nickname TEXT NOT NULL DEFAULT '',
|
||||
rules TEXT NOT NULL DEFAULT '[]'
|
||||
);
|
||||
)
|
||||
`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 迁移:添加 nickname 列
|
||||
s.db.Exec(`ALTER TABLE clients ADD COLUMN nickname TEXT NOT NULL DEFAULT ''`)
|
||||
|
||||
// 创建插件表
|
||||
_, err = s.db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS plugins (
|
||||
name TEXT PRIMARY KEY,
|
||||
version TEXT NOT NULL,
|
||||
type TEXT NOT NULL DEFAULT 'proxy',
|
||||
source TEXT NOT NULL DEFAULT 'wasm',
|
||||
description TEXT,
|
||||
author TEXT,
|
||||
checksum TEXT,
|
||||
size INTEGER DEFAULT 0,
|
||||
enabled INTEGER DEFAULT 1,
|
||||
wasm_data BLOB
|
||||
)
|
||||
`)
|
||||
return err
|
||||
}
|
||||
@@ -53,7 +77,7 @@ func (s *SQLiteStore) GetAllClients() ([]Client, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
rows, err := s.db.Query(`SELECT id, rules FROM clients`)
|
||||
rows, err := s.db.Query(`SELECT id, nickname, rules FROM clients`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -63,7 +87,7 @@ func (s *SQLiteStore) GetAllClients() ([]Client, error) {
|
||||
for rows.Next() {
|
||||
var c Client
|
||||
var rulesJSON string
|
||||
if err := rows.Scan(&c.ID, &rulesJSON); err != nil {
|
||||
if err := rows.Scan(&c.ID, &c.Nickname, &rulesJSON); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal([]byte(rulesJSON), &c.Rules); err != nil {
|
||||
@@ -81,7 +105,7 @@ func (s *SQLiteStore) GetClient(id string) (*Client, error) {
|
||||
|
||||
var c Client
|
||||
var rulesJSON string
|
||||
err := s.db.QueryRow(`SELECT id, rules FROM clients WHERE id = ?`, id).Scan(&c.ID, &rulesJSON)
|
||||
err := s.db.QueryRow(`SELECT id, nickname, rules FROM clients WHERE id = ?`, id).Scan(&c.ID, &c.Nickname, &rulesJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -100,7 +124,7 @@ func (s *SQLiteStore) CreateClient(c *Client) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.db.Exec(`INSERT INTO clients (id, rules) VALUES (?, ?)`, c.ID, string(rulesJSON))
|
||||
_, err = s.db.Exec(`INSERT INTO clients (id, nickname, rules) VALUES (?, ?, ?)`, c.ID, c.Nickname, string(rulesJSON))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -113,7 +137,7 @@ func (s *SQLiteStore) UpdateClient(c *Client) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.db.Exec(`UPDATE clients SET rules = ? WHERE id = ?`, string(rulesJSON), c.ID)
|
||||
_, err = s.db.Exec(`UPDATE clients SET nickname = ?, rules = ? WHERE id = ?`, c.Nickname, string(rulesJSON), c.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -144,3 +168,100 @@ func (s *SQLiteStore) GetClientRules(id string) ([]protocol.ProxyRule, error) {
|
||||
}
|
||||
return c.Rules, nil
|
||||
}
|
||||
|
||||
// ========== 插件存储方法 ==========
|
||||
|
||||
// GetAllPlugins 获取所有插件
|
||||
func (s *SQLiteStore) GetAllPlugins() ([]PluginData, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
rows, err := s.db.Query(`
|
||||
SELECT name, version, type, source, description, author, checksum, size, enabled
|
||||
FROM plugins
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var plugins []PluginData
|
||||
for rows.Next() {
|
||||
var p PluginData
|
||||
var enabled int
|
||||
err := rows.Scan(&p.Name, &p.Version, &p.Type, &p.Source,
|
||||
&p.Description, &p.Author, &p.Checksum, &p.Size, &enabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Enabled = enabled == 1
|
||||
plugins = append(plugins, p)
|
||||
}
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
// GetPlugin 获取单个插件
|
||||
func (s *SQLiteStore) GetPlugin(name string) (*PluginData, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
var p PluginData
|
||||
var enabled int
|
||||
err := s.db.QueryRow(`
|
||||
SELECT name, version, type, source, description, author, checksum, size, enabled
|
||||
FROM plugins WHERE name = ?
|
||||
`, name).Scan(&p.Name, &p.Version, &p.Type, &p.Source,
|
||||
&p.Description, &p.Author, &p.Checksum, &p.Size, &enabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Enabled = enabled == 1
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
// SavePlugin 保存插件
|
||||
func (s *SQLiteStore) SavePlugin(p *PluginData) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
enabled := 0
|
||||
if p.Enabled {
|
||||
enabled = 1
|
||||
}
|
||||
_, err := s.db.Exec(`
|
||||
INSERT OR REPLACE INTO plugins
|
||||
(name, version, type, source, description, author, checksum, size, enabled, wasm_data)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, p.Name, p.Version, p.Type, p.Source, p.Description, p.Author,
|
||||
p.Checksum, p.Size, enabled, p.WASMData)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeletePlugin 删除插件
|
||||
func (s *SQLiteStore) DeletePlugin(name string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
_, err := s.db.Exec(`DELETE FROM plugins WHERE name = ?`, name)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetPluginEnabled 设置插件启用状态
|
||||
func (s *SQLiteStore) SetPluginEnabled(name string, enabled bool) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
val := 0
|
||||
if enabled {
|
||||
val = 1
|
||||
}
|
||||
_, err := s.db.Exec(`UPDATE plugins SET enabled = ? WHERE name = ?`, val, name)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetPluginWASM 获取插件 WASM 数据
|
||||
func (s *SQLiteStore) GetPluginWASM(name string) ([]byte, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
var data []byte
|
||||
err := s.db.QueryRow(`SELECT wasm_data FROM plugins WHERE name = ?`, name).Scan(&data)
|
||||
return data, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user