Skip to content

Commit b9fa1ac

Browse files
authored
Merge branch 'main' into fix-index-names-when-recreating-tables-mysql
2 parents e51fce5 + 4aa3cac commit b9fa1ac

32 files changed

+1111
-527
lines changed

custom/conf/app.example.ini

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,10 @@ INTERNAL_TOKEN=
378378
;;
379379
;; Validate against https://haveibeenpwned.com/Passwords to see if a password has been exposed
380380
;PASSWORD_CHECK_PWN = false
381+
;;
382+
;; Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations.
383+
;; This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
384+
;SUCCESSFUL_TOKENS_CACHE_SIZE = 20
381385

382386
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
383387
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2123,3 +2127,11 @@ PATH =
21232127
;;
21242128
;; Minio enabled ssl only available when STORAGE_TYPE is `minio`
21252129
;MINIO_USE_SSL = false
2130+
2131+
;[proxy]
2132+
;; Enable the proxy, all requests to external via HTTP will be affected
2133+
;PROXY_ENABLED = false
2134+
;; Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy/no_proxy
2135+
;PROXY_URL =
2136+
;; Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts.
2137+
;PROXY_HOSTS =

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ relation to port exhaustion.
441441
- spec - use one or more special characters as ``!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~``
442442
- off - do not check password complexity
443443
- `PASSWORD_CHECK_PWN`: **false**: Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed.
444+
- `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
444445

445446
## OpenID (`openid`)
446447

@@ -548,8 +549,8 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
548549
- `DELIVER_TIMEOUT`: **5**: Delivery timeout (sec) for shooting webhooks.
549550
- `SKIP_TLS_VERIFY`: **false**: Allow insecure certification.
550551
- `PAGING_NUM`: **10**: Number of webhook history events that are shown in one page.
551-
- `PROXY_URL`: ****: Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy
552-
- `PROXY_HOSTS`: ****: Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts.
552+
- `PROXY_URL`: **\<empty\>**: Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy. If not given, will use global proxy setting.
553+
- `PROXY_HOSTS`: **\<empty\>`**: Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts. If not given, will use global proxy setting.
553554

554555
## Mailer (`mailer`)
555556

@@ -949,6 +950,7 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
949950
- `ALLOWED_DOMAINS`: **\<empty\>**: Domains allowlist for migrating repositories, default is blank. It means everything will be allowed. Multiple domains could be separated by commas.
950951
- `BLOCKED_DOMAINS`: **\<empty\>**: Domains blocklist for migrating repositories, default is blank. Multiple domains could be separated by commas. When `ALLOWED_DOMAINS` is not blank, this option will be ignored.
951952
- `ALLOW_LOCALNETWORKS`: **false**: Allow private addresses defined by RFC 1918, RFC 1122, RFC 4632 and RFC 4291
953+
- `SKIP_TLS_VERIFY`: **false**: Allow skip tls verify
952954

953955
## Mirror (`mirror`)
954956

