mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Add RemoteAddress to mirrors (#26952)
				
					
				
			This PR adds a new field `RemoteAddress` to both mirror types which contains the sanitized remote address for easier (database) access to that information. Will be used in the audit PR if merged.
This commit is contained in:
		@@ -532,6 +532,8 @@ var migrations = []Migration{
 | 
			
		||||
	NewMigration("Add Actions artifacts expiration date", v1_21.AddExpiredUnixColumnInActionArtifactTable),
 | 
			
		||||
	// v275 -> v276
 | 
			
		||||
	NewMigration("Add ScheduleID for ActionRun", v1_21.AddScheduleIDForActionRun),
 | 
			
		||||
	// v276 -> v277
 | 
			
		||||
	NewMigration("Add RemoteAddress to mirrors", v1_21.AddRemoteAddressToMirrors),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetCurrentDBVersion returns the current db version
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										132
									
								
								models/migrations/v1_21/v276.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								models/migrations/v1_21/v276.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package v1_21 //nolint
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	giturl "code.gitea.io/gitea/modules/git/url"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
 | 
			
		||||
	"xorm.io/xorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func AddRemoteAddressToMirrors(x *xorm.Engine) error {
 | 
			
		||||
	type Mirror struct {
 | 
			
		||||
		RemoteAddress string `xorm:"VARCHAR(2048)"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type PushMirror struct {
 | 
			
		||||
		RemoteAddress string `xorm:"VARCHAR(2048)"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := x.Sync(new(Mirror), new(PushMirror)); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := migratePullMirrors(x); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return migratePushMirrors(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func migratePullMirrors(x *xorm.Engine) error {
 | 
			
		||||
	type Mirror struct {
 | 
			
		||||
		ID            int64  `xorm:"pk autoincr"`
 | 
			
		||||
		RepoID        int64  `xorm:"INDEX"`
 | 
			
		||||
		RemoteAddress string `xorm:"VARCHAR(2048)"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sess := x.NewSession()
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
 | 
			
		||||
	if err := sess.Begin(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := sess.Iterate(new(Mirror), func(_ int, bean any) error {
 | 
			
		||||
		m := bean.(*Mirror)
 | 
			
		||||
		remoteAddress, err := getRemoteAddress(sess, m.RepoID, "origin")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m.RemoteAddress = remoteAddress
 | 
			
		||||
 | 
			
		||||
		_, err = sess.ID(m.ID).Cols("remote_address").Update(m)
 | 
			
		||||
		return err
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sess.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func migratePushMirrors(x *xorm.Engine) error {
 | 
			
		||||
	type PushMirror struct {
 | 
			
		||||
		ID            int64 `xorm:"pk autoincr"`
 | 
			
		||||
		RepoID        int64 `xorm:"INDEX"`
 | 
			
		||||
		RemoteName    string
 | 
			
		||||
		RemoteAddress string `xorm:"VARCHAR(2048)"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sess := x.NewSession()
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
 | 
			
		||||
	if err := sess.Begin(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := sess.Iterate(new(PushMirror), func(_ int, bean any) error {
 | 
			
		||||
		m := bean.(*PushMirror)
 | 
			
		||||
		remoteAddress, err := getRemoteAddress(sess, m.RepoID, m.RemoteName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m.RemoteAddress = remoteAddress
 | 
			
		||||
 | 
			
		||||
		_, err = sess.ID(m.ID).Cols("remote_address").Update(m)
 | 
			
		||||
		return err
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sess.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getRemoteAddress(sess *xorm.Session, repoID int64, remoteName string) (string, error) {
 | 
			
		||||
	var ownerName string
 | 
			
		||||
	var repoName string
 | 
			
		||||
	has, err := sess.
 | 
			
		||||
		Table("repository").
 | 
			
		||||
		Cols("owner_name", "lower_name").
 | 
			
		||||
		Where("id=?", repoID).
 | 
			
		||||
		Get(&ownerName, &repoName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	} else if !has {
 | 
			
		||||
		return "", fmt.Errorf("repository [%v] not found", repoID)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repoPath := filepath.Join(setting.RepoRootPath, strings.ToLower(ownerName), strings.ToLower(repoName)+".git")
 | 
			
		||||
 | 
			
		||||
	remoteURL, err := git.GetRemoteAddress(context.Background(), repoPath, remoteName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	u, err := giturl.Parse(remoteURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	u.User = nil
 | 
			
		||||
 | 
			
		||||
	return u.String(), nil
 | 
			
		||||
}
 | 
			
		||||
@@ -31,7 +31,7 @@ type Mirror struct {
 | 
			
		||||
	LFS         bool   `xorm:"lfs_enabled NOT NULL DEFAULT false"`
 | 
			
		||||
	LFSEndpoint string `xorm:"lfs_endpoint TEXT"`
 | 
			
		||||
 | 
			
		||||
	Address string `xorm:"-"`
 | 
			
		||||
	RemoteAddress string `xorm:"VARCHAR(2048)"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,11 @@ var ErrPushMirrorNotExist = util.NewNotExistErrorf("PushMirror does not exist")
 | 
			
		||||
 | 
			
		||||
// PushMirror represents mirror information of a repository.
 | 
			
		||||
type PushMirror struct {
 | 
			
		||||
	ID         int64       `xorm:"pk autoincr"`
 | 
			
		||||
	RepoID     int64       `xorm:"INDEX"`
 | 
			
		||||
	Repo       *Repository `xorm:"-"`
 | 
			
		||||
	RemoteName string
 | 
			
		||||
	ID            int64       `xorm:"pk autoincr"`
 | 
			
		||||
	RepoID        int64       `xorm:"INDEX"`
 | 
			
		||||
	Repo          *Repository `xorm:"-"`
 | 
			
		||||
	RemoteName    string
 | 
			
		||||
	RemoteAddress string `xorm:"VARCHAR(2048)"`
 | 
			
		||||
 | 
			
		||||
	SyncOnCommit   bool `xorm:"NOT NULL DEFAULT true"`
 | 
			
		||||
	Interval       time.Duration
 | 
			
		||||
@@ -31,6 +32,7 @@ type PushMirror struct {
 | 
			
		||||
	LastUpdateUnix timeutil.TimeStamp `xorm:"INDEX last_update"`
 | 
			
		||||
	LastError      string             `xorm:"text"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PushMirrorOptions struct {
 | 
			
		||||
	ID         int64
 | 
			
		||||
	RepoID     int64
 | 
			
		||||
 
 | 
			
		||||
@@ -191,12 +191,8 @@ func (repo *Repository) SanitizedOriginalURL() string {
 | 
			
		||||
	if repo.OriginalURL == "" {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	u, err := url.Parse(repo.OriginalURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	u.User = nil
 | 
			
		||||
	return u.String()
 | 
			
		||||
	u, _ := util.SanitizeURL(repo.OriginalURL)
 | 
			
		||||
	return u
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// text representations to be returned in SizeDetail.Name
 | 
			
		||||
 
 | 
			
		||||
@@ -180,12 +180,17 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
 | 
			
		||||
	defer committer.Close()
 | 
			
		||||
 | 
			
		||||
	if opts.Mirror {
 | 
			
		||||
		remoteAddress, err := util.SanitizeURL(opts.CloneAddr)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return repo, err
 | 
			
		||||
		}
 | 
			
		||||
		mirrorModel := repo_model.Mirror{
 | 
			
		||||
			RepoID:         repo.ID,
 | 
			
		||||
			Interval:       setting.Mirror.DefaultInterval,
 | 
			
		||||
			EnablePrune:    true,
 | 
			
		||||
			NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval),
 | 
			
		||||
			LFS:            opts.LFS,
 | 
			
		||||
			RemoteAddress:  remoteAddress,
 | 
			
		||||
		}
 | 
			
		||||
		if opts.LFS {
 | 
			
		||||
			mirrorModel.LFSEndpoint = opts.LFSEndpoint
 | 
			
		||||
 
 | 
			
		||||
@@ -39,3 +39,12 @@ func URLJoin(base string, elems ...string) string {
 | 
			
		||||
	}
 | 
			
		||||
	return joinedURL
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SanitizeURL(s string) (string, error) {
 | 
			
		||||
	u, err := url.Parse(s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	u.User = nil
 | 
			
		||||
	return u.String(), nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -353,12 +353,19 @@ func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirro
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	remoteAddress, err := util.SanitizeURL(mirrorOption.RemoteAddress)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("SanitizeURL", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pushMirror := &repo_model.PushMirror{
 | 
			
		||||
		RepoID:       repo.ID,
 | 
			
		||||
		Repo:         repo,
 | 
			
		||||
		RemoteName:   fmt.Sprintf("remote_mirror_%s", remoteSuffix),
 | 
			
		||||
		Interval:     interval,
 | 
			
		||||
		SyncOnCommit: mirrorOption.SyncOnCommit,
 | 
			
		||||
		RepoID:        repo.ID,
 | 
			
		||||
		Repo:          repo,
 | 
			
		||||
		RemoteName:    fmt.Sprintf("remote_mirror_%s", remoteSuffix),
 | 
			
		||||
		Interval:      interval,
 | 
			
		||||
		SyncOnCommit:  mirrorOption.SyncOnCommit,
 | 
			
		||||
		RemoteAddress: remoteAddress,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = repo_model.InsertPushMirror(ctx, pushMirror); err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -243,6 +243,13 @@ func SettingsPost(ctx *context.Context) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		remoteAddress, err := util.SanitizeURL(form.MirrorAddress)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("SanitizeURL", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		pullMirror.RemoteAddress = remoteAddress
 | 
			
		||||
 | 
			
		||||
		form.LFS = form.LFS && setting.LFS.StartServer
 | 
			
		||||
 | 
			
		||||
		if len(form.LFSEndpoint) > 0 {
 | 
			
		||||
@@ -397,12 +404,19 @@ func SettingsPost(ctx *context.Context) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		remoteAddress, err := util.SanitizeURL(form.PushMirrorAddress)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("SanitizeURL", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m := &repo_model.PushMirror{
 | 
			
		||||
			RepoID:       repo.ID,
 | 
			
		||||
			Repo:         repo,
 | 
			
		||||
			RemoteName:   fmt.Sprintf("remote_mirror_%s", remoteSuffix),
 | 
			
		||||
			SyncOnCommit: form.PushMirrorSyncOnCommit,
 | 
			
		||||
			Interval:     interval,
 | 
			
		||||
			RepoID:        repo.ID,
 | 
			
		||||
			Repo:          repo,
 | 
			
		||||
			RemoteName:    fmt.Sprintf("remote_mirror_%s", remoteSuffix),
 | 
			
		||||
			SyncOnCommit:  form.PushMirrorSyncOnCommit,
 | 
			
		||||
			Interval:      interval,
 | 
			
		||||
			RemoteAddress: remoteAddress,
 | 
			
		||||
		}
 | 
			
		||||
		if err := repo_model.InsertPushMirror(ctx, m); err != nil {
 | 
			
		||||
			ctx.ServerError("InsertPushMirror", err)
 | 
			
		||||
 
 | 
			
		||||
@@ -628,15 +628,6 @@ func markupRender(ctx *context.Context, renderCtx *markup.RenderContext, input i
 | 
			
		||||
	return escaped, output, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func safeURL(address string) string {
 | 
			
		||||
	u, err := url.Parse(address)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return address
 | 
			
		||||
	}
 | 
			
		||||
	u.User = nil
 | 
			
		||||
	return u.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkHomeCodeViewable(ctx *context.Context) {
 | 
			
		||||
	if len(ctx.Repo.Units) > 0 {
 | 
			
		||||
		if ctx.Repo.Repository.IsBeingCreated() {
 | 
			
		||||
@@ -660,7 +651,7 @@ func checkHomeCodeViewable(ctx *context.Context) {
 | 
			
		||||
 | 
			
		||||
			ctx.Data["Repo"] = ctx.Repo
 | 
			
		||||
			ctx.Data["MigrateTask"] = task
 | 
			
		||||
			ctx.Data["CloneAddr"] = safeURL(cfg.CloneAddr)
 | 
			
		||||
			ctx.Data["CloneAddr"], _ = util.SanitizeURL(cfg.CloneAddr)
 | 
			
		||||
			ctx.Data["Failed"] = task.Status == structs.TaskStatusFailed
 | 
			
		||||
			ctx.HTML(http.StatusOK, tplMigrating)
 | 
			
		||||
			return
 | 
			
		||||
 
 | 
			
		||||
@@ -5,21 +5,16 @@ package convert
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ToPushMirror convert from repo_model.PushMirror and remoteAddress to api.TopicResponse
 | 
			
		||||
func ToPushMirror(pm *repo_model.PushMirror) (*api.PushMirror, error) {
 | 
			
		||||
	repo := pm.GetRepository()
 | 
			
		||||
	remoteAddress, err := getRemoteAddress(repo, pm.RemoteName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &api.PushMirror{
 | 
			
		||||
		RepoName:       repo.Name,
 | 
			
		||||
		RemoteName:     pm.RemoteName,
 | 
			
		||||
		RemoteAddress:  remoteAddress,
 | 
			
		||||
		RemoteAddress:  pm.RemoteAddress,
 | 
			
		||||
		CreatedUnix:    pm.CreatedUnix.FormatLong(),
 | 
			
		||||
		LastUpdateUnix: pm.LastUpdateUnix.FormatLong(),
 | 
			
		||||
		LastError:      pm.LastError,
 | 
			
		||||
@@ -27,13 +22,3 @@ func ToPushMirror(pm *repo_model.PushMirror) (*api.PushMirror, error) {
 | 
			
		||||
		SyncOnCommit:   pm.SyncOnCommit,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getRemoteAddress(repo *repo_model.Repository, remoteName string) (string, error) {
 | 
			
		||||
	url, err := git.GetRemoteURL(git.DefaultContext, repo.RepoPath(), remoteName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	// remove confidential information
 | 
			
		||||
	url.User = nil
 | 
			
		||||
	return url.String(), nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,8 +37,7 @@
 | 
			
		||||
					{{end}}
 | 
			
		||||
				</div>
 | 
			
		||||
				{{if $.PullMirror}}
 | 
			
		||||
					{{$address := MirrorRemoteAddress $.Context . $.PullMirror.GetRemoteName false}}
 | 
			
		||||
					<div class="fork-flag">{{$.locale.Tr "repo.mirror_from"}} <a target="_blank" rel="noopener noreferrer" href="{{$address.Address}}">{{$address.Address}}</a></div>
 | 
			
		||||
					<div class="fork-flag">{{$.locale.Tr "repo.mirror_from"}} <a target="_blank" rel="noopener noreferrer" href="{{$.PullMirror.RemoteAddress}}">{{$.PullMirror.RemoteAddress}}</a></div>
 | 
			
		||||
				{{end}}
 | 
			
		||||
				{{if .IsFork}}<div class="fork-flag">{{$.locale.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{.BaseRepo.FullName}}</a></div>{{end}}
 | 
			
		||||
				{{if .IsGenerated}}<div class="fork-flag">{{$.locale.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{.TemplateRepo.FullName}}</a></div>{{end}}
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@
 | 
			
		||||
					{{else if $isWorkingPullMirror}}
 | 
			
		||||
					<tbody>
 | 
			
		||||
						<tr>
 | 
			
		||||
							<td>{{(MirrorRemoteAddress $.Context .Repository .PullMirror.GetRemoteName false).Address}}</td>
 | 
			
		||||
							<td>{{.PullMirror.RemoteAddress}}</td>
 | 
			
		||||
							<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.pull"}}</td>
 | 
			
		||||
							<td>{{DateTime "full" .PullMirror.UpdatedUnix}}</td>
 | 
			
		||||
							<td class="right aligned">
 | 
			
		||||
@@ -200,8 +200,7 @@
 | 
			
		||||
					<tbody>
 | 
			
		||||
						{{range .PushMirrors}}
 | 
			
		||||
						<tr>
 | 
			
		||||
							{{$address := MirrorRemoteAddress $.Context $.Repository .GetRemoteName true}}
 | 
			
		||||
							<td class="gt-word-break">{{$address.Address}}</td>
 | 
			
		||||
							<td class="gt-word-break">{{.RemoteAddress}}</td>
 | 
			
		||||
							<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.push"}}</td>
 | 
			
		||||
							<td>{{if .LastUpdateUnix}}{{DateTime "full" .LastUpdateUnix}}{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label" data-tooltip-content="{{.LastError}}">{{$.locale.Tr "error"}}</div>{{end}}</td>
 | 
			
		||||
							<td class="right aligned">
 | 
			
		||||
@@ -211,7 +210,7 @@
 | 
			
		||||
									data-tooltip-content="{{$.locale.Tr "repo.settings.mirror_settings.push_mirror.edit_sync_time"}}"
 | 
			
		||||
									data-modal-push-mirror-edit-id="{{.ID}}"
 | 
			
		||||
									data-modal-push-mirror-edit-interval="{{.Interval}}"
 | 
			
		||||
									data-modal-push-mirror-edit-address="{{$address.Address}}"
 | 
			
		||||
									data-modal-push-mirror-edit-address="{{.RemoteAddress}}"
 | 
			
		||||
								>
 | 
			
		||||
									{{svg "octicon-pencil" 14}}
 | 
			
		||||
								</button>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user