mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-27 00:31:17 +00:00
Fix #34349 By the way, remove `(ctx *APIContext) HasAPIError() ` and `(ctx *APIContext) GetErrMsg()` because they do nothing, the error handling has been done in API's middeware The existing OAuth2 tests were not quite right, refactored them together
246 lines
5.9 KiB
Go
246 lines
5.9 KiB
Go
// Copyright 2017 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package validation
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"code.gitea.io/gitea/modules/auth"
|
|
"code.gitea.io/gitea/modules/git"
|
|
"code.gitea.io/gitea/modules/glob"
|
|
"code.gitea.io/gitea/modules/json"
|
|
|
|
"gitea.com/go-chi/binding"
|
|
)
|
|
|
|
const (
|
|
// ErrGitRefName is git reference name error
|
|
ErrGitRefName = "GitRefNameError"
|
|
// ErrGlobPattern is returned when glob pattern is invalid
|
|
ErrGlobPattern = "GlobPattern"
|
|
// ErrRegexPattern is returned when a regex pattern is invalid
|
|
ErrRegexPattern = "RegexPattern"
|
|
// ErrUsername is username error
|
|
ErrUsername = "UsernameError"
|
|
// ErrInvalidGroupTeamMap is returned when a group team mapping is invalid
|
|
ErrInvalidGroupTeamMap = "InvalidGroupTeamMap"
|
|
// ErrInvalidBadgeSlug is returned when a badge slug is invalid
|
|
ErrInvalidBadgeSlug = "InvalidBadgeSlug"
|
|
)
|
|
|
|
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)
|
|
}
|
|
|
|
// AddBindingRules adds additional binding rules
|
|
func AddBindingRules() {
|
|
binding.JSONProvider = jsonProvider{}
|
|
addGitRefNameBindingRule()
|
|
addValidURLBindingRule()
|
|
addValidSiteURLBindingRule()
|
|
addGlobPatternRule()
|
|
addRegexPatternRule()
|
|
addGlobOrRegexPatternRule()
|
|
addUsernamePatternRule()
|
|
addValidGroupTeamMapRule()
|
|
addSlugPatternRule()
|
|
}
|
|
|
|
func addGitRefNameBindingRule() {
|
|
// Git refname 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
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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)
|
|
},
|
|
})
|
|
}
|
|
|
|
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
|
|
},
|
|
})
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
return true, errs
|
|
},
|
|
})
|
|
}
|
|
|
|
func portOnly(hostport string) string {
|
|
_, after, ok := strings.Cut(hostport, ":")
|
|
if !ok {
|
|
return ""
|
|
}
|
|
if _, after2, ok2 := strings.Cut(hostport, "]:"); ok2 {
|
|
return after2
|
|
}
|
|
if strings.Contains(hostport, "]") {
|
|
return ""
|
|
}
|
|
return after
|
|
}
|
|
|
|
func validPort(p string) bool {
|
|
for _, r := range []byte(p) {
|
|
if r < '0' || r > '9' {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|