feat(07-01): add bcrypt, locale override, and validation rules
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -26,8 +26,7 @@ var validateOnce = validator.New(validator.WithRequiredStructEnabled())
|
||||
func Validate(ctx context.Context, tx *gorm.DB, model any, rules map[string]string, values map[string]any, tr *phrasebook.Translator) (map[string][]string, error) {
|
||||
out := map[string][]string{}
|
||||
for field, rule := range rules {
|
||||
val, _ := values[field]
|
||||
msgs, err := validateField(ctx, tx, model, field, rule, val, tr)
|
||||
msgs, err := validateField(ctx, tx, model, field, rule, values, tr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -41,7 +40,8 @@ func Validate(ctx context.Context, tx *gorm.DB, model any, rules map[string]stri
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func validateField(ctx context.Context, tx *gorm.DB, model any, field, rule string, val any, tr *phrasebook.Translator) ([]string, error) {
|
||||
func validateField(ctx context.Context, tx *gorm.DB, model any, field, rule string, values map[string]any, tr *phrasebook.Translator) ([]string, error) {
|
||||
val := values[field]
|
||||
tokens := splitRule(rule)
|
||||
nullable := false
|
||||
required := false
|
||||
@@ -82,6 +82,29 @@ func validateField(ctx context.Context, tx *gorm.DB, model any, field, rule stri
|
||||
uniqueTable = arg
|
||||
case "boolean":
|
||||
// Go's bool field type already enforces this; treat as a type-check no-op.
|
||||
case "email":
|
||||
tags = append(tags, "email")
|
||||
case "confirmed":
|
||||
if fmt.Sprint(val) != fmt.Sprint(values[field+"_confirmation"]) {
|
||||
return []string{validateMessage(ctx, tr, "confirmed", field, nil)}, nil
|
||||
}
|
||||
case "different":
|
||||
if fmt.Sprint(val) == fmt.Sprint(values[arg]) {
|
||||
return []string{validateMessage(ctx, tr, "different", field, map[string]string{"other": arg})}, nil
|
||||
}
|
||||
case "mimes":
|
||||
got := strings.TrimPrefix(strings.ToLower(strings.TrimSpace(fmt.Sprint(val))), ".")
|
||||
match := false
|
||||
for _, ext := range strings.Split(arg, ",") {
|
||||
want := strings.TrimPrefix(strings.ToLower(strings.TrimSpace(ext)), ".")
|
||||
if got != "" && got != "<nil>" && got == want {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
return []string{validateMessage(ctx, tr, "mimes", field, nil)}, nil
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("lagoon: unrecognized validation rule %q", tok)
|
||||
}
|
||||
@@ -382,6 +405,14 @@ func validateMessage(ctx context.Context, tr *phrasebook.Translator, rule, field
|
||||
return "The " + field + " must be at least " + params["min"] + "."
|
||||
case "oneof":
|
||||
return "The selected " + field + " is invalid."
|
||||
case "email":
|
||||
return "The " + field + " must be a valid email address."
|
||||
case "confirmed":
|
||||
return "The " + field + " confirmation does not match."
|
||||
case "different":
|
||||
return "The " + field + " and " + params["other"] + " must be different."
|
||||
case "mimes":
|
||||
return "The " + field + " must be a file of the allowed types."
|
||||
default:
|
||||
return "The " + field + " is invalid."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user