mirror of
https://github.com/go-vikunja/vikunja.git
synced 2025-12-05 18:57:47 -06:00
feat(plugins): allow plugins to register routes
This commit is contained in:
@@ -17,12 +17,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/events"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/plugins"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
|
||||
"github.com/ThreeDotsLabs/watermill/message"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type ExamplePlugin struct{}
|
||||
@@ -38,6 +43,55 @@ func (p *ExamplePlugin) Init() error {
|
||||
}
|
||||
func (p *ExamplePlugin) Shutdown() error { return nil }
|
||||
|
||||
// RegisterAuthenticatedRoutes implements the AuthenticatedRouterPlugin interface
|
||||
func (p *ExamplePlugin) RegisterAuthenticatedRoutes(g *echo.Group) {
|
||||
g.GET("/user-info", handleUserInfo)
|
||||
|
||||
log.Infof("example plugin authenticated routes registered")
|
||||
}
|
||||
|
||||
// RegisterUnauthenticatedRoutes implements the UnauthenticatedRouterPlugin interface
|
||||
func (p *ExamplePlugin) RegisterUnauthenticatedRoutes(g *echo.Group) {
|
||||
g.GET("/status", handleStatus)
|
||||
|
||||
log.Infof("example plugin unauthenticated routes registered")
|
||||
}
|
||||
|
||||
// Authenticated route handlers
|
||||
func handleUserInfo(c echo.Context) error {
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// Get the authenticated user from context
|
||||
u, err := user.GetCurrentUserFromDB(s, c)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "User not found")
|
||||
}
|
||||
|
||||
p := &ExamplePlugin{}
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"message": "Hello from example plugin!",
|
||||
"user": u,
|
||||
"plugin": p.Name(),
|
||||
"version": p.Version(),
|
||||
})
|
||||
}
|
||||
|
||||
// Unauthenticated route handlers
|
||||
func handleStatus(c echo.Context) error {
|
||||
|
||||
p := &ExamplePlugin{}
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"status": "ok",
|
||||
"plugin": p.Name(),
|
||||
"version": p.Version(),
|
||||
"message": "Example plugin is running",
|
||||
})
|
||||
}
|
||||
|
||||
func NewPlugin() plugins.Plugin { return &ExamplePlugin{} }
|
||||
|
||||
type TestListener struct{}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
)
|
||||
|
||||
@@ -33,3 +34,15 @@ type MigrationPlugin interface {
|
||||
Plugin
|
||||
Migrations() []*xormigrate.Migration
|
||||
}
|
||||
|
||||
// AuthenticatedRouterPlugin lets a plugin register authenticated web handlers and routes.
|
||||
type AuthenticatedRouterPlugin interface {
|
||||
Plugin
|
||||
RegisterAuthenticatedRoutes(g *echo.Group)
|
||||
}
|
||||
|
||||
// UnauthenticatedRouterPlugin lets a plugin register unauthenticated web handlers and routes.
|
||||
type UnauthenticatedRouterPlugin interface {
|
||||
Plugin
|
||||
RegisterUnauthenticatedRoutes(g *echo.Group)
|
||||
}
|
||||
|
||||
@@ -25,12 +25,16 @@ import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/migration"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// Manager handles loading and managing plugins.
|
||||
type Manager struct {
|
||||
plugins []Plugin
|
||||
migrationPlugs []MigrationPlugin
|
||||
plugins []Plugin
|
||||
migrationPlugs []MigrationPlugin
|
||||
authenticatedRouterPlugs []AuthenticatedRouterPlugin
|
||||
unauthenticatedRouterPlugs []UnauthenticatedRouterPlugin
|
||||
}
|
||||
|
||||
var manager = &Manager{}
|
||||
@@ -70,6 +74,21 @@ func Shutdown() {
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterPluginRoutes registers routes from all router plugins.
|
||||
func RegisterPluginRoutes(authenticated *echo.Group, unauthenticated *echo.Group) {
|
||||
// Register authenticated routes
|
||||
for _, p := range manager.authenticatedRouterPlugs {
|
||||
p.RegisterAuthenticatedRoutes(authenticated)
|
||||
log.Debugf("Registered authenticated routes for plugin %s", p.Name())
|
||||
}
|
||||
|
||||
// Register unauthenticated routes
|
||||
for _, p := range manager.unauthenticatedRouterPlugs {
|
||||
p.RegisterUnauthenticatedRoutes(unauthenticated)
|
||||
log.Debugf("Registered unauthenticated routes for plugin %s", p.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) loadPlugins(paths []string) error {
|
||||
for _, p := range paths {
|
||||
entries, err := os.ReadDir(p)
|
||||
@@ -113,6 +132,14 @@ func (m *Manager) loadPlugin(path string) error {
|
||||
migration.AddPluginMigrations(mp.Migrations())
|
||||
}
|
||||
|
||||
if arp, ok := p.(AuthenticatedRouterPlugin); ok {
|
||||
m.authenticatedRouterPlugs = append(m.authenticatedRouterPlugs, arp)
|
||||
}
|
||||
|
||||
if urp, ok := p.(UnauthenticatedRouterPlugin); ok {
|
||||
m.unauthenticatedRouterPlugs = append(m.unauthenticatedRouterPlugs, urp)
|
||||
}
|
||||
|
||||
log.Infof("Loaded plugin %s", p.Name())
|
||||
|
||||
return nil
|
||||
|
||||
@@ -73,6 +73,7 @@ import (
|
||||
"code.vikunja.io/api/pkg/modules/migration/todoist"
|
||||
"code.vikunja.io/api/pkg/modules/migration/trello"
|
||||
vikunja_file "code.vikunja.io/api/pkg/modules/migration/vikunja-file"
|
||||
"code.vikunja.io/api/pkg/plugins"
|
||||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/routes/caldav"
|
||||
"code.vikunja.io/api/pkg/version"
|
||||
@@ -644,6 +645,17 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
},
|
||||
}
|
||||
a.POST("/projects/:project/views/:view/buckets/:bucket/tasks", taskBucketProvider.UpdateWeb)
|
||||
|
||||
// Plugin routes
|
||||
if config.PluginsEnabled.GetBool() {
|
||||
// Authenticated plugin routes
|
||||
authenticatedPluginGroup := a.Group("/plugins")
|
||||
|
||||
// Unauthenticated plugin routes (with basic IP rate limiting)
|
||||
unauthenticatedPluginGroup := n.Group("/plugins")
|
||||
|
||||
plugins.RegisterPluginRoutes(authenticatedPluginGroup, unauthenticatedPluginGroup)
|
||||
}
|
||||
}
|
||||
|
||||
func registerMigrations(m *echo.Group) {
|
||||
|
||||
Reference in New Issue
Block a user