diff --git a/lib/api/static/init.go b/lib/api/static/init.go index cde926e..40c68ba 100644 --- a/lib/api/static/init.go +++ b/lib/api/static/init.go @@ -169,7 +169,9 @@ func Init(store *lib.InitStore) { return c.Next() }) - store.C.Get("/pluginfw/plugin-definitions.json", plugins.ReturnPluginResponse) + store.C.Get("/pluginfw/plugin-definitions.json", func(ctx *fiber.Ctx) error { + return plugins.ReturnPluginResponse(ctx) + }) store.C.Static("/static/plugins/", "./plugins") diff --git a/lib/plugins/plugins.go b/lib/plugins/plugins.go index 8c1f308..432b072 100644 --- a/lib/plugins/plugins.go +++ b/lib/plugins/plugins.go @@ -1,9 +1,8 @@ package plugins import ( + "embed" "encoding/json" - "os" - "path" "github.com/ether/etherpad-go/lib/settings" "github.com/gofiber/fiber/v2" @@ -18,29 +17,34 @@ type Plugin struct { const corePluginName = "ep_etherpad-lite" +// Stored assets for plugin loading +var storedUIAssets embed.FS +var storedPluginAssets embed.FS + // GetPackages gibt alle installierten Plugins zurück func GetPackages() map[string]Plugin { var mappedPlugins = make(map[string]Plugin) - root, _ := os.Getwd() + + // Core plugin from uiAssets mappedPlugins[corePluginName] = Plugin{ Name: corePluginName, Version: "1.8.13", Path: "node_modules/" + corePluginName, - RealPath: path.Join(root, "assets", "ep.json"), + RealPath: "assets/ep.json", } - pluginsDir := path.Join(root, "plugins") - entries, err := os.ReadDir(pluginsDir) + // Read plugins from embedded pluginAssets + entries, err := storedPluginAssets.ReadDir("plugins") if err == nil { for _, entry := range entries { if entry.IsDir() { pluginName := entry.Name() - pluginPath := path.Join(pluginsDir, pluginName) - epJsonPath := path.Join(pluginPath, "ep.json") - if _, err := os.Stat(epJsonPath); err == nil { + epJsonPath := "plugins/" + pluginName + "/ep.json" + // Check if ep.json exists in this plugin directory + if _, err := storedPluginAssets.ReadFile(epJsonPath); err == nil { mappedPlugins[pluginName] = Plugin{ Name: pluginName, - Version: "0.0.1", // Standardversion, falls keine package.json vorhanden + Version: "0.0.1", Path: "node_modules/" + pluginName, RealPath: epJsonPath, } @@ -86,17 +90,26 @@ func Update() (map[string]Plugin, map[string]Part, map[string]Plugin) { } func LoadPlugin(plugin Plugin, plugins map[string]Plugin, parts map[string]Part) { - var pluginPath = path.Join(plugin.RealPath) + var bytes []byte + var err error + + // Core plugin (ep_etherpad-lite) is embedded in uiAssets, others in pluginAssets + if plugin.Name == corePluginName { + bytes, err = storedUIAssets.ReadFile(plugin.RealPath) + } else { + bytes, err = storedPluginAssets.ReadFile(plugin.RealPath) + } - bytes, err := os.ReadFile(pluginPath) if err != nil { - println("Error reading plugin file") + println("Error reading plugin file " + plugin.RealPath + ": " + err.Error()) return } + var pluginDef PluginDef err = json.Unmarshal(bytes, &pluginDef) if err != nil { - panic(err) + println("Error parsing plugin file " + plugin.RealPath + ": " + err.Error()) + return } plugins[plugin.Name] = plugin @@ -194,7 +207,9 @@ var cachedPlugins = map[string]Plugin{} var cachedParts = map[string]Part{} var cachedPackages = map[string]Plugin{} -func init() { +func Init(uiAssets embed.FS, pluginAssets embed.FS) { + storedUIAssets = uiAssets + storedPluginAssets = pluginAssets GetCachedPlugins() } @@ -221,3 +236,13 @@ func GetCachedPackages() map[string]Plugin { } return cachedPackages } + +// GetStoredPluginAssets returns the stored plugin assets for use by other packages +func GetStoredPluginAssets() embed.FS { + return storedPluginAssets +} + +// GetStoredUIAssets returns the stored UI assets for use by other packages +func GetStoredUIAssets() embed.FS { + return storedUIAssets +} diff --git a/lib/server/server.go b/lib/server/server.go index 9376104..6670ad7 100644 --- a/lib/server/server.go +++ b/lib/server/server.go @@ -26,9 +26,10 @@ import ( "go.uber.org/zap" ) -func InitServer(setupLogger *zap.SugaredLogger, uiAssets embed.FS) { +func InitServer(setupLogger *zap.SugaredLogger, uiAssets embed.FS, pluginAssets embed.FS) { settings2.InitSettings(setupLogger) + plugins.Init(uiAssets, pluginAssets) var settings = settings2.Displayed validatorEvaluator := validator.New(validator.WithRequiredStructEnabled()) @@ -65,7 +66,7 @@ func InitServer(setupLogger *zap.SugaredLogger, uiAssets embed.FS) { importer := io.NewImporter(padManager, authorManager, dataStore, setupLogger) globalHub := ws.NewHub() sessionStore := ws.NewSessionStore() - padMessageHandler := ws.NewPadMessageHandler(dataStore, &retrievedHooks, padManager, &sessionStore, globalHub, setupLogger) + padMessageHandler := ws.NewPadMessageHandler(dataStore, &retrievedHooks, padManager, &sessionStore, globalHub, setupLogger, uiAssets) adminMessageHandler := ws.NewAdminMessageHandler(dataStore, &retrievedHooks, padManager, padMessageHandler, setupLogger, globalHub, app) securityManager := pad.NewSecurityManager(dataStore, &retrievedHooks, padManager) diff --git a/lib/settings/clientVars/clientVars.go b/lib/settings/clientVars/clientVars.go index 33ed908..7e28e05 100644 --- a/lib/settings/clientVars/clientVars.go +++ b/lib/settings/clientVars/clientVars.go @@ -1,6 +1,7 @@ package clientVars import ( + "embed" "strconv" "time" @@ -18,6 +19,7 @@ import ( type Factory struct { ReadOnlyManager *pad2.ReadOnlyManager AuthorManager *author2.Manager + UiAssets embed.FS } func (f *Factory) NewClientVars(pad pad.Pad, sessionInfo *ws.Session, apool apool2.APool, translatedAttribs string, historicalAuthorData map[string]author2.Author, retrievedSettings *settings.Settings) (*clientVars.ClientVars, error) { diff --git a/lib/test/testutils/dbUtils_test_helper.go b/lib/test/testutils/dbUtils_test_helper.go index ef38492..73f3168 100644 --- a/lib/test/testutils/dbUtils_test_helper.go +++ b/lib/test/testutils/dbUtils_test_helper.go @@ -733,7 +733,7 @@ func (test *TestDBHandler) TestRun( loggerPart := zap.NewNop().Sugar() importer := io.NewImporter(padManager, authManager, ds, loggerPart) padMessageHandler := ws.NewPadMessageHandler( - ds, &hooks, padManager, &sess, hub, loggerPart, + ds, &hooks, padManager, &sess, hub, loggerPart, TestAssets, ) app := fiber.New() adminMessageHandler := ws.NewAdminMessageHandler( diff --git a/lib/ws/PadMessageHandler.go b/lib/ws/PadMessageHandler.go index 3a0bf6e..338828e 100644 --- a/lib/ws/PadMessageHandler.go +++ b/lib/ws/PadMessageHandler.go @@ -1,6 +1,7 @@ package ws import ( + "embed" "encoding/json" "errors" "fmt" @@ -97,7 +98,7 @@ type PadMessageHandler struct { Logger *zap.SugaredLogger } -func NewPadMessageHandler(db db2.DataStore, hooks *hooks.Hook, padManager *pad.Manager, sessionStore *SessionStore, hub *Hub, logger *zap.SugaredLogger) *PadMessageHandler { +func NewPadMessageHandler(db db2.DataStore, hooks *hooks.Hook, padManager *pad.Manager, sessionStore *SessionStore, hub *Hub, logger *zap.SugaredLogger, uiAssets embed.FS) *PadMessageHandler { var padMessageHandler = PadMessageHandler{ padManager: padManager, readOnlyManager: pad.NewReadOnlyManager(db), @@ -106,6 +107,7 @@ func NewPadMessageHandler(db db2.DataStore, hooks *hooks.Hook, padManager *pad.M factory: clientVars.Factory{ ReadOnlyManager: pad.NewReadOnlyManager(db), AuthorManager: author.NewManager(db), + UiAssets: uiAssets, }, SessionStore: sessionStore, hub: hub, diff --git a/main.go b/main.go index be2952a..ea4221a 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,9 @@ import ( //go:embed assets var uiAssets embed.FS +//go:embed plugins +var pluginAssets embed.FS + // @title Etherpad Go API // @version 1.0 // @description REST API for Etherpad Go - Collaborative Text Editor @@ -77,5 +80,5 @@ func main() { } } - server2.InitServer(setupLogger, uiAssets) + server2.InitServer(setupLogger, uiAssets, pluginAssets) }