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
+14
View File
@@ -17,6 +17,7 @@ const (
Transcoding = contextKey("transcoding")
ClientUniqueId = contextKey("clientUniqueId")
ReverseProxyIp = contextKey("reverseProxyIp")
InternalAuth = contextKey("internalAuth") // Used for internal API calls, e.g., from the plugins
)
var allKeys = []contextKey{
@@ -62,6 +63,10 @@ func WithReverseProxyIp(ctx context.Context, reverseProxyIp string) context.Cont
return context.WithValue(ctx, ReverseProxyIp, reverseProxyIp)
}
func WithInternalAuth(ctx context.Context, username string) context.Context {
return context.WithValue(ctx, InternalAuth, username)
}
func UserFrom(ctx context.Context) (model.User, bool) {
v, ok := ctx.Value(User).(model.User)
return v, ok
@@ -102,6 +107,15 @@ func ReverseProxyIpFrom(ctx context.Context) (string, bool) {
return v, ok
}
func InternalAuthFrom(ctx context.Context) (string, bool) {
if v := ctx.Value(InternalAuth); v != nil {
if username, ok := v.(string); ok {
return username, true
}
}
return "", false
}
func AddValues(ctx, requestCtx context.Context) context.Context {
for _, key := range allKeys {
if v := requestCtx.Value(key); v != nil {