navidrome/server/subsonic/middlewares.go

106 lines
2.9 KiB
Go
Raw Normal View History

package subsonic
import (
"context"
"fmt"
"net/http"
"net/url"
"strings"
2020-01-24 01:44:08 +01:00
"github.com/deluan/navidrome/engine"
"github.com/deluan/navidrome/log"
"github.com/deluan/navidrome/model"
"github.com/deluan/navidrome/server/subsonic/responses"
)
func postFormToQueryParams(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
SendError(w, r, NewError(responses.ErrorGeneric, err.Error()))
}
var parts []string
for key, values := range r.Form {
for _, v := range values {
parts = append(parts, url.QueryEscape(key)+"="+url.QueryEscape(v))
}
}
r.URL.RawQuery = strings.Join(parts, "&")
next.ServeHTTP(w, r)
})
}
func checkRequiredParameters(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requiredParameters := []string{"u", "v", "c"}
for _, p := range requiredParameters {
if ParamString(r, p) == "" {
msg := fmt.Sprintf(`Missing required parameter "%s"`, p)
2020-01-09 02:45:07 +01:00
log.Warn(r, msg)
SendError(w, r, NewError(responses.ErrorMissingParameter, msg))
return
}
}
2020-01-09 16:35:00 +01:00
user := ParamString(r, "u")
client := ParamString(r, "c")
version := ParamString(r, "v")
ctx := r.Context()
2020-01-21 00:12:17 +01:00
ctx = context.WithValue(ctx, "username", user)
2020-01-09 16:35:00 +01:00
ctx = context.WithValue(ctx, "client", client)
ctx = context.WithValue(ctx, "version", version)
2020-02-02 02:07:15 +01:00
log.Info(ctx, "API: New request "+r.URL.Path, "username", user, "client", client, "version", version)
2020-01-09 16:35:00 +01:00
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}
func authenticate(users engine.Users) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2020-01-21 00:12:17 +01:00
username := ParamString(r, "u")
pass := ParamString(r, "p")
token := ParamString(r, "t")
salt := ParamString(r, "s")
2020-02-06 22:48:35 +01:00
jwt := ParamString(r, "jwt")
2020-02-06 22:48:35 +01:00
usr, err := users.Authenticate(r.Context(), username, pass, token, salt, jwt)
if err == model.ErrInvalidAuth {
2020-01-21 00:12:17 +01:00
log.Warn(r, "Invalid login", "username", username, err)
} else if err != nil {
2020-01-21 00:12:17 +01:00
log.Error(r, "Error authenticating username", "username", username, err)
}
if err != nil {
2020-01-21 00:12:17 +01:00
log.Warn(r, "Invalid login", "username", username)
SendError(w, r, NewError(responses.ErrorAuthenticationFail))
return
}
2020-01-21 00:12:17 +01:00
ctx := r.Context()
ctx = context.WithValue(ctx, "user", usr)
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}
}
func requiredParams(params ...string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for _, p := range params {
_, err := RequiredParamString(r, p, fmt.Sprintf("%s parameter is required", p))
if err != nil {
SendError(w, r, err)
return
}
}
next.ServeHTTP(w, r)
})
}
}