@@ -1022,6 +1024,19 @@ is `data/repo-archive` and the default of `MINIO_BASE_PATH` is `repo-archive/`.
10221024
- `MINIO_BASE_PATH`: **repo-archive/**: Minio base path on the bucket only available when `STORAGE_TYPE` is `minio`
10231025
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
10241026

1027+
## Proxy (`proxy`)
1028+
1029+
- `PROXY_ENABLED`: **false**: Enable the proxy if true, all requests to external via HTTP will be affected, if false, no proxy will be used even environment http_proxy/https_proxy
1030+
- `PROXY_URL`: **\<empty\>**: Proxy server URL, support http://, https//, socks://, blank will follow environment http_proxy/https_proxy
1031+
- `PROXY_HOSTS`: **\<empty\>**: Comma separated list of host names requiring proxy. Glob patterns (*) are accepted; use ** to match all hosts.
1032+
1033+
i.e.
1034+
```ini
1035+
PROXY_ENABLED = true
1036+
PROXY_URL = socks://127.0.0.1:1080
1037+
PROXY_HOSTS = *.github.com
1038+
```
1039+
10251040
## Other (`other`)
10261041

10271042
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.

docs/content/doc/advanced/config-cheat-sheet.zh-cn.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ IS_INPUT_FILE = false
332332
- `ALLOWED_DOMAINS`: **\<empty\>**: 迁移仓库的域名白名单,默认为空,表示允许从任意域名迁移仓库,多个域名用逗号分隔。
333333
- `BLOCKED_DOMAINS`: **\<empty\>**: 迁移仓库的域名黑名单,默认为空,多个域名用逗号分隔。如果 `ALLOWED_DOMAINS` 不为空,此选项将会被忽略。
334334
- `ALLOW_LOCALNETWORKS`: **false**: Allow private addresses defined by RFC 1918
335+
- `SKIP_TLS_VERIFY`: **false**: 允许忽略 TLS 认证
335336

336337
## LFS (`lfs`)
337338

@@ -397,6 +398,19 @@ Repository archive 的存储配置。 如果 `STORAGE_TYPE` 为空,则此配
397398
- `MINIO_BASE_PATH`: **repo-archive/**: Minio base path ,仅当 `STORAGE_TYPE``minio` 时有效。
398399
- `MINIO_USE_SSL`: **false**: Minio 是否启用 ssl ,仅当 `STORAGE_TYPE``minio` 时有效。
399400

401+
## Proxy (`proxy`)
402+
403+
- `PROXY_ENABLED`: **false**: 是否启用全局代理。如果为否,则不使用代理,环境变量中的代理也不使用
404+
- `PROXY_URL`: **\<empty\>**: 代理服务器地址,支持 http://, https//, socks://,为空则不启用代理而使用环境变量中的 http_proxy/https_proxy
405+
- `PROXY_HOSTS`: **\<empty\>**: 逗号分隔的多个需要代理的网址,支持 * 号匹配符号, ** 表示匹配所有网站
406+
407+
i.e.
408+
```ini
409+
PROXY_ENABLED = true
410+
PROXY_URL = socks://127.0.0.1:1080
411+
PROXY_HOSTS = *.github.com
412+
```
413+
400414
## Other (`other`)
401415

402416
- `SHOW_FOOTER_BRANDING`: 为真则在页面底部显示Gitea的字样。

models/models.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717

1818
// Needed for the MySQL driver
1919
_ "github.com/go-sql-driver/mysql"
20+
lru "github.com/hashicorp/golang-lru"
2021
"xorm.io/xorm"
2122
"xorm.io/xorm/names"
2223
"xorm.io/xorm/schemas"
@@ -234,6 +235,15 @@ func NewEngine(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err e
234235
return fmt.Errorf("sync database struct error: %v", err)
235236
}
236237

238+
if setting.SuccessfulTokensCacheSize > 0 {
239+
successfulAccessTokenCache, err = lru.New(setting.SuccessfulTokensCacheSize)
240+
if err != nil {
241+
return fmt.Errorf("unable to allocate AccessToken cache: %v", err)
242+
}
243+
} else {
244+
successfulAccessTokenCache = nil
245+
}
246+
237247
return nil
238248
}
239249

models/token.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ import (
1414
"code.gitea.io/gitea/modules/util"
1515

1616
gouuid "github.com/google/uuid"
17+
lru "github.com/hashicorp/golang-lru"
1718
)
1819

20+
var successfulAccessTokenCache *lru.Cache
21+
1922
// AccessToken represents a personal access token.
2023
type AccessToken struct {
2124
ID int64 `xorm:"pk autoincr"`
@@ -52,6 +55,21 @@ func NewAccessToken(t *AccessToken) error {
5255
return err
5356
}
5457

58+
func getAccessTokenIDFromCache(token string) int64 {
59+
if successfulAccessTokenCache == nil {
60+
return 0
61+
}
62+
tInterface, ok := successfulAccessTokenCache.Get(token)
63+
if !ok {
64+
return 0
65+
}
66+
t, ok := tInterface.(int64)
67+
if !ok {
68+
return 0
69+
}
70+
return t
71+
}
72+
5573
// GetAccessTokenBySHA returns access token by given token value
5674
func GetAccessTokenBySHA(token string) (*AccessToken, error) {
5775
if token == "" {
@@ -66,17 +84,38 @@ func GetAccessTokenBySHA(token string) (*AccessToken, error) {
6684
return nil, ErrAccessTokenNotExist{token}
6785
}
6886
}
69-
var tokens []AccessToken
87+
7088
lastEight := token[len(token)-8:]
89+
90+
if id := getAccessTokenIDFromCache(token); id > 0 {
91+
token := &AccessToken{
92+
TokenLastEight: lastEight,
93+
}
94+
// Re-get the token from the db in case it has been deleted in the intervening period
95+
has, err := x.ID(id).Get(token)
96+
if err != nil {
97+
return nil, err
98+
}
99+
if has {
100+
return token, nil
101+
}
102+
successfulAccessTokenCache.Remove(token)
103+
}
104+
105+
var tokens []AccessToken
71106
err := x.Table(&AccessToken{}).Where("token_last_eight = ?", lastEight).Find(&tokens)
72107
if err != nil {
73108
return nil, err
74109
} else if len(tokens) == 0 {
75110
return nil, ErrAccessTokenNotExist{token}
76111
}
112+
77113
for _, t := range tokens {
78114
tempHash := hashToken(token, t.TokenSalt)
79115
if subtle.ConstantTimeCompare([]byte(t.TokenHash), []byte(tempHash)) == 1 {
116+
if successfulAccessTokenCache != nil {
117+
successfulAccessTokenCache.Add(token, t.ID)
118+
}
80119
return &t, nil
81120
}
82121
}

modules/git/command.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,24 +110,47 @@ func (c *Command) RunInDirTimeoutEnvFullPipeline(env []string, timeout time.Dura
110110
// RunInDirTimeoutEnvFullPipelineFunc executes the command in given directory with given timeout,
111111
// it pipes stdout and stderr to given io.Writer and passes in an io.Reader as stdin. Between cmd.Start and cmd.Wait the passed in function is run.
112112
func (c *Command) RunInDirTimeoutEnvFullPipelineFunc(env []string, timeout time.Duration, dir string, stdout, stderr io.Writer, stdin io.Reader, fn func(context.Context, context.CancelFunc) error) error {
113-
if timeout == -1 {
114-
timeout = defaultCommandExecutionTimeout
113+
return c.RunWithContext(&RunContext{
114+
Env: env,
115+
Timeout: timeout,
116+
Dir: dir,
117+
Stdout: stdout,
118+
Stderr: stderr,
119+
Stdin: stdin,
120+
PipelineFunc: fn,
121+
})
122+
}
123+
124+
// RunContext represents parameters to run the command
125+
type RunContext struct {
126+
Env []string
127+
Timeout time.Duration
128+
Dir string
129+
Stdout, Stderr io.Writer
130+
Stdin io.Reader
131+
PipelineFunc func(context.Context, context.CancelFunc) error
132+
}
133+
134+
// RunWithContext run the command with context
135+
func (c *Command) RunWithContext(rc *RunContext) error {
136+
if rc.Timeout == -1 {
137+
rc.Timeout = defaultCommandExecutionTimeout
115138
}
116139

117-
if len(dir) == 0 {
140+
if len(rc.Dir) == 0 {
118141
log.Debug("%s", c)
119142
} else {
120-
log.Debug("%s: %v", dir, c)
143+
log.Debug("%s: %v", rc.Dir, c)
121144
}
122145

123-
ctx, cancel := context.WithTimeout(c.parentContext, timeout)
146+
ctx, cancel := context.WithTimeout(c.parentContext, rc.Timeout)
124147
defer cancel()
125148

126149
cmd := exec.CommandContext(ctx, c.name, c.args...)
127-
if env == nil {
150+
if rc.Env == nil {
128151
cmd.Env = os.Environ()
129152
} else {
130-
cmd.Env = env
153+
cmd.Env = rc.Env
131154
}
132155

133156
cmd.Env = append(
@@ -141,23 +164,23 @@ func (c *Command) RunInDirTimeoutEnvFullPipelineFunc(env []string, timeout time.
141164
if goVersionLessThan115 {
142165
cmd.Env = append(cmd.Env, "GODEBUG=asyncpreemptoff=1")
143166
}
144-
cmd.Dir = dir
145-
cmd.Stdout = stdout
146-
cmd.Stderr = stderr
147-
cmd.Stdin = stdin
167+
cmd.Dir = rc.Dir
168+
cmd.Stdout = rc.Stdout
169+
cmd.Stderr = rc.Stderr
170+
cmd.Stdin = rc.Stdin
148171
if err := cmd.Start(); err != nil {
149172
return err
150173
}
151174

152175
desc := c.desc
153176
if desc == "" {
154-
desc = fmt.Sprintf("%s %s %s [repo_path: %s]", GitExecutable, c.name, strings.Join(c.args, " "), dir)
177+
desc = fmt.Sprintf("%s %s %s [repo_path: %s]", GitExecutable, c.name, strings.Join(c.args, " "), rc.Dir)
155178
}
156179
pid := process.GetManager().Add(desc, cancel)
157180
defer process.GetManager().Remove(pid)
158181

159-
if fn != nil {
160-
err := fn(ctx, cancel)
182+
if rc.PipelineFunc != nil {
183+
err := rc.PipelineFunc(ctx, cancel)
161184
if err != nil {
162185
cancel()
163186
_ = cmd.Wait()

modules/git/repo.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ import (
99
"bytes"
1010
"context"
1111
"fmt"
12+
"io"
13+
"net/url"
1214
"os"
1315
"path"
1416
"strconv"
1517
"strings"
1618
"time"
19+
20+
"code.gitea.io/gitea/modules/proxy"
1721
)
1822

1923
// GPGSettings represents the default GPG settings for this repository
@@ -99,12 +103,12 @@ type CloneRepoOptions struct {
99103
}
100104

101105
// Clone clones original repository to target path.
102-
func Clone(from, to string, opts CloneRepoOptions) (err error) {
106+
func Clone(from, to string, opts CloneRepoOptions) error {
103107
return CloneWithContext(DefaultContext, from, to, opts)
104108
}
105109

106110
// CloneWithContext clones original repository to target path.
107-
func CloneWithContext(ctx context.Context, from, to string, opts CloneRepoOptions) (err error) {
111+
func CloneWithContext(ctx context.Context, from, to string, opts CloneRepoOptions) error {
108112
cargs := make([]string, len(GlobalCommandArgs))
109113
copy(cargs, GlobalCommandArgs)
110114
return CloneWithArgs(ctx, from, to, cargs, opts)
@@ -146,8 +150,24 @@ func CloneWithArgs(ctx context.Context, from, to string, args []string, opts Clo
146150
opts.Timeout = -1
147151
}
148152

149-
_, err = cmd.RunTimeout(opts.Timeout)
150-
return err
153+
var envs = os.Environ()
154+
u, err := url.Parse(from)
155+
if err == nil && (strings.EqualFold(u.Scheme, "http") || strings.EqualFold(u.Scheme, "https")) {
156+
if proxy.Match(u.Host) {
157+
envs = append(envs, fmt.Sprintf("https_proxy=%s", proxy.GetProxyURL()))
158+
}
159+
}
160+
161+
var stderr = new(bytes.Buffer)
162+
if err = cmd.RunWithContext(&RunContext{
163+
Timeout: opts.Timeout,
164+
Env: envs,
165+
Stdout: io.Discard,
166+
Stderr: stderr,
167+
}); err != nil {
168+
return ConcatenateError(err, stderr.String())
169+
}
170+
return nil
151171
}
152172

153173
// PullRemoteOptions options when pull from remote

modules/lfs/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ type Client interface {
2424
}
2525

2626
// NewClient creates a LFS client
27-
func NewClient(endpoint *url.URL) Client {
27+
func NewClient(endpoint *url.URL, skipTLSVerify bool) Client {
2828
if endpoint.Scheme == "file" {
2929
return newFilesystemClient(endpoint)
3030
}
31-
return newHTTPClient(endpoint)
31+
return newHTTPClient(endpoint, skipTLSVerify)
3232
}

modules/lfs/client_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ import (
1313

1414
func TestNewClient(t *testing.T) {
1515
u, _ := url.Parse("file:///test")
16-
c := NewClient(u)
16+
c := NewClient(u, true)
1717
assert.IsType(t, &FilesystemClient{}, c)
1818

1919
u, _ = url.Parse("https://test.com/lfs")
20-
c = NewClient(u)
20+
c = NewClient(u, true)
2121
assert.IsType(t, &HTTPClient{}, c)
2222
}

modules/lfs/http_client.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package lfs
77
import (
88
"bytes"
99
"context"
10+
"crypto/tls"
1011
"errors"
1112
"fmt"
1213
"net/http"
@@ -15,6 +16,7 @@ import (
1516

1617
"code.gitea.io/gitea/modules/json"
1718
"code.gitea.io/gitea/modules/log"
19+
"code.gitea.io/gitea/modules/proxy"
1820
)
1921

2022
const batchSize = 20
@@ -32,8 +34,13 @@ func (c *HTTPClient) BatchSize() int {
3234
return batchSize
3335
}
3436

35-
func newHTTPClient(endpoint *url.URL) *HTTPClient {
36-
hc := &http.Client{}
37+
func newHTTPClient(endpoint *url.URL, skipTLSVerify bool) *HTTPClient {
38+
hc := &http.Client{
39+
Transport: &http.Transport{
40+
TLSClientConfig: &tls.Config{InsecureSkipVerify: skipTLSVerify},
41+
Proxy: proxy.Proxy(),
42+
},
43+
}
3744

3845
client := &HTTPClient{
3946
client: hc,

0 commit comments

Comments
 (0)