From b24ffcf3f8a00aff1340ae938a946967efa372f0 Mon Sep 17 00:00:00 2001 From: Nikolai Papin Date: Sun, 3 Aug 2025 00:22:01 +0300 Subject: [PATCH] feat: birthday validation integrated into profile --- backend/internal/dto/profile.go | 2 +- backend/internal/models/auth.go | 2 +- backend/internal/services/auth.go | 7 +++++++ backend/internal/services/profile.go | 1 - backend/internal/validation/custom.go | 17 +++++++++++++++++ 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/backend/internal/dto/profile.go b/backend/internal/dto/profile.go index bba4da5..46d5a26 100644 --- a/backend/internal/dto/profile.go +++ b/backend/internal/dto/profile.go @@ -30,7 +30,7 @@ type NewProfileDto struct { Name string `json:"name" binding:"required" validate:"name"` Bio string `json:"bio" validate:"bio"` AvatarUploadID string `json:"avatar_upload_id" validate:"omitempty,upload_id=avatar"` - Birthday int64 `json:"birthday"` + Birthday int64 `json:"birthday" validate:"birthday_unix_milli"` Color string `json:"color" validate:"color_hex"` ColorGrad string `json:"color_grad" validate:"color_hex"` } diff --git a/backend/internal/models/auth.go b/backend/internal/models/auth.go index 365f644..ec467e5 100644 --- a/backend/internal/models/auth.go +++ b/backend/internal/models/auth.go @@ -32,7 +32,7 @@ type RegistrationCompleteRequest struct { Username string `json:"username" binding:"required" validate:"username"` VerificationCode string `json:"verification_code" binding:"required" validate:"verification_code=reg"` Name string `json:"name" binding:"required" validate:"name"` - Birthday *string `json:"birthday"` + Birthday int64 `json:"birthday" validate:"birthday_unix_milli"` } type RegistrationCompleteResponse struct { diff --git a/backend/internal/services/auth.go b/backend/internal/services/auth.go index 04c884f..489faaa 100644 --- a/backend/internal/services/auth.go +++ b/backend/internal/services/auth.go @@ -35,6 +35,7 @@ import ( "github.com/google/uuid" "github.com/jackc/pgerrcode" "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgtype" "go.uber.org/zap" ) @@ -437,9 +438,15 @@ func (a *authServiceImpl) RegistrationComplete(cinfo dto.ClientInfo, request mod return nil, errs.ErrServerError } + birthdayTimestamp := pgtype.Timestamp { + Time: time.UnixMilli(request.Birthday), + Valid: true, + } + profile, err = db.TXQueries.CreateProfile(db.CTX, database.CreateProfileParams{ UserID: user.ID, Name: request.Name, + Birthday: birthdayTimestamp, }) if err != nil { diff --git a/backend/internal/services/profile.go b/backend/internal/services/profile.go index c074915..39b3c8b 100644 --- a/backend/internal/services/profile.go +++ b/backend/internal/services/profile.go @@ -126,7 +126,6 @@ func (p *profileServiceImpl) GetProfileSettings(cinfo dto.ClientInfo) (*dto.Prof return profileSettingsDto, nil } -// XXX: no validation for timestamps' allowed ranges func (p *profileServiceImpl) UpdateProfile(cinfo dto.ClientInfo, newProfile dto.NewProfileDto) (bool, error) { helper, db, err := database.NewDbHelperTransaction(p.dbctx); if err != nil { p.log.Error( diff --git a/backend/internal/validation/custom.go b/backend/internal/validation/custom.go index 06ec89c..a230b19 100644 --- a/backend/internal/validation/custom.go +++ b/backend/internal/validation/custom.go @@ -21,6 +21,7 @@ import ( "easywish/config" "fmt" "regexp" + "time" "github.com/go-playground/validator/v10" ) @@ -55,6 +56,22 @@ func GetCustomHandlers() []CustomValidatorHandler { return regexp.MustCompile(`^.{1,512}$`).MatchString(username) }}, + { + FieldName: "birthday_unix_milli", + Function: func(fl validator.FieldLevel) bool { + + timestamp := fl.Field().Int() + date := time.UnixMilli(timestamp) + currentDate := time.Now() + + age := currentDate.Year() - date.Year() + if currentDate.YearDay() < date.YearDay() { + age-- + } + + return age >= 0 && age <= 122 + }}, + { FieldName: "color_hex", Function: func(fl validator.FieldLevel) bool {