mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-09 04:30:16 +09:00
Backport #39661 1. fix #39660: relax email validation 2. fix #39658: use "int64" instead of time.Duration (for JSON v2) Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -151,16 +151,28 @@ func TestListEmails(t *testing.T) {
|
|||||||
|
|
||||||
func TestEmailAddressValidate(t *testing.T) {
|
func TestEmailAddressValidate(t *testing.T) {
|
||||||
cases := map[string]bool{
|
cases := map[string]bool{
|
||||||
"": false,
|
"": false,
|
||||||
"root@localhost": true,
|
"@a": false,
|
||||||
"user@[192.168.1.2]": true,
|
|
||||||
"@a": false,
|
// "_" shouldn't appear in domain but can appear in hostname, since we can't stop site admins from doing so, just accept it
|
||||||
"abc@gmail.com": true,
|
"root@local_host": true,
|
||||||
"abc@gmail.com\n": false,
|
"root@localhost": true,
|
||||||
|
"root@LOCALHOST": true,
|
||||||
|
|
||||||
|
"user@[192.168.1.2]": true,
|
||||||
|
"user@[IPv6:FFff::1]": true,
|
||||||
|
|
||||||
|
"abc@gmail.com": true,
|
||||||
|
"abc@gmail.com.": false,
|
||||||
|
"abc@gmail.com-": false,
|
||||||
|
"abc@gmail.com\n": false,
|
||||||
|
"abc@gmail..com": false,
|
||||||
|
"abc@gmail com": false,
|
||||||
|
"abc@gmail*com": false,
|
||||||
|
|
||||||
"Foo <foo@bar.com>": false,
|
"Foo <foo@bar.com>": false,
|
||||||
"abc@gmail.com (x)": false,
|
"abc@gmail.com (x)": false,
|
||||||
"jürgen@example.com": false,
|
"jürgen@example.com": false, // utf8 address is not supported yet
|
||||||
"a@foo_bar.com": false,
|
|
||||||
}
|
}
|
||||||
for tc, isValid := range cases {
|
for tc, isValid := range cases {
|
||||||
t.Run(tc, func(t *testing.T) {
|
t.Run(tc, func(t *testing.T) {
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ func ReloadTemplates(ctx context.Context) ResponseExtra {
|
|||||||
|
|
||||||
// FlushOptions represents the options for the flush call
|
// FlushOptions represents the options for the flush call
|
||||||
type FlushOptions struct {
|
type FlushOptions struct {
|
||||||
Timeout time.Duration
|
Timeout int64
|
||||||
NonBlocking bool
|
NonBlocking bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushQueues calls the internal flush-queues function
|
// FlushQueues calls the internal flush-queues function
|
||||||
func FlushQueues(ctx context.Context, timeout time.Duration, nonBlocking bool) ResponseExtra {
|
func FlushQueues(ctx context.Context, timeout time.Duration, nonBlocking bool) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + "api/internal/manager/flush-queues"
|
reqURL := setting.LocalURL + "api/internal/manager/flush-queues"
|
||||||
req := newInternalRequestAPI(ctx, reqURL, "POST", FlushOptions{Timeout: timeout, NonBlocking: nonBlocking})
|
req := newInternalRequestAPI(ctx, reqURL, "POST", FlushOptions{Timeout: int64(timeout), NonBlocking: nonBlocking})
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
req.SetReadWriteTimeout(timeout + 10*time.Second)
|
req.SetReadWriteTimeout(timeout + 10*time.Second)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import (
|
|||||||
|
|
||||||
"gitea.dev/modules/glob"
|
"gitea.dev/modules/glob"
|
||||||
"gitea.dev/modules/setting"
|
"gitea.dev/modules/setting"
|
||||||
|
|
||||||
"golang.org/x/net/idna"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type globalVarsStruct struct {
|
type globalVarsStruct struct {
|
||||||
@@ -24,6 +22,8 @@ type globalVarsStruct struct {
|
|||||||
invalidUsernamePattern *regexp.Regexp
|
invalidUsernamePattern *regexp.Regexp
|
||||||
validBadgeSlugPattern *regexp.Regexp
|
validBadgeSlugPattern *regexp.Regexp
|
||||||
invalidBadgeSlugPattern *regexp.Regexp
|
invalidBadgeSlugPattern *regexp.Regexp
|
||||||
|
validEmailHostName *regexp.Regexp
|
||||||
|
validEmailHostIP *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
var globalVars = sync.OnceValue(func() *globalVarsStruct {
|
var globalVars = sync.OnceValue(func() *globalVarsStruct {
|
||||||
@@ -33,6 +33,8 @@ var globalVars = sync.OnceValue(func() *globalVarsStruct {
|
|||||||
invalidUsernamePattern: regexp.MustCompile(`[-._]{2,}|[-._]$`), // No consecutive or trailing non-alphanumeric chars
|
invalidUsernamePattern: regexp.MustCompile(`[-._]{2,}|[-._]$`), // No consecutive or trailing non-alphanumeric chars
|
||||||
validBadgeSlugPattern: regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]*$`),
|
validBadgeSlugPattern: regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]*$`),
|
||||||
invalidBadgeSlugPattern: regexp.MustCompile(`[-._]{2,}|[-._]$`),
|
invalidBadgeSlugPattern: regexp.MustCompile(`[-._]{2,}|[-._]$`),
|
||||||
|
validEmailHostName: regexp.MustCompile(`^[a-zA-Z0-9][-.\w]*$`),
|
||||||
|
validEmailHostIP: regexp.MustCompile(`(?i)^\[([0-9.]+|ipv6:[0-9a-f:.]+)\]$`),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -124,10 +126,12 @@ func IsEmailAddressValid(email string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_, domain, _ := strings.Cut(email, "@")
|
_, domain, _ := strings.Cut(email, "@")
|
||||||
if strings.HasPrefix(domain, "[") {
|
if !globalVars().validEmailHostName.MatchString(domain) && !globalVars().validEmailHostIP.MatchString(domain) {
|
||||||
// address like "foo@[192.168.1.2]"
|
return false
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
_, err = idna.Registration.ToASCII(domain)
|
if strings.HasPrefix(domain, "-") || strings.HasSuffix(domain, "-") ||
|
||||||
return err == nil
|
strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package private
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gitea.dev/models/db"
|
"gitea.dev/models/db"
|
||||||
"gitea.dev/modules/graceful"
|
"gitea.dev/modules/graceful"
|
||||||
@@ -34,7 +35,7 @@ func FlushQueues(ctx *context.PrivateContext) {
|
|||||||
// Save the hammer ctx here - as a new one is created each time you call this.
|
// Save the hammer ctx here - as a new one is created each time you call this.
|
||||||
baseCtx := graceful.GetManager().HammerContext()
|
baseCtx := graceful.GetManager().HammerContext()
|
||||||
go func() {
|
go func() {
|
||||||
err := queue.GetManager().FlushAll(baseCtx, opts.Timeout)
|
err := queue.GetManager().FlushAll(baseCtx, time.Duration(opts.Timeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Flushing request timed-out with error: %v", err)
|
log.Error("Flushing request timed-out with error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ func FlushQueues(ctx *context.PrivateContext) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := queue.GetManager().FlushAll(ctx, opts.Timeout)
|
err := queue.GetManager().FlushAll(ctx, time.Duration(opts.Timeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.PrivateUserErrorf(http.StatusRequestTimeout, "%v", err)
|
ctx.PrivateUserErrorf(http.StatusRequestTimeout, "%v", err)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user