mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-06-18 18:16:26 +00:00
Improvements to enforce middleware, linting, returning 404 properly
This commit is contained in:
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
|
||||
c "npm/internal/api/context"
|
||||
h "npm/internal/api/http"
|
||||
@ -11,7 +12,6 @@ import (
|
||||
"npm/internal/entity/user"
|
||||
njwt "npm/internal/jwt"
|
||||
"npm/internal/logger"
|
||||
"npm/internal/util"
|
||||
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
)
|
||||
@ -35,7 +35,7 @@ func DecodeAuth() func(http.Handler) http.Handler {
|
||||
// Enforce is a authentication middleware to enforce access from the
|
||||
// jwtauth.Verifier middleware request context values. The Authenticator sends a 401 Unauthorised
|
||||
// response for any unverified tokens and passes the good ones through.
|
||||
func Enforce(permission string) func(http.Handler) http.Handler {
|
||||
func Enforce(permissions ...string) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
@ -56,7 +56,7 @@ func Enforce(permission string) func(http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
// Check if permissions exist for this user
|
||||
if permission != "" {
|
||||
if len(permissions) > 0 {
|
||||
// Since the permission that we require is not on the token, we have to get it from the DB
|
||||
// So we don't go crazy with hits, we will use a memory cache
|
||||
cacheKey := fmt.Sprintf("userCapabilties.%v", userID)
|
||||
@ -75,9 +75,16 @@ func Enforce(permission string) func(http.Handler) http.Handler {
|
||||
|
||||
// Now check that they have the permission in their admin capabilities
|
||||
// full-admin can do anything
|
||||
if !util.SliceContainsItem(userCapabilities, user.CapabilityFullAdmin) && !util.SliceContainsItem(userCapabilities, permission) {
|
||||
hasOnePermission := false
|
||||
for _, permission := range permissions {
|
||||
if slices.Contains(userCapabilities, user.CapabilityFullAdmin) || slices.Contains(userCapabilities, permission) {
|
||||
hasOnePermission = true
|
||||
}
|
||||
}
|
||||
|
||||
if !hasOnePermission {
|
||||
// Access denied
|
||||
logger.Debug("User has: %+v but needs %s", userCapabilities, permission)
|
||||
logger.Debug("Enforce Failed: User has %v but needs %v", userCapabilities, permissions)
|
||||
h.ResultErrorJSON(w, r, http.StatusForbidden, "Forbidden", nil)
|
||||
return
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
h "npm/internal/api/http"
|
||||
@ -9,15 +8,11 @@ import (
|
||||
)
|
||||
|
||||
// EnforceSetup will error if the config setup doesn't match what is required
|
||||
func EnforceSetup(shouldBeSetup bool) func(http.Handler) http.Handler {
|
||||
func EnforceSetup() func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if config.IsSetup != shouldBeSetup {
|
||||
state := "during"
|
||||
if config.IsSetup {
|
||||
state = "after"
|
||||
}
|
||||
h.ResultErrorJSON(w, r, http.StatusForbidden, fmt.Sprintf("Not available %s setup phase", state), nil)
|
||||
if !config.IsSetup {
|
||||
h.ResultErrorJSON(w, r, http.StatusForbidden, "Not available during setup phase", nil)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -17,34 +17,19 @@ func TestEnforceSetup(t *testing.T) {
|
||||
defer goleak.VerifyNone(t, goleak.IgnoreAnyFunction("database/sql.(*DB).connectionOpener"))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
shouldBeSetup bool
|
||||
isSetup bool
|
||||
expectedCode int
|
||||
name string
|
||||
isSetup bool
|
||||
expectedCode int
|
||||
}{
|
||||
{
|
||||
name: "should allow request when setup is expected and is setup",
|
||||
shouldBeSetup: true,
|
||||
isSetup: true,
|
||||
expectedCode: http.StatusOK,
|
||||
name: "should allow request when setup is expected and is setup",
|
||||
isSetup: true,
|
||||
expectedCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "should error when setup is expected but not setup",
|
||||
shouldBeSetup: true,
|
||||
isSetup: false,
|
||||
expectedCode: http.StatusForbidden,
|
||||
},
|
||||
{
|
||||
name: "should allow request when setup is not expected and not setup",
|
||||
shouldBeSetup: false,
|
||||
isSetup: false,
|
||||
expectedCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "should error when setup is not expected but is setup",
|
||||
shouldBeSetup: false,
|
||||
isSetup: true,
|
||||
expectedCode: http.StatusForbidden,
|
||||
name: "should error when setup is expected but not setup",
|
||||
isSetup: false,
|
||||
expectedCode: http.StatusForbidden,
|
||||
},
|
||||
}
|
||||
|
||||
@ -52,7 +37,7 @@ func TestEnforceSetup(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
config.IsSetup = tt.isSetup
|
||||
|
||||
handler := middleware.EnforceSetup(tt.shouldBeSetup)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
handler := middleware.EnforceSetup()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
// to be used later in other endpoints.
|
||||
func ListQuery(obj interface{}) func(http.Handler) http.Handler {
|
||||
schemaData := tags.GetFilterSchema(obj)
|
||||
filterMap := tags.GetFilterMap(obj)
|
||||
filterMap := tags.GetFilterMap(obj, "")
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
Reference in New Issue
Block a user