summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorWGH <wgh@torlan.ru>2019-09-09 08:48:21 +0300
committerLauris BH <lauris.buksis@zzdats.lv>2019-09-09 08:48:21 +0300
commit6ddd3b0b470d16dfe62caf5fff21011cfff44a76 (patch)
tree05d4c7fedf8af21b489003890be000f839f69a51 /modules
parent0118b6aaf8ada3edd67cb975c776f6f124178ad2 (diff)
downloadgitea-6ddd3b0b470d16dfe62caf5fff21011cfff44a76.tar.gz
gitea-6ddd3b0b470d16dfe62caf5fff21011cfff44a76.zip
Implement webhook branch filter (#7791)
* Fix validate() function to handle errors in embedded anon structs * Implement webhook branch filter See #2025, #3998.
Diffstat (limited to 'modules')
-rw-r--r--modules/auth/auth.go17
-rw-r--r--modules/auth/repo_form.go1
-rw-r--r--modules/structs/hook.go12
-rw-r--r--modules/validation/binding.go25
-rw-r--r--modules/validation/binding_test.go5
-rw-r--r--modules/validation/glob_pattern_test.go62
6 files changed, 106 insertions, 16 deletions
diff --git a/modules/auth/auth.go b/modules/auth/auth.go
index 68553941ec..624bb15cbf 100644
--- a/modules/auth/auth.go
+++ b/modules/auth/auth.go
@@ -310,6 +310,10 @@ func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaro
}
data["HasError"] = true
+ // If the field with name errs[0].FieldNames[0] is not found in form
+ // somehow, some code later on will panic on Data["ErrorMsg"].(string).
+ // So initialize it to some default.
+ data["ErrorMsg"] = l.Tr("form.unknown_error")
AssignForm(f, data)
typ := reflect.TypeOf(f)
@@ -320,16 +324,9 @@ func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaro
val = val.Elem()
}
- for i := 0; i < typ.NumField(); i++ {
- field := typ.Field(i)
-
+ if field, ok := typ.FieldByName(errs[0].FieldNames[0]); ok {
fieldName := field.Tag.Get("form")
- // Allow ignored fields in the struct
- if fieldName == "-" {
- continue
- }
-
- if errs[0].FieldNames[0] == field.Name {
+ if fieldName != "-" {
data["Err_"+field.Name] = true
trName := field.Tag.Get("locale")
@@ -360,6 +357,8 @@ func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaro
data["ErrorMsg"] = trName + l.Tr("form.url_error")
case binding.ERR_INCLUDE:
data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field))
+ case validation.ErrGlobPattern:
+ data["ErrorMsg"] = trName + l.Tr("form.glob_pattern_error", errs[0].Message)
default:
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
}
diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go
index 418f6d3874..56ae77a7f7 100644
--- a/modules/auth/repo_form.go
+++ b/modules/auth/repo_form.go
@@ -185,6 +185,7 @@ type WebhookForm struct {
PullRequest bool
Repository bool
Active bool
+ BranchFilter string `binding:"GlobPattern"`
}
// PushOnly if the hook will be triggered when push
diff --git a/modules/structs/hook.go b/modules/structs/hook.go
index 8dae578ec6..9a25219e36 100644
--- a/modules/structs/hook.go
+++ b/modules/structs/hook.go
@@ -40,17 +40,19 @@ type CreateHookOption struct {
// enum: gitea,gogs,slack,discord
Type string `json:"type" binding:"Required"`
// required: true
- Config map[string]string `json:"config" binding:"Required"`
- Events []string `json:"events"`
+ Config map[string]string `json:"config" binding:"Required"`
+ Events []string `json:"events"`
+ BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
// default: false
Active bool `json:"active"`
}
// EditHookOption options when modify one hook
type EditHookOption struct {
- Config map[string]string `json:"config"`
- Events []string `json:"events"`
- Active *bool `json:"active"`
+ Config map[string]string `json:"config"`
+ Events []string `json:"events"`
+ BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
+ Active *bool `json:"active"`
}
// Payloader payload is some part of one hook
diff --git a/modules/validation/binding.go b/modules/validation/binding.go
index fc420e62fb..6ed75b50fb 100644
--- a/modules/validation/binding.go
+++ b/modules/validation/binding.go
@@ -10,11 +10,15 @@ import (
"strings"
"gitea.com/macaron/binding"
+ "github.com/gobwas/glob"
)
const (
// ErrGitRefName is git reference name error
ErrGitRefName = "GitRefNameError"
+
+ // ErrGlobPattern is returned when glob pattern is invalid
+ ErrGlobPattern = "GlobPattern"
)
var (
@@ -28,6 +32,7 @@ var (
func AddBindingRules() {
addGitRefNameBindingRule()
addValidURLBindingRule()
+ addGlobPatternRule()
}
func addGitRefNameBindingRule() {
@@ -82,6 +87,26 @@ func addValidURLBindingRule() {
})
}
+func addGlobPatternRule() {
+ binding.AddRule(&binding.Rule{
+ IsMatch: func(rule string) bool {
+ return rule == "GlobPattern"
+ },
+ IsValid: func(errs binding.Errors, name string, val interface{}) (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
+ }
+ }
+
+ return true, errs
+ },
+ })
+}
+
func portOnly(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
diff --git a/modules/validation/binding_test.go b/modules/validation/binding_test.go
index 5ac88c9317..9fc9a6db08 100644
--- a/modules/validation/binding_test.go
+++ b/modules/validation/binding_test.go
@@ -26,8 +26,9 @@ type (
}
TestForm struct {
- BranchName string `form:"BranchName" binding:"GitRefName"`
- URL string `form:"ValidUrl" binding:"ValidUrl"`
+ BranchName string `form:"BranchName" binding:"GitRefName"`
+ URL string `form:"ValidUrl" binding:"ValidUrl"`
+ GlobPattern string `form:"GlobPattern" binding:"GlobPattern"`
}
)
diff --git a/modules/validation/glob_pattern_test.go b/modules/validation/glob_pattern_test.go
new file mode 100644
index 0000000000..26775167b4
--- /dev/null
+++ b/modules/validation/glob_pattern_test.go
@@ -0,0 +1,62 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package validation
+
+import (
+ "testing"
+
+ "gitea.com/macaron/binding"
+ "github.com/gobwas/glob"
+)
+
+func getGlobPatternErrorString(pattern string) string {
+ // It would be unwise to rely on that glob
+ // compilation errors don't ever change.
+ if _, err := glob.Compile(pattern); err != nil {
+ return err.Error()
+ }
+ return ""
+}
+
+var globValidationTestCases = []validationTestCase{
+ {
+ description: "Empty glob pattern",
+ data: TestForm{
+ GlobPattern: "",
+ },
+ expectedErrors: binding.Errors{},
+ },
+ {
+ description: "Valid glob",
+ data: TestForm{
+ GlobPattern: "{master,release*}",
+ },
+ expectedErrors: binding.Errors{},
+ },
+
+ {
+ description: "Invalid glob",
+ data: TestForm{
+ GlobPattern: "[a-",
+ },
+ expectedErrors: binding.Errors{
+ binding.Error{
+ FieldNames: []string{"GlobPattern"},
+ Classification: ErrGlobPattern,
+ Message: getGlobPatternErrorString("[a-"),
+ },
+ },
+ },
+}
+
+func Test_GlobPatternValidation(t *testing.T) {
+ AddBindingRules()
+
+ for _, testCase := range globValidationTestCases {
+ t.Run(testCase.description, func(t *testing.T) {
+ performValidationTest(t, testCase)
+ })
+ }
+}