feat(plugins): allow Plugins to call the Subsonic API (#4260)

* chore: .gitignore any navidrome binary

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: implement internal authentication handling in middleware

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(manager): add SubsonicRouter to Manager for API routing

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): add SubsonicAPI Host service for plugins and an example plugin

Signed-off-by: Deluan <deluan@navidrome.org>

* fix lint

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): refactor path handling in SubsonicAPI to extract endpoint correctly

Signed-off-by: Deluan <deluan@navidrome.org>

* docs(plugins): add SubsonicAPI service documentation to README

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): implement permission checks for SubsonicAPI service

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): enhance SubsonicAPI service initialization with atomic router handling

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor(plugins): better encapsulated dependency injection

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor(plugins): rename parameter in WithInternalAuth for clarity

Signed-off-by: Deluan <deluan@navidrome.org>

* docs(plugins): update SubsonicAPI permissions section in README for clarity and detail

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): enhance SubsonicAPI permissions output with allowed usernames and admin flag

Signed-off-by: Deluan <deluan@navidrome.org>

* feat(plugins): add schema reference to example plugins

Signed-off-by: Deluan <deluan@navidrome.org>

* remove import alias

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan Quintão
2025-06-25 14:18:32 -04:00
committed by GitHub
parent 024b50dc2b
commit 45c408a674
34 changed files with 1573 additions and 46 deletions
+18 -5
View File
@@ -67,7 +67,7 @@ func CreateSubsonicAPIRouter(ctx context.Context) *subsonic.Router {
dataStore := persistence.New(sqlDB)
fileCache := artwork.GetImageCache()
fFmpeg := ffmpeg.New()
manager := plugins.GetManager()
manager := plugins.GetManager(dataStore)
agentsAgents := agents.GetAgents(dataStore, manager)
provider := external.NewProvider(dataStore, agentsAgents)
artworkArtwork := artwork.NewArtwork(dataStore, fileCache, fFmpeg, provider)
@@ -92,7 +92,7 @@ func CreatePublicRouter() *public.Router {
dataStore := persistence.New(sqlDB)
fileCache := artwork.GetImageCache()
fFmpeg := ffmpeg.New()
manager := plugins.GetManager()
manager := plugins.GetManager(dataStore)
agentsAgents := agents.GetAgents(dataStore, manager)
provider := external.NewProvider(dataStore, agentsAgents)
artworkArtwork := artwork.NewArtwork(dataStore, fileCache, fFmpeg, provider)
@@ -137,7 +137,7 @@ func CreateScanner(ctx context.Context) scanner.Scanner {
dataStore := persistence.New(sqlDB)
fileCache := artwork.GetImageCache()
fFmpeg := ffmpeg.New()
manager := plugins.GetManager()
manager := plugins.GetManager(dataStore)
agentsAgents := agents.GetAgents(dataStore, manager)
provider := external.NewProvider(dataStore, agentsAgents)
artworkArtwork := artwork.NewArtwork(dataStore, fileCache, fFmpeg, provider)
@@ -154,7 +154,7 @@ func CreateScanWatcher(ctx context.Context) scanner.Watcher {
dataStore := persistence.New(sqlDB)
fileCache := artwork.GetImageCache()
fFmpeg := ffmpeg.New()
manager := plugins.GetManager()
manager := plugins.GetManager(dataStore)
agentsAgents := agents.GetAgents(dataStore, manager)
provider := external.NewProvider(dataStore, agentsAgents)
artworkArtwork := artwork.NewArtwork(dataStore, fileCache, fFmpeg, provider)
@@ -174,6 +174,19 @@ func GetPlaybackServer() playback.PlaybackServer {
return playbackServer
}
func getPluginManager() *plugins.Manager {
sqlDB := db.Db()
dataStore := persistence.New(sqlDB)
manager := plugins.GetManager(dataStore)
return manager
}
// wire_injectors.go:
var allProviders = wire.NewSet(core.Set, artwork.Set, server.New, subsonic.New, nativeapi.New, public.New, persistence.New, lastfm.NewRouter, listenbrainz.NewRouter, events.GetBroker, scanner.New, scanner.NewWatcher, plugins.GetManager, wire.Bind(new(agents.PluginLoader), new(*plugins.Manager)), wire.Bind(new(scrobbler.PluginLoader), new(*plugins.Manager)), metrics.NewPrometheusInstance, db.Db)
var allProviders = wire.NewSet(core.Set, artwork.Set, server.New, subsonic.New, nativeapi.New, public.New, persistence.New, lastfm.NewRouter, listenbrainz.NewRouter, events.GetBroker, scanner.New, scanner.NewWatcher, plugins.GetManager, metrics.NewPrometheusInstance, db.Db, wire.Bind(new(agents.PluginLoader), new(*plugins.Manager)), wire.Bind(new(scrobbler.PluginLoader), new(*plugins.Manager)))
func GetPluginManager(ctx context.Context) *plugins.Manager {
manager := getPluginManager()
manager.SetSubsonicRouter(CreateSubsonicAPIRouter(ctx))
return manager
}