mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-03 21:12:09 +02:00
Merge bee3e1c09b1cedad9b379cc112b25f6b9fc1c186 into 6eed75af248ae597d854a3c5e6b8831a5ff76290
This commit is contained in:
commit
3657d33223
@ -287,6 +287,7 @@ func (g *RepositoryDumper) CreateLabels(_ context.Context, labels ...*base.Label
|
||||
// CreateReleases creates releases
|
||||
func (g *RepositoryDumper) CreateReleases(_ context.Context, releases ...*base.Release) error {
|
||||
if g.opts.ReleaseAssets {
|
||||
httpClient := NewMigrationHTTPClient()
|
||||
for _, release := range releases {
|
||||
attachDir := filepath.Join("release_assets", uuid.New().String())
|
||||
if err := os.MkdirAll(filepath.Join(g.baseDir, attachDir), os.ModePerm); err != nil {
|
||||
@ -296,25 +297,26 @@ func (g *RepositoryDumper) CreateReleases(_ context.Context, releases ...*base.R
|
||||
// we cannot use asset.Name because it might contains special characters.
|
||||
attachLocalPath := filepath.Join(attachDir, uuid.New().String())
|
||||
|
||||
// SECURITY: We cannot check the DownloadURL and DownloadFunc are safe here
|
||||
// ... we must assume that they are safe and simply download the attachment
|
||||
// SECURITY: Prefer DownloadFunc and fall back to a migration-filtered HTTP client.
|
||||
// download attachment
|
||||
err := func(attachPath string) error {
|
||||
var rc io.ReadCloser
|
||||
var err error
|
||||
if asset.DownloadURL == nil {
|
||||
if asset.DownloadFunc != nil {
|
||||
rc, err = asset.DownloadFunc()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
} else {
|
||||
resp, err := http.Get(*asset.DownloadURL)
|
||||
} else if asset.DownloadURL != nil {
|
||||
resp, err := httpClient.Get(*asset.DownloadURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
rc = resp.Body
|
||||
} else {
|
||||
return errors.New("missing download URL and download function")
|
||||
}
|
||||
|
||||
fw, err := os.Create(attachPath)
|
||||
|
||||
98
services/migrations/dump_test.go
Normal file
98
services/migrations/dump_test.go
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
base "code.gitea.io/gitea/modules/migration"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRepositoryDumperReleaseAssetPrefersDownloadFunc(t *testing.T) {
|
||||
var downloadURLHits int32
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.AddInt32(&downloadURLHits, 1)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte("remote"))
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
downloadURL := server.URL + "/asset"
|
||||
var downloadFuncCalls int32
|
||||
asset := &base.ReleaseAsset{
|
||||
Name: "asset.txt",
|
||||
DownloadURL: &downloadURL,
|
||||
DownloadFunc: func() (io.ReadCloser, error) {
|
||||
atomic.AddInt32(&downloadFuncCalls, 1)
|
||||
return io.NopCloser(strings.NewReader("local")), nil
|
||||
},
|
||||
}
|
||||
release := &base.Release{
|
||||
TagName: "v1.0.0",
|
||||
Assets: []*base.ReleaseAsset{asset},
|
||||
}
|
||||
|
||||
baseDir := t.TempDir()
|
||||
dumper, err := NewRepositoryDumper(context.Background(), baseDir, "owner", "repo", base.MigrateOptions{ReleaseAssets: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, dumper.CreateReleases(context.Background(), release))
|
||||
assert.Equal(t, int32(1), atomic.LoadInt32(&downloadFuncCalls))
|
||||
assert.Equal(t, int32(0), atomic.LoadInt32(&downloadURLHits))
|
||||
|
||||
attachRelative := filepath.Join("release_assets", release.TagName, asset.Name)
|
||||
attachPath := filepath.Join(baseDir, "owner", "repo", attachRelative)
|
||||
data, err := os.ReadFile(attachPath)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "local", string(data))
|
||||
require.NotNil(t, asset.DownloadURL)
|
||||
assert.Equal(t, attachRelative, *asset.DownloadURL)
|
||||
}
|
||||
|
||||
func TestRepositoryDumperReleaseAssetUsesMigrationClient(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
test.MockVariableValue(&setting.Migrations.AllowedDomains, "github.com")()
|
||||
test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, false)()
|
||||
assert.NoError(t, Init())
|
||||
|
||||
var downloadURLHits int32
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
atomic.AddInt32(&downloadURLHits, 1)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte("remote"))
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
downloadURL := server.URL + "/asset"
|
||||
asset := &base.ReleaseAsset{
|
||||
Name: "asset.txt",
|
||||
DownloadURL: &downloadURL,
|
||||
}
|
||||
release := &base.Release{
|
||||
TagName: "v1.0.0",
|
||||
Assets: []*base.ReleaseAsset{asset},
|
||||
}
|
||||
|
||||
baseDir := t.TempDir()
|
||||
dumper, err := NewRepositoryDumper(context.Background(), baseDir, "owner", "repo", base.MigrateOptions{ReleaseAssets: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Error(t, dumper.CreateReleases(context.Background(), release))
|
||||
assert.Equal(t, int32(0), atomic.LoadInt32(&downloadURLHits))
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user