From 98d41b97b83d1afeca3938f385c785e6fe0af860 Mon Sep 17 00:00:00 2001 From: SystemGlitch Date: Mon, 12 Aug 2024 16:45:00 +0200 Subject: [PATCH] #221 Auth: Fix JWT controller gorm.ErrRecordNotFound handling (#224) --- auth/jwt_controller.go | 7 ++++++- auth/jwt_controller_test.go | 29 ++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/auth/jwt_controller.go b/auth/jwt_controller.go index c49bfb0c..f65ee708 100644 --- a/auth/jwt_controller.go +++ b/auth/jwt_controller.go @@ -116,6 +116,11 @@ func (c *JWTController[T]) Login(response *goyave.Response, request *goyave.Requ return } + if notFound { + response.JSON(http.StatusUnauthorized, map[string]string{"error": request.Lang.Get("auth.invalid-credentials")}) + return + } + t := reflect.Indirect(reflect.ValueOf(user)) for t.Kind() == reflect.Ptr { t = t.Elem() @@ -126,7 +131,7 @@ func (c *JWTController[T]) Login(response *goyave.Response, request *goyave.Requ return } - if !notFound && bcrypt.CompareHashAndPassword([]byte(pass.String()), []byte(password)) == nil { + if bcrypt.CompareHashAndPassword([]byte(pass.String()), []byte(password)) == nil { tokenFunc := lo.Ternary(c.TokenFunc == nil, c.defaultTokenFunc, c.TokenFunc) token, err := tokenFunc(request, user) if err != nil { diff --git a/auth/jwt_controller_test.go b/auth/jwt_controller_test.go index 88a201a9..8acd7d05 100644 --- a/auth/jwt_controller_test.go +++ b/auth/jwt_controller_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/gorm" "goyave.dev/goyave/v5" "goyave.dev/goyave/v5/slog" "goyave.dev/goyave/v5/util/testutil" @@ -69,7 +70,7 @@ func TestJWTController(t *testing.T) { assert.NotEmpty(t, respBody["token"]) }) - t.Run("Login_invalid", func(t *testing.T) { + t.Run("Login_invalid_password", func(t *testing.T) { server, user := prepareAuthenticatorTest(t) server.Config().Set("auth.jwt.secret", "secret") @@ -95,6 +96,32 @@ func TestJWTController(t *testing.T) { assert.Equal(t, map[string]string{"error": server.Lang.GetDefault().Get("auth.invalid-credentials")}, respBody) }) + t.Run("Login_invalid_username", func(t *testing.T) { + server, user := prepareAuthenticatorTest(t) + server.Config().Set("auth.jwt.secret", "secret") + + mockUserService := &MockUserService[TestUser]{err: fmt.Errorf("test errors: %w", gorm.ErrRecordNotFound)} + controller := NewJWTController(mockUserService, "Password") + server.RegisterRoutes(func(_ *goyave.Server, router *goyave.Router) { + router.Controller(controller) + }) + + data := map[string]any{ + "username": "wrong username", + "password": user.Password, + } + body, err := json.Marshal(data) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "/login", bytes.NewReader(body)) + request.Header.Set("Content-Type", "application/json") + resp := server.TestRequest(request) + assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) + respBody, err := testutil.ReadJSONBody[map[string]string](resp.Body) + assert.NoError(t, resp.Body.Close()) + require.NoError(t, err) + assert.Equal(t, map[string]string{"error": server.Lang.GetDefault().Get("auth.invalid-credentials")}, respBody) + }) + t.Run("Login_token_func_error", func(t *testing.T) { server, user := prepareAuthenticatorTest(t) buf := &bytes.Buffer{}