2017-04-18 23:02:20 -04:00
|
|
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
2022-11-27 13:20:29 -05:00
|
|
|
// SPDX-License-Identifier: MIT
|
2017-04-18 23:02:20 -04:00
|
|
|
|
|
|
|
package validation
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
|
2023-02-08 01:44:42 -05:00
|
|
|
"code.gitea.io/gitea/modules/auth"
|
2022-09-04 06:47:56 -04:00
|
|
|
"code.gitea.io/gitea/modules/git"
|
2024-11-27 21:50:27 -05:00
|
|
|
"code.gitea.io/gitea/modules/util"
|
2022-09-04 06:47:56 -04:00
|
|
|
|
2024-11-05 15:40:44 -05:00
|
|
|
"code.forgejo.org/go-chi/binding"
|
2019-09-09 01:48:21 -04:00
|
|
|
"github.com/gobwas/glob"
|
2017-04-18 23:02:20 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
// ErrGitRefName is git reference name error
|
|
|
|
ErrGitRefName = "GitRefNameError"
|
2019-09-09 01:48:21 -04:00
|
|
|
// ErrGlobPattern is returned when glob pattern is invalid
|
|
|
|
ErrGlobPattern = "GlobPattern"
|
2021-06-25 10:28:55 -04:00
|
|
|
// ErrRegexPattern is returned when a regex pattern is invalid
|
|
|
|
ErrRegexPattern = "RegexPattern"
|
2022-11-04 05:04:08 -04:00
|
|
|
// ErrUsername is username error
|
|
|
|
ErrUsername = "UsernameError"
|
2023-02-08 01:44:42 -05:00
|
|
|
// ErrInvalidGroupTeamMap is returned when a group team mapping is invalid
|
|
|
|
ErrInvalidGroupTeamMap = "InvalidGroupTeamMap"
|
2024-08-28 18:56:35 -04:00
|
|
|
// ErrEmail is returned when an email address is invalid
|
|
|
|
ErrEmail = "Email"
|
2017-04-18 23:02:20 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// AddBindingRules adds additional binding rules
|
|
|
|
func AddBindingRules() {
|
|
|
|
addGitRefNameBindingRule()
|
2024-11-27 21:50:27 -05:00
|
|
|
addValidURLListBindingRule()
|
2017-04-18 23:02:20 -04:00
|
|
|
addValidURLBindingRule()
|
2021-06-25 18:38:27 -04:00
|
|
|
addValidSiteURLBindingRule()
|
2019-09-09 01:48:21 -04:00
|
|
|
addGlobPatternRule()
|
2021-06-25 10:28:55 -04:00
|
|
|
addRegexPatternRule()
|
|
|
|
addGlobOrRegexPatternRule()
|
2022-11-04 05:04:08 -04:00
|
|
|
addUsernamePatternRule()
|
2023-02-08 01:44:42 -05:00
|
|
|
addValidGroupTeamMapRule()
|
2024-08-28 18:56:35 -04:00
|
|
|
addEmailBindingRules()
|
2017-04-18 23:02:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func addGitRefNameBindingRule() {
|
|
|
|
// Git refname validation rule
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
2024-11-27 21:50:27 -05:00
|
|
|
return rule == "GitRefName"
|
2017-04-18 23:02:20 -04:00
|
|
|
},
|
2023-07-04 14:36:08 -04:00
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
2017-04-18 23:02:20 -04:00
|
|
|
str := fmt.Sprintf("%v", val)
|
|
|
|
|
2022-09-04 06:47:56 -04:00
|
|
|
if !git.IsValidRefPattern(str) {
|
2017-04-18 23:02:20 -04:00
|
|
|
errs.Add([]string{name}, ErrGitRefName, "GitRefName")
|
|
|
|
return false, errs
|
|
|
|
}
|
|
|
|
return true, errs
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-11-27 21:50:27 -05:00
|
|
|
func addValidURLListBindingRule() {
|
|
|
|
// URL validation rule
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
|
|
|
return rule == "ValidUrlList"
|
|
|
|
},
|
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
|
|
|
str := fmt.Sprintf("%v", val)
|
|
|
|
if len(str) == 0 {
|
|
|
|
errs.Add([]string{name}, binding.ERR_URL, "Url")
|
|
|
|
return false, errs
|
|
|
|
}
|
|
|
|
|
|
|
|
ok := true
|
|
|
|
urls := util.SplitTrimSpace(str, "\n")
|
|
|
|
for _, u := range urls {
|
|
|
|
if !IsValidURL(u) {
|
|
|
|
ok = false
|
|
|
|
errs.Add([]string{name}, binding.ERR_URL, u)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ok, errs
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-04-18 23:02:20 -04:00
|
|
|
func addValidURLBindingRule() {
|
|
|
|
// URL validation rule
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
2024-11-27 21:50:27 -05:00
|
|
|
return rule == "ValidUrl"
|
2017-04-18 23:02:20 -04:00
|
|
|
},
|
2023-07-04 14:36:08 -04:00
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
2017-04-18 23:02:20 -04:00
|
|
|
str := fmt.Sprintf("%v", val)
|
2018-08-15 02:29:37 -04:00
|
|
|
if len(str) != 0 && !IsValidURL(str) {
|
|
|
|
errs.Add([]string{name}, binding.ERR_URL, "Url")
|
|
|
|
return false, errs
|
2017-04-18 23:02:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return true, errs
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-06-25 18:38:27 -04:00
|
|
|
func addValidSiteURLBindingRule() {
|
|
|
|
// URL validation rule
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
2024-11-27 21:50:27 -05:00
|
|
|
return rule == "ValidSiteUrl"
|
2021-06-25 18:38:27 -04:00
|
|
|
},
|
2023-07-04 14:36:08 -04:00
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
2021-06-25 18:38:27 -04:00
|
|
|
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
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-09-09 01:48:21 -04:00
|
|
|
func addGlobPatternRule() {
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
|
|
|
return rule == "GlobPattern"
|
|
|
|
},
|
2021-06-25 10:28:55 -04:00
|
|
|
IsValid: globPatternValidator,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-07-04 14:36:08 -04:00
|
|
|
func globPatternValidator(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
2021-06-25 10:28:55 -04:00
|
|
|
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 addRegexPatternRule() {
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
|
|
|
return rule == "RegexPattern"
|
|
|
|
},
|
|
|
|
IsValid: regexPatternValidator,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-07-04 14:36:08 -04:00
|
|
|
func regexPatternValidator(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
2021-06-25 10:28:55 -04:00
|
|
|
str := fmt.Sprintf("%v", val)
|
|
|
|
|
|
|
|
if _, err := regexp.Compile(str); err != nil {
|
|
|
|
errs.Add([]string{name}, ErrRegexPattern, err.Error())
|
|
|
|
return false, errs
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, errs
|
|
|
|
}
|
|
|
|
|
|
|
|
func addGlobOrRegexPatternRule() {
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
|
|
|
return rule == "GlobOrRegexPattern"
|
|
|
|
},
|
2023-07-04 14:36:08 -04:00
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
2021-06-25 10:28:55 -04:00
|
|
|
str := strings.TrimSpace(fmt.Sprintf("%v", val))
|
2019-09-09 01:48:21 -04:00
|
|
|
|
2021-06-25 10:28:55 -04:00
|
|
|
if len(str) >= 2 && strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
|
|
|
|
return regexPatternValidator(errs, name, str[1:len(str)-1])
|
2019-09-09 01:48:21 -04:00
|
|
|
}
|
2021-06-25 10:28:55 -04:00
|
|
|
return globPatternValidator(errs, name, val)
|
2019-09-09 01:48:21 -04:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-04 05:04:08 -04:00
|
|
|
func addUsernamePatternRule() {
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
|
|
|
return rule == "Username"
|
|
|
|
},
|
2023-07-04 14:36:08 -04:00
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
2022-11-04 05:04:08 -04:00
|
|
|
str := fmt.Sprintf("%v", val)
|
|
|
|
if !IsValidUsername(str) {
|
|
|
|
errs.Add([]string{name}, ErrUsername, "invalid username")
|
|
|
|
return false, errs
|
|
|
|
}
|
|
|
|
return true, errs
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-02-08 01:44:42 -05:00
|
|
|
func addValidGroupTeamMapRule() {
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
2024-11-27 21:50:27 -05:00
|
|
|
return rule == "ValidGroupTeamMap"
|
2023-02-08 01:44:42 -05:00
|
|
|
},
|
2023-07-04 14:36:08 -04:00
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
2023-02-08 01:44:42 -05:00
|
|
|
_, err := auth.UnmarshalGroupTeamMapping(fmt.Sprintf("%v", val))
|
|
|
|
if err != nil {
|
|
|
|
errs.Add([]string{name}, ErrInvalidGroupTeamMap, err.Error())
|
|
|
|
return false, errs
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, errs
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-08-28 18:56:35 -04:00
|
|
|
func addEmailBindingRules() {
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
|
|
|
return strings.HasPrefix(rule, "EmailWithAllowedDomain")
|
|
|
|
},
|
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
|
|
|
if err := ValidateEmail(fmt.Sprintf("%v", val)); err != nil {
|
|
|
|
errs.Add([]string{name}, ErrEmail, err.Error())
|
|
|
|
return false, errs
|
|
|
|
}
|
|
|
|
return true, errs
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
binding.AddRule(&binding.Rule{
|
|
|
|
IsMatch: func(rule string) bool {
|
|
|
|
return strings.HasPrefix(rule, "EmailForAdmin")
|
|
|
|
},
|
|
|
|
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
|
|
|
|
if err := ValidateEmailForAdmin(fmt.Sprintf("%v", val)); err != nil {
|
|
|
|
errs.Add([]string{name}, ErrEmail, err.Error())
|
|
|
|
return false, errs
|
|
|
|
}
|
|
|
|
return true, errs
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-04-18 23:02:20 -04:00
|
|
|
func portOnly(hostport string) string {
|
|
|
|
colon := strings.IndexByte(hostport, ':')
|
|
|
|
if colon == -1 {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
if i := strings.Index(hostport, "]:"); i != -1 {
|
|
|
|
return hostport[i+len("]:"):]
|
|
|
|
}
|
|
|
|
if strings.Contains(hostport, "]") {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return hostport[colon+len(":"):]
|
|
|
|
}
|
|
|
|
|
|
|
|
func validPort(p string) bool {
|
|
|
|
for _, r := range []byte(p) {
|
|
|
|
if r < '0' || r > '9' {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|