mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-21 18:00:45 +00:00
refactor: http request binding (#38971)
Better than before, still not good enough (more work can be done in the future) And add the missing error handling in the PrivateContext "bind" middleware. By the way, picked some "TrimSpace" changes from "fix: trim whitespace from SMTP address and port - #38934" (fix #38926)
This commit is contained in:
+76
-165
@@ -4,17 +4,20 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"io"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gitea.dev/modules/auth"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/glob"
|
||||
"gitea.dev/modules/json"
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
"gitea.com/go-chi/binding" //nolint:depguard // this package wraps it
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -41,178 +44,75 @@ func (j jsonProvider) NewEncoder(writer io.Writer) binding.JSONEncoder {
|
||||
return json.NewEncoder(writer)
|
||||
}
|
||||
|
||||
func newFieldError(field reflect.StructField, cls, msg string) *BindingError {
|
||||
return &BindingError{[]string{field.Name}, cls, msg} //nolint:govet // make sure no missing fields
|
||||
}
|
||||
|
||||
// AddBindingRules adds additional binding rules
|
||||
func AddBindingRules() {
|
||||
func AddBindingRules(b *binding.Binder) {
|
||||
binding.JSONProvider = jsonProvider{}
|
||||
addGitRefNameBindingRule()
|
||||
addValidURLBindingRule()
|
||||
addValidSiteURLBindingRule()
|
||||
addGlobPatternRule()
|
||||
addRegexPatternRule()
|
||||
addGlobOrRegexPatternRule()
|
||||
addUsernamePatternRule()
|
||||
addValidGroupTeamMapRule()
|
||||
addSlugPatternRule()
|
||||
}
|
||||
|
||||
func addGitRefNameBindingRule() {
|
||||
// Git ref name validation rule
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "GitRefName"
|
||||
},
|
||||
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
str := fmt.Sprintf("%v", val)
|
||||
|
||||
if !git.IsValidRefPattern(str) {
|
||||
errs.Add([]string{name}, ErrGitRefName, "GitRefName")
|
||||
return false, errs
|
||||
}
|
||||
return true, errs
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func addValidURLBindingRule() {
|
||||
// URL validation rule
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "ValidUrl"
|
||||
},
|
||||
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
str := fmt.Sprintf("%v", val)
|
||||
if len(str) != 0 && !IsValidURL(str) {
|
||||
errs.Add([]string{name}, binding.ERR_URL, "Url")
|
||||
return false, errs
|
||||
}
|
||||
|
||||
return true, errs
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func addValidSiteURLBindingRule() {
|
||||
// URL validation rule
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "ValidSiteUrl"
|
||||
},
|
||||
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
str := fmt.Sprintf("%v", val)
|
||||
if len(str) != 0 && !IsValidSiteURL(str) {
|
||||
errs.Add([]string{name}, binding.ERR_URL, "Url")
|
||||
return false, errs
|
||||
}
|
||||
|
||||
return true, errs
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func addSlugPatternRule() {
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "BadgeSlug"
|
||||
},
|
||||
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
str := fmt.Sprintf("%v", val)
|
||||
if !IsValidBadgeSlug(str) {
|
||||
errs.Add([]string{name}, ErrInvalidBadgeSlug, "invalid badge slug")
|
||||
return false, errs
|
||||
}
|
||||
return true, errs
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func addGlobPatternRule() {
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "GlobPattern"
|
||||
},
|
||||
IsValid: globPatternValidator,
|
||||
})
|
||||
}
|
||||
|
||||
func globPatternValidator(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
str := fmt.Sprintf("%v", val)
|
||||
|
||||
if len(str) != 0 {
|
||||
if _, err := glob.Compile(str); err != nil {
|
||||
errs.Add([]string{name}, ErrGlobPattern, err.Error())
|
||||
return false, errs
|
||||
b.AddRuleNonZero("GitRefName", func(ctx context.Context, f *binding.ValidationField) *binding.Error {
|
||||
if !git.IsValidRefPattern(f.ValueMustString()) {
|
||||
return newFieldError(f.StructField, ErrGitRefName, "GitRefName")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
b.AddRuleNonZero("ValidUrl", func(ctx context.Context, f *binding.ValidationField) *binding.Error {
|
||||
if !IsValidURL(f.ValueMustString()) {
|
||||
return newFieldError(f.StructField, binding.ERR_URL, "Url")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
b.AddRuleNonZero("ValidSiteUrl", func(ctx context.Context, f *binding.ValidationField) *binding.Error {
|
||||
if !IsValidSiteURL(f.ValueMustString()) {
|
||||
return newFieldError(f.StructField, binding.ERR_URL, "Url")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
b.AddRuleNonZero("BadgeSlug", func(ctx context.Context, f *binding.ValidationField) *binding.Error {
|
||||
if !IsValidBadgeSlug(f.ValueMustString()) {
|
||||
return newFieldError(f.StructField, ErrInvalidBadgeSlug, "invalid badge slug")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
ruleGlobPattern := func(_ context.Context, f *binding.ValidationField) *binding.Error {
|
||||
if _, err := glob.Compile(f.ValueMustString()); err != nil {
|
||||
return newFieldError(f.StructField, ErrGlobPattern, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return true, errs
|
||||
}
|
||||
|
||||
func addRegexPatternRule() {
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "RegexPattern"
|
||||
},
|
||||
IsValid: regexPatternValidator,
|
||||
})
|
||||
}
|
||||
|
||||
func regexPatternValidator(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
str := fmt.Sprintf("%v", val)
|
||||
|
||||
if _, err := regexp.Compile(str); err != nil {
|
||||
errs.Add([]string{name}, ErrRegexPattern, err.Error())
|
||||
return false, errs
|
||||
b.AddRuleNonZero("GlobPattern", ruleGlobPattern)
|
||||
ruleRegexPattern := func(_ context.Context, f *binding.ValidationField, val string) *binding.Error {
|
||||
if _, err := regexp.Compile(val); err != nil {
|
||||
return newFieldError(f.StructField, ErrRegexPattern, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return true, errs
|
||||
}
|
||||
|
||||
func addGlobOrRegexPatternRule() {
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "GlobOrRegexPattern"
|
||||
},
|
||||
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
str := strings.TrimSpace(fmt.Sprintf("%v", val))
|
||||
|
||||
if len(str) >= 2 && strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
|
||||
return regexPatternValidator(errs, name, str[1:len(str)-1])
|
||||
}
|
||||
return globPatternValidator(errs, name, val)
|
||||
},
|
||||
b.AddRuleNonZero("RegexPattern", func(ctx context.Context, f *binding.ValidationField) *binding.Error {
|
||||
return ruleRegexPattern(ctx, f, f.ValueMustString())
|
||||
})
|
||||
}
|
||||
|
||||
func addUsernamePatternRule() {
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "Username"
|
||||
},
|
||||
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
str := fmt.Sprintf("%v", val)
|
||||
if !IsValidUsername(str) {
|
||||
errs.Add([]string{name}, ErrUsername, "invalid username")
|
||||
return false, errs
|
||||
}
|
||||
return true, errs
|
||||
},
|
||||
b.AddRuleNonZero("GlobOrRegexPattern", func(ctx context.Context, f *binding.ValidationField) *binding.Error {
|
||||
str := f.ValueMustString()
|
||||
if len(str) >= 2 && strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
|
||||
return ruleRegexPattern(ctx, f, str[1:len(str)-1])
|
||||
}
|
||||
return ruleGlobPattern(ctx, f)
|
||||
})
|
||||
}
|
||||
|
||||
func addValidGroupTeamMapRule() {
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "ValidGroupTeamMap"
|
||||
},
|
||||
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
||||
_, err := auth.UnmarshalGroupTeamMapping(fmt.Sprintf("%v", val))
|
||||
if err != nil {
|
||||
errs.Add([]string{name}, ErrInvalidGroupTeamMap, err.Error())
|
||||
return false, errs
|
||||
}
|
||||
b.AddRuleNonZero("Username", func(ctx context.Context, f *binding.ValidationField) *binding.Error {
|
||||
if !IsValidUsername(f.ValueMustString()) {
|
||||
return newFieldError(f.StructField, ErrUsername, "invalid username")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return true, errs
|
||||
},
|
||||
b.AddRuleNonZero("ValidGroupTeamMap", func(ctx context.Context, f *binding.ValidationField) *binding.Error {
|
||||
_, err := auth.UnmarshalGroupTeamMapping(f.ValueMustString())
|
||||
if err != nil {
|
||||
return newFieldError(f.StructField, ErrInvalidGroupTeamMap, err.Error())
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -238,3 +138,14 @@ func validPort(p string) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var Binder = sync.OnceValue(func() *binding.Binder {
|
||||
b := binding.NewBinder().WithDefaultRules().WithNameMapper(util.ToSnakeCase)
|
||||
AddBindingRules(b)
|
||||
return b
|
||||
})
|
||||
|
||||
type (
|
||||
BindingErrors = binding.Errors
|
||||
BindingError = binding.Error
|
||||
)
|
||||
|
||||
@@ -4,24 +4,16 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
chi "github.com/go-chi/chi/v5"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
testRoute = "/test"
|
||||
)
|
||||
|
||||
type (
|
||||
validationTestCase struct {
|
||||
description string
|
||||
data any
|
||||
expectedErrors binding.Errors
|
||||
expectedErrors BindingErrors
|
||||
}
|
||||
|
||||
TestForm struct {
|
||||
@@ -33,24 +25,5 @@ type (
|
||||
)
|
||||
|
||||
func performValidationTest(t *testing.T, testCase validationTestCase) {
|
||||
httpRecorder := httptest.NewRecorder()
|
||||
m := chi.NewRouter()
|
||||
|
||||
m.Post(testRoute, func(resp http.ResponseWriter, req *http.Request) {
|
||||
assert.Equal(t, testCase.expectedErrors, binding.Validate(req, testCase.data))
|
||||
})
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, testRoute, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
req.Header.Add("Content-Type", "x-www-form-urlencoded")
|
||||
m.ServeHTTP(httpRecorder, req)
|
||||
|
||||
switch httpRecorder.Code {
|
||||
case http.StatusNotFound:
|
||||
panic("Routing is messed up in test fixture (got 404): check methods and paths")
|
||||
case http.StatusInternalServerError:
|
||||
panic("Something bad happened on '" + testCase.description + "'")
|
||||
}
|
||||
assert.Equal(t, testCase.expectedErrors, Binder().Validate(t.Context(), testCase.data))
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"gitea.dev/modules/glob"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
)
|
||||
|
||||
func getGlobPatternErrorString(pattern string) string {
|
||||
@@ -21,29 +19,27 @@ func getGlobPatternErrorString(pattern string) string {
|
||||
}
|
||||
|
||||
func Test_GlobPatternValidation(t *testing.T) {
|
||||
AddBindingRules()
|
||||
|
||||
globValidationTestCases := []validationTestCase{
|
||||
{
|
||||
description: "Empty glob pattern",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
GlobPattern: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Valid glob",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
GlobPattern: "{master,release*}",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
description: "Invalid glob",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
GlobPattern: "[a-",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"GlobPattern"},
|
||||
Classification: ErrGlobPattern,
|
||||
Message: getGlobPatternErrorString("[a-"),
|
||||
|
||||
@@ -5,38 +5,35 @@ package validation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
)
|
||||
|
||||
func Test_GitRefNameValidation(t *testing.T) {
|
||||
AddBindingRules()
|
||||
gitRefNameValidationTestCases := []validationTestCase{
|
||||
{
|
||||
description: "Reference name contains only characters",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "test",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name contains single slash",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "feature/test",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name has allowed special characters",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "debian/1%1.6.0-2",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Reference name contains backslash",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "feature\\test",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -45,11 +42,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name starts with dot",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: ".test",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -58,11 +55,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name ends with dot",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "test.",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -71,11 +68,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name starts with slash",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "/test",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -84,11 +81,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name ends with slash",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "test/",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -97,11 +94,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name ends with .lock",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "test.lock",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -110,11 +107,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name contains multiple consecutive dots",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "te..st",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -123,11 +120,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name contains multiple consecutive slashes",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "te//st",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -136,11 +133,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name is single @",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "@",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -149,11 +146,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name has @{",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "branch@{",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -162,11 +159,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character ~",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "~debian/1%1.6.0-2",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -175,11 +172,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character *",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "*debian/1%1.6.0-2",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -188,11 +185,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character ?",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "?debian/1%1.6.0-2",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -201,11 +198,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character ^",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "^debian/1%1.6.0-2",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -214,11 +211,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character :",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "debian:jessie",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -227,11 +224,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character (whitespace)",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "debian jessie",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
@@ -240,11 +237,11 @@ func Test_GitRefNameValidation(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "Reference name has unallowed special character [",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
BranchName: "debian[jessie",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"BranchName"},
|
||||
Classification: ErrGitRefName,
|
||||
Message: "GitRefName",
|
||||
|
||||
@@ -6,8 +6,6 @@ package validation
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
)
|
||||
|
||||
func getRegexPatternErrorString(pattern string) string {
|
||||
@@ -18,29 +16,27 @@ func getRegexPatternErrorString(pattern string) string {
|
||||
}
|
||||
|
||||
func Test_RegexPatternValidation(t *testing.T) {
|
||||
AddBindingRules()
|
||||
|
||||
regexValidationTestCases := []validationTestCase{
|
||||
{
|
||||
description: "Empty regex pattern",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
RegexPattern: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Valid regex",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
RegexPattern: `(\d{1,3})+`,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
description: "Invalid regex",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
RegexPattern: "[a-",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"RegexPattern"},
|
||||
Classification: ErrRegexPattern,
|
||||
Message: getRegexPatternErrorString("[a-"),
|
||||
|
||||
@@ -5,92 +5,88 @@ package validation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
)
|
||||
|
||||
func Test_ValidURLValidation(t *testing.T) {
|
||||
AddBindingRules()
|
||||
|
||||
urlValidationTestCases := []validationTestCase{
|
||||
{
|
||||
description: "Empty URL",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "URL without port",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "http://test.lan/",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "URL with port",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "http://test.lan:3000/",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "URL with IPv6 address without port",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "http://[::1]/",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "URL with IPv6 address with port",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "http://[::1]:3000/",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Invalid URL",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "http//test.lan/",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: binding.ERR_URL,
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Invalid schema",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "ftp://test.lan/",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: binding.ERR_URL,
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Invalid port",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "http://test.lan:3x4/",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: binding.ERR_URL,
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Invalid port with IPv6 address",
|
||||
data: TestForm{
|
||||
data: &TestForm{
|
||||
URL: "http://[::1]:3x4/",
|
||||
},
|
||||
expectedErrors: binding.Errors{
|
||||
binding.Error{
|
||||
expectedErrors: BindingErrors{
|
||||
BindingError{
|
||||
FieldNames: []string{"URL"},
|
||||
Classification: binding.ERR_URL,
|
||||
Classification: "UrlError",
|
||||
Message: "Url",
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user