Documentation
¶
Overview ¶
Package plugin manages Komari plugins: ZIP packages with a komari-plugin.json manifest, mirroring the theme package format. A plugin runs in its own jsruntime instance confined to its data/plugin/<short> directory, plus its long-term data directory data/plugin-data/<short> exposed as __storageDir__ (which survives plugin updates), declares runtime permissions in its manifest, and receives the host-injected "server" module (server.route / server.call / server.hook, whose ws kinds can intercept WebSocket connections and frames). Plugins run with admin authority inside the system.
Lifecycle: plugins are installed as directories under DataDir. The persisted state file (state.json) records which plugins are enabled, which permissions were approved, and the last load error. Enabled plugins are loaded at startup; a failed load auto-disables the plugin and keeps the error text visible through admin:listPlugins.
Index ¶
- Variables
- func AdminDeletePlugin(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
- func AdminGetPluginConfiguration(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
- func AdminGetPluginLogs(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
- func AdminListPlugins(_ context.Context, _ *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
- func AdminSetPluginConfiguration(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
- func AdminSetPluginEnabled(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
- func CheckKomariVersion(constraint string) error
- func CheckSonarVersion(constraint string) error
- func CloseAll() error
- func CreatePluginMarketSource(c *gin.Context)
- func Delete(short string) error
- func DeletePluginMarketSource(c *gin.Context)
- func GetConfiguration(short string) (map[string]any, error)
- func GetLogs(short string) string
- func HTMLInjectHandler(next http.Handler) http.Handler
- func Init(engine *gin.Engine)
- func InstallPluginFromMarket(c *gin.Context)
- func InstallZip(zipPath string) (models.Plugin, error)
- func ListPluginMarketCatalog(c *gin.Context)
- func ListPluginMarketSources(c *gin.Context)
- func LoadAll() error
- func Manifest(short string) (models.Plugin, error)
- func Reload(short string) error
- func ResolveFile(short, name string) (string, error)
- func ResolvePublicFile(short, name string) (string, error)
- func SaveConfiguration(short string, data map[string]any) error
- func ServeAdminPluginFile(c *gin.Context)
- func ServePublicPluginFile(c *gin.Context)
- func SetEnabled(short string, enabled, approved bool) error
- func UpdatePluginMarketSource(c *gin.Context)
- func WrapHandler(next http.Handler) http.Handler
- type Info
- type Instance
- type LogBuffer
- type Manager
- func (m *Manager) OnClose(info *wsconn.ConnInfo)
- func (m *Manager) OnConnect(info *wsconn.ConnInfo) (deny bool, reason string)
- func (m *Manager) OnMessage(info *wsconn.ConnInfo, frameType int, data []byte) (int, []byte, bool)
- func (m *Manager) OnSend(info *wsconn.ConnInfo, frameType int, data []byte) (int, []byte, bool)
- type PluginMarketPlugin
- type PluginMarketSource
- type PluginState
- type State
Constants ¶
This section is empty.
Variables ¶
var DataDir = "./data/plugin"
DataDir is the on-disk root for installed plugins, mirroring the theme directory layout. It is a variable so tests can redirect it.
var ErrNotInstalled = errors.New("plugin is not installed")
ErrNotInstalled is returned when deleting a plugin that is not installed.
var ErrPermissionApprovalRequired = errors.New("plugin permissions require approval")
ErrPermissionApprovalRequired is returned when enabling a plugin whose declared permissions have not been approved, or changed since approval.
var StorageDir = "./data/plugin-data"
StorageDir is the on-disk root for long-term plugin data. Each plugin gets StorageDir/<short>. The directory is confined into the plugin runtime as __storageDir__ and survives plugin reinstalls: update removes only DataDir/<short> (the code from the ZIP) while StorageDir/<short> persists. Deleting a plugin removes both.
Functions ¶
func AdminDeletePlugin ¶
func AdminDeletePlugin(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
func AdminGetPluginConfiguration ¶
func AdminGetPluginConfiguration(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
func AdminGetPluginLogs ¶
func AdminGetPluginLogs(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
func AdminListPlugins ¶
func AdminListPlugins(_ context.Context, _ *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
func AdminSetPluginConfiguration ¶
func AdminSetPluginConfiguration(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
func AdminSetPluginEnabled ¶
func AdminSetPluginEnabled(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)
AdminSetPluginEnabled is the single switch entry point. When a plugin's declared permissions differ from the approved hash, enabling it returns { requires_approval: true } instead of an error; the caller then shows a permission dialog and retries with approved=true.
func CheckKomariVersion ¶
CheckKomariVersion is a backward-compatible alias for CheckSonarVersion.
func CheckSonarVersion ¶
CheckSonarVersion validates a manifest version constraint against the running server version. Supported constraints: empty (any version), "x.y.z" (exact), and ">=x.y.z", ">x.y.z", "<=x.y.z", "<x.y.z". An optional leading "v" is accepted.
func CloseAll ¶
func CloseAll() error
CloseAll unloads every loaded plugin. Used during server shutdown.
func GetConfiguration ¶
GetConfiguration returns the saved configuration values of one plugin, merged with the manifest-declared defaults for keys that were never saved. This mirrors the theme configuration behavior so plugins and the admin UI always see a complete value set. Missing rows yield only defaults; a missing manifest yields only the saved values.
func HTMLInjectHandler ¶
HTMLInjectHandler installs plugin HTML injection around the application handler. Every text/html response is buffered and gets the fragments registered through server.injectHTML inserted before </head> and </body>; all other responses (JSON, assets, streams, downloads...) pass through to the client unmodified.
func Init ¶
Init wires the manager to the HTTP engine and into every WebSocket wsconn. It must be called before any plugin is loaded.
func InstallPluginFromMarket ¶
func InstallZip ¶
InstallZip validates a plugin ZIP and extracts it into DataDir/<short>. The archive must contain komari-plugin.json at its root. Archive limits mirror the theme package format; path-traversal entries reject the whole package instead of being skipped. Reinstalling over a running plugin unloads it first and restores it to its persisted enabled state when the extraction succeeds.
func ListPluginMarketCatalog ¶
func ListPluginMarketSources ¶
func LoadAll ¶
func LoadAll() error
LoadAll loads every installed plugin whose persisted state is enabled and approved. A failed load auto-disables the plugin, persists last_error and is returned joined so callers can log it without stopping startup.
func Reload ¶
Reload unloads and loads an enabled plugin. The load hook completes before this function returns; a failed load is persisted as the plugin's last error and disables the plugin, matching the normal enable/startup path.
func ResolveFile ¶
ResolveFile returns the absolute path of a file inside an installed plugin directory, rejecting traversal. Used to serve injected plugin pages.
func ResolvePublicFile ¶
ResolvePublicFile returns the absolute path of a file that belongs to a public iframe page of an installed plugin. Public pages are served without authentication: the plugin must be enabled and the requested file must live inside the directory of a page declared with visibility=public, so the page HTML and its relative assets are reachable without exposing the whole plugin directory.
func SaveConfiguration ¶
SaveConfiguration upserts the configuration values of one plugin.
func ServeAdminPluginFile ¶
ServeAdminPluginFile serves a static file from an installed plugin directory, used by injected plugin admin pages. 与 ServePublicPluginFile(无需鉴权的公开 iframe 页面)同名会冲突,故以 Admin/Public 区分。
func ServePublicPluginFile ¶
ServePublicPluginFile serves a public iframe page declared in a plugin manifest (visibility=public). It is reachable without authentication; the plugin must be enabled and the requested file must be listed as a public page. 与 ServeAdminPluginFile(管理页面静态文件)同名会冲突,故以 Admin/Public 区分。
func SetEnabled ¶
SetEnabled is the single switch entry point. Enabling a plugin whose declared permissions differ from the approved hash requires approved=true.
Types ¶
type Info ¶
type Info struct {
models.Plugin
Enabled bool `json:"enabled"`
Running bool `json:"running"`
LastError string `json:"last_error"`
}
Info describes one installed plugin for the admin surface.
type Instance ¶
type Instance struct {
// contains filtered or unexported fields
}
Instance is one loaded plugin runtime plus its host bindings.
type LogBuffer ¶
type LogBuffer struct {
// contains filtered or unexported fields
}
LogBuffer is a bounded ring buffer holding one plugin's console output and lifecycle markers. Old bytes are dropped from the front when the limit is reached.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns the installed plugin set: load/unload lifecycle, persisted state, per-plugin logs, and the host engine used by server.route.
func (*Manager) OnConnect ¶
OnConnect implements wsconn.FrameInterceptor. It runs the wsConnect hooks registered for the connection path; the first denial rejects the wsconn.
type PluginMarketPlugin ¶
type PluginMarketPlugin struct {
Name any `json:"name"`
Short string `json:"short"`
Description any `json:"description"`
Version string `json:"version"`
Author any `json:"author"`
URL string `json:"url"`
Download string `json:"download"`
SHA256 string `json:"sha256"`
Sonar string `json:"sonar"`
Komari string `json:"komari"`
Installable bool `json:"installable"`
SourceID string `json:"source_id,omitempty"`
SourceName string `json:"source_name,omitempty"`
}