From c766140dad3408048ad843d0e7b4ab5d9f5777c6 Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Sat, 16 Sep 2023 18:03:02 +0200 Subject: [PATCH] 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. --- models/migrations/migrations.go | 2 + models/migrations/v1_21/v276.go | 132 +++++++++++++++++++++++++++ models/repo/mirror.go | 2 +- models/repo/pushmirror.go | 10 +- models/repo/repo.go | 8 +- modules/repository/repo.go | 5 + modules/util/url.go | 9 ++ routers/api/v1/repo/mirror.go | 17 +++- routers/web/repo/setting/setting.go | 24 ++++- routers/web/repo/view.go | 11 +-- services/convert/mirror.go | 17 +--- templates/repo/header.tmpl | 3 +- templates/repo/settings/options.tmpl | 7 +- 13 files changed, 194 insertions(+), 53 deletions(-) create mode 100644 models/migrations/v1_21/v276.go diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index f0a8b05d5..3524077ea 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -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 diff --git a/models/migrations/v1_21/v276.go b/models/migrations/v1_21/v276.go new file mode 100644 index 000000000..8933f186d --- /dev/null +++ b/models/migrations/v1_21/v276.go @@ -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 +} diff --git a/models/repo/mirror.go b/models/repo/mirror.go index 39482037b..fffc7577c 100644 --- a/models/repo/mirror.go +++ b/models/repo/mirror.go @@ -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() { diff --git a/models/repo/pushmirror.go b/models/repo/pushmirror.go index 3edbcceb9..73c138444 100644 --- a/models/repo/pushmirror.go +++ b/models/repo/pushmirror.go @@ -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 diff --git a/models/repo/repo.go b/models/repo/repo.go index b37948fea..5ebc7bfc2 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -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 diff --git a/modules/repository/repo.go b/modules/repository/repo.go index 6bf88e775..b50c8f75c 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -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 diff --git a/modules/util/url.go b/modules/util/url.go index 75fcf634a..62370339c 100644 --- a/modules/util/url.go +++ b/modules/util/url.go @@ -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 +} diff --git a/routers/api/v1/repo/mirror.go b/routers/api/v1/repo/mirror.go index 12542c808..15c7046b4 100644 --- a/routers/api/v1/repo/mirror.go +++ b/routers/api/v1/repo/mirror.go @@ -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 { diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index 7c85ff207..68943586e 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -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) diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 37da76e3e..91c00b049 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -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 diff --git a/services/convert/mirror.go b/services/convert/mirror.go index f7a8e17fd..505110452 100644 --- a/services/convert/mirror.go +++ b/services/convert/mirror.go @@ -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 -} diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index 984e9f044..935060816 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -37,8 +37,7 @@ {{end}} {{if $.PullMirror}} - {{$address := MirrorRemoteAddress $.Context . $.PullMirror.GetRemoteName false}} -
{{$.locale.Tr "repo.mirror_from"}} {{$address.Address}}
+
{{$.locale.Tr "repo.mirror_from"}} {{$.PullMirror.RemoteAddress}}
{{end}} {{if .IsFork}}
{{$.locale.Tr "repo.forked_from"}} {{.BaseRepo.FullName}}
{{end}} {{if .IsGenerated}}
{{$.locale.Tr "repo.generated_from"}} {{.TemplateRepo.FullName}}
{{end}} diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index 16944506f..78700e05b 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -123,7 +123,7 @@ {{else if $isWorkingPullMirror}} - {{(MirrorRemoteAddress $.Context .Repository .PullMirror.GetRemoteName false).Address}} + {{.PullMirror.RemoteAddress}} {{$.locale.Tr "repo.settings.mirror_settings.direction.pull"}} {{DateTime "full" .PullMirror.UpdatedUnix}} @@ -200,8 +200,7 @@ {{range .PushMirrors}} - {{$address := MirrorRemoteAddress $.Context $.Repository .GetRemoteName true}} - {{$address.Address}} + {{.RemoteAddress}} {{$.locale.Tr "repo.settings.mirror_settings.direction.push"}} {{if .LastUpdateUnix}}{{DateTime "full" .LastUpdateUnix}}{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}
{{$.locale.Tr "error"}}
{{end}} @@ -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}}