plugin disable system: kernel→SDK PluginManager + WebUI/CLI

- New disabled_plugins table (name, disabled_at, disabled_by)
- SDK.PluginManager interface: DisablePlugin/EnablePlugin/ListDisabledPlugins
- Registry implements PluginManager, wired into PluginSDK
- WebUI: POST /api/v1/plugins/<name>/disable|enable + plugins page with toggle
- Disabling webui shows confirmation dialog
- CLI: /plugin disable <name> / /plugin enable <name>
- pluginmgr removePlugin sync-cleanup from disabled_plugins table
This commit is contained in:
root
2026-07-29 15:07:32 +08:00
parent a899d777c3
commit 796a48dae5
8 changed files with 339 additions and 39 deletions

View File

@ -53,6 +53,58 @@ func (r *ConfigRegistry) initCoreTable() {
key TEXT PRIMARY KEY,
value TEXT NOT NULL
)`)
r.db.Exec(`CREATE TABLE IF NOT EXISTS disabled_plugins (
name TEXT PRIMARY KEY,
disabled_at TEXT NOT NULL,
disabled_by TEXT NOT NULL DEFAULT ''
)`)
}
func (r *ConfigRegistry) AddDisabledPlugin(name, by string) error {
r.mu.Lock()
defer r.mu.Unlock()
_, err := r.db.Exec(`INSERT OR REPLACE INTO disabled_plugins (name, disabled_at, disabled_by) VALUES (?, datetime('now'), ?)`, name, by)
return err
}
func (r *ConfigRegistry) RemoveDisabledPlugin(name string) error {
r.mu.Lock()
defer r.mu.Unlock()
_, err := r.db.Exec(`DELETE FROM disabled_plugins WHERE name = ?`, name)
return err
}
type DisabledPluginInfo struct {
Name string `json:"name"`
DisabledAt string `json:"disabled_at"`
DisabledBy string `json:"disabled_by"`
}
func (r *ConfigRegistry) ListDisabledPlugins() ([]DisabledPluginInfo, error) {
r.mu.RLock()
defer r.mu.RUnlock()
rows, err := r.db.Query(`SELECT name, disabled_at, disabled_by FROM disabled_plugins ORDER BY name`)
if err != nil {
return nil, err
}
defer rows.Close()
var list []DisabledPluginInfo
for rows.Next() {
var info DisabledPluginInfo
if err := rows.Scan(&info.Name, &info.DisabledAt, &info.DisabledBy); err != nil {
return nil, err
}
list = append(list, info)
}
return list, rows.Err()
}
func (r *ConfigRegistry) IsPluginDisabled(name string) bool {
r.mu.RLock()
defer r.mu.RUnlock()
var count int
r.db.QueryRow(`SELECT COUNT(*) FROM disabled_plugins WHERE name = ?`, name).Scan(&count)
return count > 0
}
func (r *ConfigRegistry) ensurePluginTable(name string) {