Skip to content

Commit

Permalink
Add validation for user fields
Browse files Browse the repository at this point in the history
Integrated validation for "name" and "email" fields in user models. Updated the UserHandler to register custom validators using go-playground/validator. Added custom error messages for validation to improve clarity for users.
  • Loading branch information
mukulmantosh committed Aug 27, 2024
1 parent 4d99f39 commit 3ab1cdc
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 8 deletions.
2 changes: 1 addition & 1 deletion cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func main() {

// User
userService := usr.NewUserService(db, env)
user.NewUserHandler(s, "/user", userService)
user.NewUserHandler(s, "/user", userService, validate)

// Restaurant
restaurantService := restro.NewRestaurantService(db, env)
Expand Down
43 changes: 41 additions & 2 deletions pkg/database/models/user/user.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package user

import (
"errors"
"github.com/go-playground/validator/v10"
"github.com/uptrace/bun"
"golang.org/x/crypto/bcrypt"
"log"
"regexp"
)

type User struct {
bun.BaseModel `bun:"table:users"`
ID int64 `bun:",pk,autoincrement" json:"id"`
Name string `bun:",notnull" json:"name"`
Email string `bun:",unique,notnull" json:"email"`
Name string `bun:",notnull" json:"name" validate:"name"`
Email string `bun:",unique,notnull" json:"email" validate:"email"`
Password string `bun:",notnull" json:"password"`
}

Expand All @@ -30,3 +33,39 @@ func (u *User) HashPassword() {
func (l *LoginUser) CheckPassword(hashPassword string) error {
return bcrypt.CompareHashAndPassword([]byte(hashPassword), []byte(l.Password))
}

func NameValidator(fl validator.FieldLevel) bool {
str, ok := fl.Field().Interface().(string)
return ok && str != ""
}

func EmailValidator(fl validator.FieldLevel) bool {
email, ok := fl.Field().Interface().(string)
if !ok {
return false
}
// Basic email regex pattern
re := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
return re.MatchString(email)
}

func UserValidationError(err error) map[string]string {
var validationErrors validator.ValidationErrors
if !errors.As(err, &validationErrors) {
return map[string]string{"error": "Unknown error"}
}

errorsMap := make(map[string]string)
for _, e := range validationErrors {
field := e.Field()
switch e.Tag() {
case "name":
errorsMap[field] = "Provide your full name"
case "email":
errorsMap[field] = "Provide valid email address"
default:
errorsMap[field] = "Invalid"
}
}
return errorsMap
}
20 changes: 15 additions & 5 deletions pkg/handler/user/service.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
package user

import (
userValidate "Go_Food_Delivery/pkg/database/models/user"
"Go_Food_Delivery/pkg/handler"
"Go_Food_Delivery/pkg/service/user"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
)

type UserHandler struct {
Serve *handler.Server
group string
router *gin.RouterGroup
service *user.UsrService
Serve *handler.Server
group string
router *gin.RouterGroup
service *user.UsrService
validate *validator.Validate
}

func NewUserHandler(s *handler.Server, groupName string, service *user.UsrService) {
func NewUserHandler(s *handler.Server, groupName string, service *user.UsrService, validate *validator.Validate) {

usrHandler := &UserHandler{
s,
groupName,
&gin.RouterGroup{},
service,
validate,
}
usrHandler.router = usrHandler.registerGroup()
usrHandler.routes()
usrHandler.registerValidator()
}

func (s *UserHandler) registerValidator() {
_ = s.validate.RegisterValidation("name", userValidate.NameValidator)
_ = s.validate.RegisterValidation("email", userValidate.EmailValidator)
}
6 changes: 6 additions & 0 deletions pkg/handler/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ func (s *UserHandler) addUser(c *gin.Context) {
return
}

if err := s.validate.Struct(user); err != nil {
validationError := userModel.UserValidationError(err)
c.JSON(http.StatusBadRequest, gin.H{"error": validationError})
return
}

_, err := s.service.Add(ctx, &user)
if err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": err.Error()})
Expand Down

0 comments on commit 3ab1cdc

Please sign in to comment.