Files
filestash/server/pkg/extension/discovery.go
T

152 lines
3.5 KiB
Go

package extension
import (
"archive/zip"
"encoding/json"
"fmt"
"io"
"os"
"strings"
"github.com/mickael-kerjean/filestash/server/pkg/config"
. "github.com/mickael-kerjean/filestash/server/pkg/env"
"github.com/mickael-kerjean/filestash/server/pkg/extension/adapter"
. "github.com/mickael-kerjean/filestash/server/pkg/kernel"
. "github.com/mickael-kerjean/filestash/server/pkg/utils"
)
func Discovery() error {
entries, err := os.ReadDir(GetAbsolutePath(PLUGIN_PATH))
if err != nil {
return err
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
fname := entry.Name()
if strings.HasSuffix(fname, ".zip") == false {
continue
}
name, impl, err := initModule(fname)
if err != nil {
Log.Error("could not initialise module name=%s err=%s", entry.Name(), err.Error())
continue
}
for i := 0; i < len(impl.Modules); i++ {
switch impl.Modules[i]["type"] {
case "css":
b, err := GetPluginFile(name, impl.Modules[i]["entrypoint"])
if err != nil {
return err
}
Hooks.Register.CSS(string(b))
case "patch":
b, err := GetPluginFile(name, impl.Modules[i]["entrypoint"])
if err != nil {
return err
}
Hooks.Register.StaticPatch(b)
case "favicon":
b, err := GetPluginFile(name, impl.Modules[i]["entrypoint"])
if err != nil {
return err
}
Hooks.Register.Favicon(b)
case "abi":
b, err := GetPluginFile(name, impl.Modules[i]["entrypoint"])
if err != nil {
return err
}
in, err := adapter.NewInstance(b, impl.Permissions...)
if err != nil {
return err
}
if in.Provides("authorisation") {
Hooks.Register.AuthorisationMiddleware(in.Authorisation())
}
if in.Provides("middleware") {
Hooks.Register.Middleware(in.Middleware())
}
if in.Provides("http") {
Hooks.Register.HttpEndpoint(in.Http())
}
if in.Provides("on_init") {
Hooks.Register.Onload(in.OnInit())
}
if in.Provides("on_changes") {
config.RegisterChange(in.OnChanges())
}
if in.Provides("on_destroy") {
Hooks.Register.OnQuit(in.OnDestroy())
}
case "xdg-open": // noop
default:
return fmt.Errorf("%w: %s", ErrNotImplemented, impl.Modules[i]["type"])
}
}
plugins[name] = impl
}
return nil
}
func GetPluginFile(pluginName string, path string) ([]byte, error) {
zipReader, err := zip.OpenReader(JoinPath(
GetAbsolutePath(PLUGIN_PATH),
pluginName+".zip",
))
if err != nil {
return nil, err
}
for _, zipFile := range zipReader.File {
if zipFile.Name != path {
continue
}
f, err := zipFile.Open()
if err != nil {
zipReader.Close()
return nil, err
}
data, err := io.ReadAll(f)
f.Close()
zipReader.Close()
if err != nil {
return nil, err
}
return data, nil
}
zipReader.Close()
return nil, ErrNotFound
}
func initModule(plgName string) (string, PluginImpl, error) {
var plgImpl = PluginImpl{}
r, err := zip.OpenReader(JoinPath(GetAbsolutePath(PLUGIN_PATH), plgName))
plgName = strings.TrimSuffix(plgName, ".zip")
if err != nil {
return plgName, plgImpl, err
}
defer r.Close()
var manifestFile io.ReadCloser
for _, f := range r.File {
if f.Name != "manifest.json" {
continue
}
rc, err := f.Open()
if err != nil {
return plgName, plgImpl, err
}
manifestFile = rc
break
}
if manifestFile == nil {
return plgName, plgImpl, ErrNotFound
}
defer manifestFile.Close()
if err = json.NewDecoder(manifestFile).Decode(&plgImpl); err != nil {
return plgName, plgImpl, err
}
return plgName, plgImpl, nil
}