fix(10.1): CR-01 answer a value that does not fit its column with a 422

lagoon.Fill now returns a *lagoon.FillTypeError naming the key when a
requested value cannot be stored in its column (a fraction, exponent or
overflow for an integer field, or a value of the wrong type). The admin
save path maps it to a validation_failed 422 on that field instead of a
500 CapabilityError; genuine capability failures keep the 500.
This commit is contained in:
Jakub Zych
2026-09-29 09:44:14 +02:00
parent 74e30c9878
commit e60e69745e
6 changed files with 152 additions and 4 deletions

View File

@@ -25,9 +25,25 @@ type HasHidden interface {
var droppedKeys sync.Map
// FillTypeError reports a requested value that cannot be stored in its
// column: a fraction, an exponent or an overflow for an integer field, or a
// value of the wrong type. Key is the column the value was requested for, so
// a caller can answer it as a validation failure on that field. Fill returns
// any other failure, such as a model that is not a struct pointer, as a
// plain error.
type FillTypeError struct {
Key string
Err error
}
func (e *FillTypeError) Error() string { return "lagoon: fill " + e.Key + ": " + e.Err.Error() }
func (e *FillTypeError) Unwrap() error { return e.Err }
// Fill copies requested keys onto model only when they are also in allowed.
// Unknown and non-fillable keys are dropped with no error (D-06). In
// non-production, each type+key pair is logged once.
// non-production, each type+key pair is logged once. A value that does not
// fit its column is a *FillTypeError.
func Fill(model any, allowed []string, requested map[string]any, production bool) error {
if model == nil {
return fmt.Errorf("lagoon: fill model is nil")
@@ -53,7 +69,7 @@ func Fill(model any, allowed []string, requested map[string]any, production bool
continue
}
if err := setField(field, val); err != nil {
return fmt.Errorf("lagoon: fill %s: %w", key, err)
return &FillTypeError{Key: key, Err: err}
}
}
return nil