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

@@ -325,6 +325,12 @@ func (s CRUDService) save(ctx context.Context, cc *CompiledController, id any, i
}
projected := projectOperation(cc, in.Body, op)
if err := lagoon.Fill(target, fillAllowed(cc, target, op), projected, false); err != nil {
// A value that does not fit its column is the admin's input,
// not a missing capability: answer it on the field.
var typed *lagoon.FillTypeError
if errors.As(err, &typed) {
return &ValidationError{Details: fillTypeDetails(typed.Key)}
}
return &CapabilityError{ControllerID: controllerID(cc)}
}
if hook, ok := target.(lagoon.HasBeforeValidate); ok && hook != nil {
@@ -737,6 +743,12 @@ func valuesForRules(model any, rules map[string]string) map[string]any {
return out
}
// fillTypeDetails is the 422 detail for a value lagoon.Fill could not store
// in its column. Writable fill keys equal their form field names.
func fillTypeDetails(key string) map[string]any {
return map[string]any{key: []string{"The " + key + " field has an invalid value."}}
}
func validationDetails(msgs map[string][]string) map[string]any {
out := make(map[string]any, len(msgs))
for key, messages := range msgs {