Improvements to enforce middleware, linting, returning 404 properly

This commit is contained in:
Jamie Curnow
2024-09-11 15:03:00 +10:00
parent 833dd23dce
commit 9a2e5c92d5
18 changed files with 110 additions and 104 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}))

View File

@ -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) {