feat: birthday validation integrated into profile

This commit is contained in:
2025-08-03 00:22:01 +03:00
parent 3a63a14c4d
commit b24ffcf3f8
5 changed files with 26 additions and 3 deletions

View File

@@ -30,7 +30,7 @@ type NewProfileDto struct {
Name string `json:"name" binding:"required" validate:"name"` Name string `json:"name" binding:"required" validate:"name"`
Bio string `json:"bio" validate:"bio"` Bio string `json:"bio" validate:"bio"`
AvatarUploadID string `json:"avatar_upload_id" validate:"omitempty,upload_id=avatar"` 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"` Color string `json:"color" validate:"color_hex"`
ColorGrad string `json:"color_grad" validate:"color_hex"` ColorGrad string `json:"color_grad" validate:"color_hex"`
} }

View File

@@ -32,7 +32,7 @@ type RegistrationCompleteRequest struct {
Username string `json:"username" binding:"required" validate:"username"` Username string `json:"username" binding:"required" validate:"username"`
VerificationCode string `json:"verification_code" binding:"required" validate:"verification_code=reg"` VerificationCode string `json:"verification_code" binding:"required" validate:"verification_code=reg"`
Name string `json:"name" binding:"required" validate:"name"` Name string `json:"name" binding:"required" validate:"name"`
Birthday *string `json:"birthday"` Birthday int64 `json:"birthday" validate:"birthday_unix_milli"`
} }
type RegistrationCompleteResponse struct { type RegistrationCompleteResponse struct {

View File

@@ -35,6 +35,7 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jackc/pgerrcode" "github.com/jackc/pgerrcode"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
"go.uber.org/zap" "go.uber.org/zap"
) )
@@ -437,9 +438,15 @@ func (a *authServiceImpl) RegistrationComplete(cinfo dto.ClientInfo, request mod
return nil, errs.ErrServerError return nil, errs.ErrServerError
} }
birthdayTimestamp := pgtype.Timestamp {
Time: time.UnixMilli(request.Birthday),
Valid: true,
}
profile, err = db.TXQueries.CreateProfile(db.CTX, database.CreateProfileParams{ profile, err = db.TXQueries.CreateProfile(db.CTX, database.CreateProfileParams{
UserID: user.ID, UserID: user.ID,
Name: request.Name, Name: request.Name,
Birthday: birthdayTimestamp,
}) })
if err != nil { if err != nil {

View File

@@ -126,7 +126,6 @@ func (p *profileServiceImpl) GetProfileSettings(cinfo dto.ClientInfo) (*dto.Prof
return profileSettingsDto, nil return profileSettingsDto, nil
} }
// XXX: no validation for timestamps' allowed ranges
func (p *profileServiceImpl) UpdateProfile(cinfo dto.ClientInfo, newProfile dto.NewProfileDto) (bool, error) { func (p *profileServiceImpl) UpdateProfile(cinfo dto.ClientInfo, newProfile dto.NewProfileDto) (bool, error) {
helper, db, err := database.NewDbHelperTransaction(p.dbctx); if err != nil { helper, db, err := database.NewDbHelperTransaction(p.dbctx); if err != nil {
p.log.Error( p.log.Error(

View File

@@ -21,6 +21,7 @@ import (
"easywish/config" "easywish/config"
"fmt" "fmt"
"regexp" "regexp"
"time"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
) )
@@ -55,6 +56,22 @@ func GetCustomHandlers() []CustomValidatorHandler {
return regexp.MustCompile(`^.{1,512}$`).MatchString(username) 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", FieldName: "color_hex",
Function: func(fl validator.FieldLevel) bool { Function: func(fl validator.FieldLevel) bool {