diff --git a/go.mod b/go.mod index b3f0be3e83..54de2028ee 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/mindersec/minder go 1.23.4 require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1 + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1 github.com/ThreeDotsLabs/watermill v1.4.1 github.com/ThreeDotsLabs/watermill-sql/v3 v3.1.0 github.com/alexdrl/zerowater v0.0.3 @@ -11,7 +11,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.28.6 github.com/aws/aws-sdk-go-v2/service/sesv2 v1.40.0 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df - github.com/bufbuild/protovalidate-go v0.7.3 + github.com/bufbuild/protovalidate-go v0.8.0 github.com/cenkalti/backoff/v4 v4.3.0 github.com/charmbracelet/bubbles v0.20.0 github.com/charmbracelet/bubbletea v1.2.4 diff --git a/go.sum b/go.sum index 2aa6256868..477adad87d 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1 h1:7QIeAuTdLp173vC/9JojRMDFcpmqtoYrxPmvdHAOynw= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1/go.mod h1:mnHCFccv4HwuIAOHNGdiIc5ZYbBCvbTWZcodLN5wITI= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1 h1:jLd96rDDNJ+zIJxvV/L855VEtrjR0G4aePVDlCpf6kw= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1/go.mod h1:mnHCFccv4HwuIAOHNGdiIc5ZYbBCvbTWZcodLN5wITI= cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo= cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -217,8 +217,8 @@ github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0 github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= -github.com/bufbuild/protovalidate-go v0.7.3 h1:kKnoSueygR3xxppvuBpm9SEwIsP359MMRfMBGmRByPg= -github.com/bufbuild/protovalidate-go v0.7.3/go.mod h1:CFv34wMqiBzAHdQ4q/tWYi9ILFYKuaC3/4zh6eqdUck= +github.com/bufbuild/protovalidate-go v0.8.0 h1:Xs3kCLCJ4tQiogJ0iOXm+ClKw/KviW3nLAryCGW2I3Y= +github.com/bufbuild/protovalidate-go v0.8.0/go.mod h1:JPWZInGm2y2NBg3vKDKdDIkvDjyLv31J3hLH5GIFc/Q= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= diff --git a/internal/api/api.go b/internal/api/api.go index dcf9cdba23..ca13cdb0cf 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -60,7 +60,33 @@ func NewValidator() (*protovalidate.Validator, error) { func formatViolations(violations *validate.Violations) string { var res []string for _, v := range violations.Violations { - res = append(res, fmt.Sprintf("- Field '%s': %s", *v.FieldPath, *v.Message)) + res = append(res, fmt.Sprintf("- Field '%s': %s", getFullPath(v.Field), *v.Message)) } return strings.Join(res, "\n") } + +func getFullPath(field *validate.FieldPath) string { + var pathElements []string + for _, element := range field.GetElements() { + if element.GetFieldName() != "" { + pathElements = append(pathElements, element.GetFieldName()) + } else if element.GetFieldNumber() != 0 { + pathElements = append(pathElements, fmt.Sprintf("%d", element.GetFieldNumber())) + } + if element.GetSubscript() != nil { + switch subscript := element.GetSubscript().(type) { + case *validate.FieldPathElement_Index: + pathElements[len(pathElements)-1] = fmt.Sprintf("%s[%d]", pathElements[len(pathElements)-1], subscript.Index) + case *validate.FieldPathElement_BoolKey: + pathElements[len(pathElements)-1] = fmt.Sprintf("%s[%t]", pathElements[len(pathElements)-1], subscript.BoolKey) + case *validate.FieldPathElement_IntKey: + pathElements[len(pathElements)-1] = fmt.Sprintf("%s[%d]", pathElements[len(pathElements)-1], subscript.IntKey) + case *validate.FieldPathElement_UintKey: + pathElements[len(pathElements)-1] = fmt.Sprintf("%s[%d]", pathElements[len(pathElements)-1], subscript.UintKey) + case *validate.FieldPathElement_StringKey: + pathElements[len(pathElements)-1] = fmt.Sprintf("%s[%s]", pathElements[len(pathElements)-1], subscript.StringKey) + } + } + } + return strings.Join(pathElements, ".") +} diff --git a/internal/api/api_test.go b/internal/api/api_test.go index 0336113124..e124b6d566 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -46,6 +46,21 @@ func TestProtoValidationInterceptor(t *testing.T) { errMsg: "Validation failed:\n- Field 'name': value does not match regex pattern", errCode: codes.InvalidArgument, }, + { + name: "invalid request with nested field", + req: &v1.ListEvaluationResultsRequest{ + Context: &v1.Context{ + Project: ptr.Ptr(uuid.New().String()), + }, + Entity: []*v1.EntityTypedId{ + { + Id: "invalid-id", + }, + }, + }, + errMsg: "Validation failed:\n- Field 'entity[0].id': value must be a valid UUID", + errCode: codes.InvalidArgument, + }, } validator, err := NewValidator()