feat: Use gin default validator
All checks were successful
Build and test / Build (push) Successful in 2m9s
All checks were successful
Build and test / Build (push) Successful in 2m9s
This commit is contained in:
parent
79739e3751
commit
71926b2197
3
go.mod
3
go.mod
@ -3,7 +3,6 @@ module git.vinchent.xyz/vinchent/howmuch
|
||||
go 1.23.1
|
||||
|
||||
require (
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/gin-contrib/cors v1.7.2
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
@ -31,7 +30,7 @@ require (
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
|
6
go.sum
6
go.sum
@ -1,5 +1,3 @@
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
@ -33,8 +31,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
|
||||
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
|
@ -29,7 +29,6 @@ import (
|
||||
"git.vinchent.xyz/vinchent/howmuch/internal/howmuch/usecase/usecase"
|
||||
"git.vinchent.xyz/vinchent/howmuch/internal/pkg/core"
|
||||
"git.vinchent.xyz/vinchent/howmuch/internal/pkg/errno"
|
||||
"github.com/asaskevich/govalidator"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@ -58,22 +57,26 @@ func NewUserController(us usecase.User) User {
|
||||
}
|
||||
|
||||
func (uc *UserController) Create(ctx core.Context) {
|
||||
var params model.User
|
||||
var params struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
FirstName string `json:"first_name" binding:"required"`
|
||||
LastName string `json:"last_name" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
if err := ctx.Bind(¶ms); err != nil {
|
||||
core.WriteResponse(ctx, UserParamsErr, nil)
|
||||
return
|
||||
}
|
||||
|
||||
_, err := govalidator.ValidateStruct(params)
|
||||
if err != nil {
|
||||
errno := UserParamsErr
|
||||
errno.Message = err.Error()
|
||||
core.WriteResponse(ctx, errno, nil)
|
||||
return
|
||||
user := model.User{
|
||||
Email: params.Email,
|
||||
FirstName: params.FirstName,
|
||||
LastName: params.LastName,
|
||||
Password: params.Password,
|
||||
}
|
||||
|
||||
_, err = uc.userUsecase.Create(ctx, ¶ms)
|
||||
_, err := uc.userUsecase.Create(ctx, &user)
|
||||
if err != nil {
|
||||
core.WriteResponse(ctx, err, nil)
|
||||
return
|
||||
|
@ -26,11 +26,11 @@ import "time"
|
||||
|
||||
// User model
|
||||
type User struct {
|
||||
ID int `json:"id"`
|
||||
Email string `json:"email" valid:"email"`
|
||||
FirstName string `json:"first_name" valid:"required"`
|
||||
LastName string `json:"last_name" valid:"required"`
|
||||
Password string `json:"password" valid:"required"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID int
|
||||
Email string
|
||||
FirstName string
|
||||
LastName string
|
||||
Password string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ type userUsecase struct {
|
||||
|
||||
type User interface {
|
||||
Create(ctx context.Context, u *model.User) (*model.User, error)
|
||||
Exist(ctx context.Context, u *model.User) (bool, error)
|
||||
Exist(ctx context.Context, u *model.User) error
|
||||
}
|
||||
|
||||
func NewUserUsecase(r repo.UserRepository, d repo.DBRepository) User {
|
||||
@ -113,23 +113,23 @@ func (uuc *userUsecase) Create(ctx context.Context, u *model.User) (*model.User,
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (uuc *userUsecase) Exist(ctx context.Context, u *model.User) (bool, error) {
|
||||
func (uuc *userUsecase) Exist(ctx context.Context, u *model.User) error {
|
||||
got, err := uuc.userRepo.GetByEmail(ctx, u.Email)
|
||||
// Any query error?
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
|
||||
// User exists?
|
||||
if got == nil {
|
||||
return false, UserNotExist
|
||||
return UserNotExist
|
||||
}
|
||||
|
||||
// Password correct?
|
||||
err = bcrypt.CompareHashAndPassword([]byte(got.Password), []byte(u.Password))
|
||||
if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
|
||||
return false, UserWrongPassword
|
||||
return UserWrongPassword
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return nil
|
||||
}
|
||||
|
@ -69,32 +69,30 @@ func TestUserExist(t *testing.T) {
|
||||
Name string
|
||||
User *model.User
|
||||
ExpErr error
|
||||
ExpRes bool
|
||||
}{
|
||||
{"user exists", &model.User{
|
||||
Email: "a@b.c",
|
||||
Password: "strongHashed",
|
||||
}, nil, true},
|
||||
}, nil},
|
||||
{"query error", &model.User{
|
||||
Email: "query@error.com",
|
||||
Password: "strongHashed",
|
||||
}, repomock.UserTestDummyErr, false},
|
||||
}, repomock.UserTestDummyErr},
|
||||
{"user doesn not exist", &model.User{
|
||||
Email: "inexist@error.com",
|
||||
Password: "strongHashed",
|
||||
}, UserNotExist, false},
|
||||
}, UserNotExist},
|
||||
{"wrong password", &model.User{
|
||||
Email: "a@b.c",
|
||||
Password: "wrongHashed",
|
||||
}, UserWrongPassword, false},
|
||||
}, UserWrongPassword},
|
||||
}
|
||||
|
||||
for _, tst := range testCases {
|
||||
ctx := context.Background()
|
||||
userUsecase := NewUserUsecase(&repomock.TestUserRepository{}, &repomock.TestDBRepository{})
|
||||
|
||||
got, err := userUsecase.Exist(ctx, tst.User)
|
||||
err := userUsecase.Exist(ctx, tst.User)
|
||||
assert.ErrorIs(t, err, tst.ExpErr)
|
||||
assert.Equal(t, tst.ExpRes, got)
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,25 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2024 vinchent <vinchent@vinchent.xyz>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
|
Loading…
Reference in New Issue
Block a user