@@ -12,21 +12,24 @@ import (
12
12
"strings"
13
13
"time"
14
14
15
+ "github.com/coder/coder/coderd/httpapi/validate"
16
+
15
17
"github.com/go-playground/validator/v10"
16
18
"golang.org/x/xerrors"
17
19
18
20
"github.com/coder/coder/coderd/tracing"
19
21
"github.com/coder/coder/codersdk"
20
22
)
21
23
22
- var Validate * validator. Validate
24
+ var Validate * validate. Validator
23
25
24
26
// This init is used to create a validator and register validation-specific
25
27
// functionality for the HTTP API.
26
28
//
27
29
// A single validator instance is used, because it caches struct parsing.
28
30
func init () {
29
- Validate = validator .New ()
31
+ Validate = validate .New ()
32
+
30
33
Validate .RegisterTagNameFunc (func (fld reflect.StructField ) string {
31
34
name := strings .SplitN (fld .Tag .Get ("json" ), "," , 2 )[0 ]
32
35
if name == "-" {
@@ -35,14 +38,13 @@ func init() {
35
38
return name
36
39
})
37
40
38
- nameValidator := func (fl validator.FieldLevel ) bool {
41
+ nameValidator := func (fl validator.FieldLevel ) error {
39
42
f := fl .Field ().Interface ()
40
43
str , ok := f .(string )
41
44
if ! ok {
42
- return false
45
+ return xerrors . New ( "name must be a string" )
43
46
}
44
- valid := NameValid (str )
45
- return valid == nil
47
+ return NameValid (str )
46
48
}
47
49
for _ , tag := range []string {"username" , "template_name" , "workspace_name" } {
48
50
err := Validate .RegisterValidation (tag , nameValidator )
@@ -51,28 +53,26 @@ func init() {
51
53
}
52
54
}
53
55
54
- templateDisplayNameValidator := func (fl validator.FieldLevel ) bool {
56
+ templateDisplayNameValidator := func (fl validator.FieldLevel ) error {
55
57
f := fl .Field ().Interface ()
56
58
str , ok := f .(string )
57
59
if ! ok {
58
- return false
60
+ return xerrors . New ( "template_display_name must be a string" )
59
61
}
60
- valid := TemplateDisplayNameValid (str )
61
- return valid == nil
62
+ return TemplateDisplayNameValid (str )
62
63
}
63
64
err := Validate .RegisterValidation ("template_display_name" , templateDisplayNameValidator )
64
65
if err != nil {
65
66
panic (err )
66
67
}
67
68
68
- templateVersionNameValidator := func (fl validator.FieldLevel ) bool {
69
+ templateVersionNameValidator := func (fl validator.FieldLevel ) error {
69
70
f := fl .Field ().Interface ()
70
71
str , ok := f .(string )
71
72
if ! ok {
72
- return false
73
+ return xerrors . New ( "template_version_name must be a string" )
73
74
}
74
- valid := TemplateVersionNameValid (str )
75
- return valid == nil
75
+ return TemplateVersionNameValid (str )
76
76
}
77
77
err = Validate .RegisterValidation ("template_version_name" , templateVersionNameValidator )
78
78
if err != nil {
@@ -168,9 +168,15 @@ func Read(ctx context.Context, rw http.ResponseWriter, r *http.Request, value in
168
168
if errors .As (err , & validationErrors ) {
169
169
apiErrors := make ([]codersdk.ValidationError , 0 , len (validationErrors ))
170
170
for _ , validationError := range validationErrors {
171
+ detail := fmt .Sprintf ("Validation failed for tag %q with value: \" %v\" " , validationError .Tag (), validationError .Value ())
172
+ var custom validate.DetailedFieldError
173
+ if xerrors .As (validationError , & custom ) {
174
+ detail = fmt .Sprintf ("Validation failed for tag %q=\" %v\" : %s" , validationError .Tag (), validationError .Value (), custom .Error ())
175
+ }
176
+
171
177
apiErrors = append (apiErrors , codersdk.ValidationError {
172
178
Field : validationError .Field (),
173
- Detail : fmt . Sprintf ( "Validation failed for tag %q with value: \" %v \" " , validationError . Tag (), validationError . Value ()) ,
179
+ Detail : detail ,
174
180
})
175
181
}
176
182
Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
0 commit comments