Files

275 lines
6.6 KiB
Go
Raw Permalink Normal View History

2017-04-19 06:02:20 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
2017-04-19 06:02:20 +03:00
package validation
import (
"fmt"
"io"
2017-04-19 06:02:20 +03:00
"regexp"
"strings"
2023-02-08 07:44:42 +01:00
"code.gitea.io/gitea/modules/auth"
2022-09-04 11:47:56 +01:00
"code.gitea.io/gitea/modules/git"
2025-09-14 02:01:00 +08:00
"code.gitea.io/gitea/modules/glob"
"code.gitea.io/gitea/modules/json"
2024-11-27 20:50:27 -06:00
"code.gitea.io/gitea/modules/util"
2022-09-04 11:47:56 +01:00
2021-01-26 23:36:53 +08:00
"gitea.com/go-chi/binding"
2017-04-19 06:02:20 +03:00
)
const (
// ErrGitRefName is git reference name error
ErrGitRefName = "GitRefNameError"
2019-09-09 08:48:21 +03:00
// ErrGlobPattern is returned when glob pattern is invalid
ErrGlobPattern = "GlobPattern"
2021-06-25 16:28:55 +02:00
// ErrRegexPattern is returned when a regex pattern is invalid
ErrRegexPattern = "RegexPattern"
2022-11-04 17:04:08 +08:00
// ErrUsername is username error
ErrUsername = "UsernameError"
2023-02-08 07:44:42 +01:00
// ErrInvalidGroupTeamMap is returned when a group team mapping is invalid
ErrInvalidGroupTeamMap = "InvalidGroupTeamMap"
2026-03-22 16:49:45 +01:00
// ErrInvalidBadgeSlug is returned when a badge slug is invalid
ErrInvalidBadgeSlug = "InvalidBadgeSlug"
2017-04-19 06:02:20 +03:00
)
type jsonProvider struct{}
func (j jsonProvider) Marshal(v any) ([]byte, error) { return json.Marshal(v) }
func (j jsonProvider) Unmarshal(data []byte, v any) error { return json.Unmarshal(data, v) }
func (j jsonProvider) NewDecoder(reader io.Reader) binding.JSONDecoder {
return json.NewDecoder(reader)
}
func (j jsonProvider) NewEncoder(writer io.Writer) binding.JSONEncoder {
return json.NewEncoder(writer)
}
2017-04-19 06:02:20 +03:00
// AddBindingRules adds additional binding rules
func AddBindingRules() {
binding.JSONProvider = jsonProvider{}
2017-04-19 06:02:20 +03:00
addGitRefNameBindingRule()
2024-11-27 20:50:27 -06:00
addValidURLListBindingRule()
2017-04-19 06:02:20 +03:00
addValidURLBindingRule()
2021-06-26 00:38:27 +02:00
addValidSiteURLBindingRule()
2019-09-09 08:48:21 +03:00
addGlobPatternRule()
2021-06-25 16:28:55 +02:00
addRegexPatternRule()
addGlobOrRegexPatternRule()
2022-11-04 17:04:08 +08:00
addUsernamePatternRule()
2023-02-08 07:44:42 +01:00
addValidGroupTeamMapRule()
2026-03-22 16:49:45 +01:00
addSlugPatternRule()
2017-04-19 06:02:20 +03:00
}
func addGitRefNameBindingRule() {
// Git refname validation rule
binding.AddRule(&binding.Rule{
IsMatch: func(rule string) bool {
2024-11-27 20:50:27 -06:00
return rule == "GitRefName"
2017-04-19 06:02:20 +03:00
},
2023-07-04 20:36:08 +02:00
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
2017-04-19 06:02:20 +03:00
str := fmt.Sprintf("%v", val)
2022-09-04 11:47:56 +01:00
if !git.IsValidRefPattern(str) {
2017-04-19 06:02:20 +03:00
errs.Add([]string{name}, ErrGitRefName, "GitRefName")
return false, errs
}
return true, errs
},
})
}
2024-11-27 20:50:27 -06: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-19 06:02:20 +03:00
func addValidURLBindingRule() {
// URL validation rule
binding.AddRule(&binding.Rule{
IsMatch: func(rule string) bool {
2024-11-27 20:50:27 -06:00
return rule == "ValidUrl"
2017-04-19 06:02:20 +03:00
},
2023-07-04 20:36:08 +02:00
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
2017-04-19 06:02:20 +03:00
str := fmt.Sprintf("%v", val)
if len(str) != 0 && !IsValidURL(str) {
errs.Add([]string{name}, binding.ERR_URL, "Url")
return false, errs
2017-04-19 06:02:20 +03:00
}
return true, errs
},
})
}
2021-06-26 00:38:27 +02:00
func addValidSiteURLBindingRule() {
// URL validation rule
binding.AddRule(&binding.Rule{
IsMatch: func(rule string) bool {
2024-11-27 20:50:27 -06:00
return rule == "ValidSiteUrl"
2021-06-26 00:38:27 +02:00
},
2023-07-04 20:36:08 +02:00
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
2021-06-26 00:38:27 +02: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
},
})
}
2026-03-22 16:49:45 +01:00
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
},
})
}
2019-09-09 08:48:21 +03:00
func addGlobPatternRule() {
binding.AddRule(&binding.Rule{
IsMatch: func(rule string) bool {
return rule == "GlobPattern"
},
2021-06-25 16:28:55 +02:00
IsValid: globPatternValidator,
})
}
2023-07-04 20:36:08 +02:00
func globPatternValidator(errs binding.Errors, name string, val any) (bool, binding.Errors) {
2021-06-25 16:28:55 +02: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 20:36:08 +02:00
func regexPatternValidator(errs binding.Errors, name string, val any) (bool, binding.Errors) {
2021-06-25 16:28:55 +02: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 20:36:08 +02:00
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
2021-06-25 16:28:55 +02:00
str := strings.TrimSpace(fmt.Sprintf("%v", val))
2019-09-09 08:48:21 +03:00
2021-06-25 16:28:55 +02:00
if len(str) >= 2 && strings.HasPrefix(str, "/") && strings.HasSuffix(str, "/") {
return regexPatternValidator(errs, name, str[1:len(str)-1])
2019-09-09 08:48:21 +03:00
}
2021-06-25 16:28:55 +02:00
return globPatternValidator(errs, name, val)
2019-09-09 08:48:21 +03:00
},
})
}
2022-11-04 17:04:08 +08:00
func addUsernamePatternRule() {
binding.AddRule(&binding.Rule{
IsMatch: func(rule string) bool {
return rule == "Username"
},
2023-07-04 20:36:08 +02:00
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
2022-11-04 17:04:08 +08: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 07:44:42 +01:00
func addValidGroupTeamMapRule() {
binding.AddRule(&binding.Rule{
IsMatch: func(rule string) bool {
2024-11-27 20:50:27 -06:00
return rule == "ValidGroupTeamMap"
2023-02-08 07:44:42 +01:00
},
2023-07-04 20:36:08 +02:00
IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
2023-02-08 07:44:42 +01:00
_, err := auth.UnmarshalGroupTeamMapping(fmt.Sprintf("%v", val))
if err != nil {
errs.Add([]string{name}, ErrInvalidGroupTeamMap, err.Error())
return false, errs
}
return true, errs
},
})
}
2017-04-19 06:02:20 +03:00
func portOnly(hostport string) string {
2025-12-04 10:06:44 +01:00
_, after, ok := strings.Cut(hostport, ":")
if !ok {
2017-04-19 06:02:20 +03:00
return ""
}
2026-01-24 09:58:28 +01:00
if _, after2, ok2 := strings.Cut(hostport, "]:"); ok2 {
return after2
2017-04-19 06:02:20 +03:00
}
if strings.Contains(hostport, "]") {
return ""
}
2025-12-04 10:06:44 +01:00
return after
2017-04-19 06:02:20 +03:00
}
func validPort(p string) bool {
for _, r := range []byte(p) {
if r < '0' || r > '9' {
return false
}
}
return true
}