Skip to content

Commit 7a083b9

Browse files
committed
add black list and white list support for migrating repositories
1 parent 3fd0eec commit 7a083b9

File tree

9 files changed

+184
-0
lines changed

9 files changed

+184
-0
lines changed

custom/conf/app.ini.sample

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,3 +803,11 @@ IS_INPUT_FILE = false
803803
ENABLED = false
804804
; If you want to add authorization, specify a token here
805805
TOKEN =
806+
807+
[migration]
808+
; Whitelist for migrating, default is blank. Blank means everything will be allowed.
809+
; Multiple domains could be separated by commas.
810+
WHITELISTED_DOMAINS =
811+
; Blacklist for migrating, default is blank. Multiple domains could be separated by commas.
812+
; When WHITELISTED_DOMAINS is not blank, this option will be ignored.
813+
BLACKLISTED_DOMAINS =

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,15 @@ Two special environment variables are passed to the render command:
511511
- `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths.
512512

513513
## Time (`time`)
514+
514515
- `FORMAT`: Time format to diplay on UI. i.e. RFC1123 or 2006-01-02 15:04:05
515516
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Shanghai/Asia
516517

518+
## Migraions (`migration`)
519+
520+
- `WHITELISTED_DOMAINS`: ****: Domains whitelist for migrating repositories, default is blank. It means everything will be allowed. Multiple domains could be separated by commas.
521+
- `BLACKLISTED_DOMAINS`: ****: Domains blacklist for migrating repositories, default is blank. Multiple domains could be separated by commas. When `WHITELISTED_DOMAINS` is not blank, this option will be ignored.
522+
517523
## Other (`other`)
518524

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

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,15 @@ IS_INPUT_FILE = false
240240
- IS_INPUT_FILE: 输入方式是最后一个参数为文件路径还是从标准输入读取。
241241

242242
## Time (`time`)
243+
243244
- `FORMAT`: 显示在界面上的时间格式。比如: RFC1123 或者 2006-01-02 15:04:05
244245
- `DEFAULT_UI_LOCATION`: 默认显示在界面上的时区,默认为本地时区。比如: Asia/Shanghai
245246

247+
## Migraions (`migration`)
248+
249+
- `WHITELISTED_DOMAINS`: ****: 迁移仓库的域名白名单,默认为空,表示允许从任意域名迁移仓库,多个域名用逗号分隔。
250+
- `BLACKLISTED_DOMAINS`: ****: 迁移仓库的域名黑名单,默认为空,多个域名用逗号分隔。如果 `WHITELISTED_DOMAINS` 不为空,此选项将会被忽略。
251+
246252
## Other (`other`)
247253

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

modules/matchlist/matchlist.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package matchlist
6+
7+
import (
8+
"github.com/gobwas/glob"
9+
)
10+
11+
// Matchlist represents a black or white list
12+
type Matchlist struct {
13+
rules []string
14+
ruleGlobs []glob.Glob
15+
}
16+
17+
// NewMatchlist creates a new black or white list
18+
func NewMatchlist(rules ...string) (*Matchlist, error) {
19+
list := Matchlist{
20+
rules: rules,
21+
ruleGlobs: make([]glob.Glob, 0, len(rules)),
22+
}
23+
24+
for _, rule := range list.rules {
25+
rg, err := glob.Compile(rule)
26+
if err != nil {
27+
return nil, err
28+
}
29+
list.ruleGlobs = append(list.ruleGlobs, rg)
30+
}
31+
32+
return &list, nil
33+
}
34+
35+
// Match will matches
36+
func (b *Matchlist) Match(u string) bool {
37+
for _, r := range b.ruleGlobs {
38+
if r.Match(u) {
39+
return true
40+
}
41+
}
42+
return false
43+
}

modules/migrations/migrate.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@
66
package migrations
77

88
import (
9+
"fmt"
10+
"net/url"
11+
"strings"
12+
913
"code.gitea.io/gitea/models"
1014
"code.gitea.io/gitea/modules/log"
15+
"code.gitea.io/gitea/modules/matchlist"
1116
"code.gitea.io/gitea/modules/migrations/base"
17+
"code.gitea.io/gitea/modules/setting"
1218
)
1319

1420
// MigrateOptions is equal to base.MigrateOptions
@@ -23,8 +29,34 @@ func RegisterDownloaderFactory(factory base.DownloaderFactory) {
2329
factories = append(factories, factory)
2430
}
2531

32+
func isMigrateURLAllowed(remoteURL string) (bool, error) {
33+
u, err := url.Parse(remoteURL)
34+
if err != nil {
35+
return false, err
36+
}
37+
38+
if strings.EqualFold(u.Scheme, "http") || strings.EqualFold(u.Scheme, "https") {
39+
if len(setting.Migration.WhitelistedDomains) > 0 {
40+
if !whitelist.Match(u.Host) {
41+
return false, fmt.Errorf("Migrate from %v is not allowed", u.Host)
42+
}
43+
} else {
44+
if blacklist.Match(u.Host) {
45+
return false, fmt.Errorf("Migrate from %v is not allowed", u.Host)
46+
}
47+
}
48+
}
49+
50+
return true, nil
51+
}
52+
2653
// MigrateRepository migrate repository according MigrateOptions
2754
func MigrateRepository(doer *models.User, ownerName string, opts base.MigrateOptions) (*models.Repository, error) {
55+
allowed, err := isMigrateURLAllowed(opts.RemoteURL)
56+
if !allowed {
57+
return nil, err
58+
}
59+
2860
var (
2961
downloader base.Downloader
3062
uploader = NewGiteaLocalUploader(doer, ownerName, opts.Name)
@@ -250,3 +282,23 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
250282

251283
return nil
252284
}
285+
286+
var (
287+
whitelist *matchlist.Matchlist
288+
blacklist *matchlist.Matchlist
289+
)
290+
291+
// Init migrations service
292+
func Init() error {
293+
var err error
294+
whitelist, err = matchlist.NewMatchlist(setting.Migration.WhitelistedDomains...)
295+
if err != nil {
296+
return fmt.Errorf("Init migration whitelist domains failed: %v", err)
297+
}
298+
299+
blacklist, err = matchlist.NewMatchlist(setting.Migration.BlacklistedDomains...)
300+
if err != nil {
301+
return fmt.Errorf("Init migration blacklist domains failed: %v", err)
302+
}
303+
return nil
304+
}

modules/migrations/migrate_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"testing"
9+
10+
"code.gitea.io/gitea/modules/setting"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestMigrateWhiteBlacklist(t *testing.T) {
16+
setting.Migration.WhitelistedDomains = []string{"github.com"}
17+
assert.NoError(t, Init())
18+
19+
allowed, err := isMigrateURLAllowed("https://gitlab.com/gitlab/gitlab.git")
20+
assert.False(t, allowed)
21+
assert.Error(t, err)
22+
23+
allowed, err = isMigrateURLAllowed("https://github.com/go-gitea/gitea.git")
24+
assert.True(t, allowed)
25+
assert.NoError(t, err)
26+
27+
setting.Migration.WhitelistedDomains = []string{}
28+
setting.Migration.BlacklistedDomains = []string{"github.com"}
29+
assert.NoError(t, Init())
30+
31+
allowed, err = isMigrateURLAllowed("https://gitlab.com/gitlab/gitlab.git")
32+
assert.True(t, allowed)
33+
assert.NoError(t, err)
34+
35+
allowed, err = isMigrateURLAllowed("https://github.com/go-gitea/gitea.git")
36+
assert.False(t, allowed)
37+
assert.Error(t, err)
38+
}

modules/setting/migrate.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package setting
6+
7+
import (
8+
"fmt"
9+
)
10+
11+
var Migration = struct {
12+
WhitelistedDomains []string
13+
BlacklistedDomains []string
14+
} {
15+
WhitelistedDomains: []string{},
16+
BlacklistedDomains: []string{},
17+
}
18+
19+
// InitMigrationConfig represents load migration configurations
20+
func InitMigrationConfig() error {
21+
if err := Cfg.Section("migration").MapTo(&Migration); err != nil {
22+
return fmt.Errorf("Failed to map Migration settings: %v", err)
23+
}
24+
return nil
25+
}

routers/init.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"code.gitea.io/gitea/modules/mailer"
2020
"code.gitea.io/gitea/modules/markup"
2121
"code.gitea.io/gitea/modules/markup/external"
22+
repo_migrations "code.gitea.io/gitea/modules/migrations"
2223
"code.gitea.io/gitea/modules/setting"
2324
"code.gitea.io/gitea/modules/ssh"
2425

@@ -101,6 +102,10 @@ func GlobalInit() {
101102
models.InitSyncMirrors()
102103
models.InitDeliverHooks()
103104
models.InitTestPullRequests()
105+
106+
if err := repo_migrations.Init(); err != nil {
107+
log.Fatal("Failed to initialize migrations: %v", err)
108+
}
104109
}
105110
if setting.EnableSQLite3 {
106111
log.Info("SQLite3 Supported")

vendor/modules.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ golang.org/x/tools/go/internal/gcimporter
524524
golang.org/x/tools/internal/fastwalk
525525
golang.org/x/tools/internal/module
526526
# google.golang.org/appengine v1.6.2
527+
# google.golang.org/appengine v1.6.1
527528
google.golang.org/appengine/cloudsql
528529
google.golang.org/appengine/urlfetch
529530
google.golang.org/appengine/internal

0 commit comments

Comments
 (0)