feat: add validation of input data in auth

This commit is contained in:
Sosokker 2025-03-12 14:57:45 +07:00
parent 5b77d27dcb
commit 69fa65ccf1

View File

@ -4,17 +4,18 @@ import (
"context"
"errors"
"net/http"
"regexp"
"github.com/danielgtaylor/huma/v2"
"github.com/forfarm/backend/internal/domain"
"github.com/forfarm/backend/internal/utilities"
"github.com/go-chi/chi/v5"
validation "github.com/go-ozzo/ozzo-validation/v4"
"golang.org/x/crypto/bcrypt"
)
func (a *api) registerAuthRoutes(_ chi.Router, api huma.API) {
tags := []string{"auth"}
prefix := "/auth"
huma.Register(api, huma.Operation{
@ -34,34 +35,61 @@ func (a *api) registerAuthRoutes(_ chi.Router, api huma.API) {
type LoginInput struct {
Body struct {
Email string `json:"email" example:" Email address of the user"`
Password string `json:"password" example:" Password of the user"`
Email string `json:"email" example:"Email address of the user"`
Password string `json:"password" example:"Password of the user"`
}
}
type LoginOutput struct {
Body struct {
Token string `json:"token" example:" JWT token for the user"`
Token string `json:"token" example:"JWT token for the user"`
}
}
type RegisterInput struct {
Body struct {
Email string `json:"email" example:" Email address of the user"`
Password string `json:"password" example:" Password of the user"`
Email string `json:"email" example:"Email address of the user"`
Password string `json:"password" example:"Password of the user"`
}
}
type RegisterOutput struct {
Body struct {
Token string `json:"token" example:" JWT token for the user"`
Token string `json:"token" example:"JWT token for the user"`
}
}
func validateEmail(email string) error {
return validation.Validate(email,
validation.Required.Error("email is required"),
validation.Match(regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}$`)).Error("invalid email format"),
)
}
func validatePassword(password string) error {
return validation.Validate(password,
validation.Required.Error("password is required"),
validation.Length(8, 0).Error("password must be at least 8 characters long"),
validation.Match(regexp.MustCompile(`[A-Z]`)).Error("password must contain at least one uppercase letter"),
validation.Match(regexp.MustCompile(`[a-z]`)).Error("password must contain at least one lowercase letter"),
validation.Match(regexp.MustCompile(`[0-9]`)).Error("password must contain at least one numeral"),
validation.Match(regexp.MustCompile(`[\W_]`)).Error("password must contain at least one special character"),
)
}
func (a *api) registerHandler(ctx context.Context, input *RegisterInput) (*RegisterOutput, error) {
resp := &RegisterOutput{}
// TODO: Validate input data
if input == nil {
return nil, errors.New("invalid input")
}
if err := validateEmail(input.Body.Email); err != nil {
return nil, err
}
if err := validatePassword(input.Body.Password); err != nil {
return nil, err
}
_, err := a.userRepo.GetByEmail(ctx, input.Body.Email)
if err == domain.ErrNotFound {
@ -78,7 +106,12 @@ func (a *api) registerHandler(ctx context.Context, input *RegisterInput) (*Regis
return nil, err
}
token, err := utilities.CreateJwtToken(input.Body.Email)
user, err := a.userRepo.GetByEmail(ctx, input.Body.Email)
if err != nil {
return nil, err
}
token, err := utilities.CreateJwtToken(user.UUID)
if err != nil {
return nil, err
}
@ -93,14 +126,25 @@ func (a *api) registerHandler(ctx context.Context, input *RegisterInput) (*Regis
func (a *api) loginHandler(ctx context.Context, input *LoginInput) (*LoginOutput, error) {
resp := &LoginOutput{}
// TODO: Validate input data
if input == nil {
return nil, errors.New("invalid input")
}
if input.Body.Email == "" {
return nil, errors.New("email field is required")
}
if input.Body.Password == "" {
return nil, errors.New("password field is required")
}
if err := validateEmail(input.Body.Email); err != nil {
return nil, err
}
user, err := a.userRepo.GetByEmail(ctx, input.Body.Email)
if err != nil {
return nil, err
}
// verify password hash
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(input.Body.Password)); err != nil {
return nil, err
}