From f351b218c08950c8780288476919b958fee22e14 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 26 Sep 2024 15:12:13 -0700 Subject: [PATCH 1/9] Fix javascript error when an anonymous user visiting migration page --- web_src/js/features/repo-migrate.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web_src/js/features/repo-migrate.ts b/web_src/js/features/repo-migrate.ts index dc361779409b6..5e1770f9ba28f 100644 --- a/web_src/js/features/repo-migrate.ts +++ b/web_src/js/features/repo-migrate.ts @@ -7,7 +7,10 @@ export function initRepoMigrationStatusChecker() { const repoMigrating = document.querySelector('#repo_migrating'); if (!repoMigrating) return; - document.querySelector('#repo_migrating_retry').addEventListener('click', doMigrationRetry); + const retryBtn = document.querySelector('#repo_migrating_retry'); + if (retryBtn) { + retryBtn.addEventListener('click', doMigrationRetry); + } const task = repoMigrating.getAttribute('data-migrating-task-id'); From e0a9e2537f1afde26fe3ccb28ec0433601cd1812 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 27 Sep 2024 00:23:31 -0700 Subject: [PATCH 2/9] Fix more bugs when view migrating repository --- routers/web/user/task.go | 33 +++++++++++++++++++++++------ routers/web/web.go | 2 +- web_src/js/features/repo-migrate.ts | 5 +---- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/routers/web/user/task.go b/routers/web/user/task.go index 475ef16212f0b..ca2a1c07fcd49 100644 --- a/routers/web/user/task.go +++ b/routers/web/user/task.go @@ -8,13 +8,15 @@ import ( "strconv" admin_model "code.gitea.io/gitea/models/admin" + access_model "code.gitea.io/gitea/models/perm/access" + "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/services/context" ) // TaskStatus returns task's status func TaskStatus(ctx *context.Context) { - task, opts, err := admin_model.GetMigratingTaskByID(ctx, ctx.PathParamInt64("task"), ctx.Doer.ID) + task, _, err := admin_model.GetMigratingTaskByID(ctx, ctx.PathParamInt64("task"), 0) if err != nil { if admin_model.IsErrTaskDoesNotExist(err) { ctx.JSON(http.StatusNotFound, map[string]any{ @@ -28,6 +30,27 @@ func TaskStatus(ctx *context.Context) { return } + if err := task.LoadRepo(ctx); err != nil { + ctx.JSON(http.StatusInternalServerError, map[string]any{ + "err": err, + }) + return + } + + perm, err := access_model.GetUserRepoPermission(ctx, task.Repo, ctx.Doer) + if err != nil { + ctx.JSON(http.StatusInternalServerError, map[string]any{ + "err": err, + }) + return + } + if !perm.CanRead(unit.TypeCode) { + ctx.JSON(http.StatusForbidden, map[string]any{ + "error": "you do not have access to this task", + }) + return + } + message := task.Message if task.Message != "" && task.Message[0] == '{' { @@ -43,11 +66,7 @@ func TaskStatus(ctx *context.Context) { } ctx.JSON(http.StatusOK, map[string]any{ - "status": task.Status, - "message": message, - "repo-id": task.RepoID, - "repo-name": opts.RepoName, - "start": task.StartTime, - "end": task.EndTime, + "status": task.Status, + "message": message, }) } diff --git a/routers/web/web.go b/routers/web/web.go index af46c36fe7d2b..a3e323f40a8b3 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -669,7 +669,7 @@ func registerRoutes(m *web.Router) { m.Get("/forgot_password", auth.ForgotPasswd) m.Post("/forgot_password", auth.ForgotPasswdPost) m.Post("/logout", auth.SignOut) - m.Get("/task/{task}", reqSignIn, user.TaskStatus) + m.Get("/task/{task}", user.TaskStatus) m.Get("/stopwatches", reqSignIn, user.GetStopwatches) m.Get("/search", ignExploreSignIn, user.Search) m.Group("/oauth2", func() { diff --git a/web_src/js/features/repo-migrate.ts b/web_src/js/features/repo-migrate.ts index 5e1770f9ba28f..4a95a34e5cf67 100644 --- a/web_src/js/features/repo-migrate.ts +++ b/web_src/js/features/repo-migrate.ts @@ -7,10 +7,7 @@ export function initRepoMigrationStatusChecker() { const repoMigrating = document.querySelector('#repo_migrating'); if (!repoMigrating) return; - const retryBtn = document.querySelector('#repo_migrating_retry'); - if (retryBtn) { - retryBtn.addEventListener('click', doMigrationRetry); - } + document.querySelector('#repo_migrating_retry')?.addEventListener('click', doMigrationRetry); const task = repoMigrating.getAttribute('data-migrating-task-id'); From 8d067d814114b928fff969f3cca2ac49f8be0968 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 27 Sep 2024 11:21:38 -0700 Subject: [PATCH 3/9] make the error more safe --- routers/web/user/task.go | 17 ++++++++++------- services/context/context.go | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/routers/web/user/task.go b/routers/web/user/task.go index ca2a1c07fcd49..a49126cf80f81 100644 --- a/routers/web/user/task.go +++ b/routers/web/user/task.go @@ -5,12 +5,12 @@ package user import ( "net/http" - "strconv" admin_model "code.gitea.io/gitea/models/admin" access_model "code.gitea.io/gitea/models/perm/access" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/services/context" ) @@ -20,33 +20,36 @@ func TaskStatus(ctx *context.Context) { if err != nil { if admin_model.IsErrTaskDoesNotExist(err) { ctx.JSON(http.StatusNotFound, map[string]any{ - "error": "task `" + strconv.FormatInt(ctx.PathParamInt64("task"), 10) + "` does not exist", + "err": "task does not exist or you do not have access to this task", }) return } + log.Error("GetMigratingTaskByID: %v", err) ctx.JSON(http.StatusInternalServerError, map[string]any{ - "err": err, + "err": http.StatusText(http.StatusInternalServerError), }) return } if err := task.LoadRepo(ctx); err != nil { + log.Error("LoadRepo: %v", err) ctx.JSON(http.StatusInternalServerError, map[string]any{ - "err": err, + "err": http.StatusText(http.StatusInternalServerError), }) return } perm, err := access_model.GetUserRepoPermission(ctx, task.Repo, ctx.Doer) if err != nil { + log.Error("LoadRepo: %v", err) ctx.JSON(http.StatusInternalServerError, map[string]any{ - "err": err, + "err": http.StatusText(http.StatusInternalServerError), }) return } if !perm.CanRead(unit.TypeCode) { - ctx.JSON(http.StatusForbidden, map[string]any{ - "error": "you do not have access to this task", + ctx.JSON(http.StatusNotFound, map[string]any{ + "err": "task does not exist or you do not have access to this task", }) return } diff --git a/services/context/context.go b/services/context/context.go index 42f7c3d9d1d8a..cf8e6875bda2f 100644 --- a/services/context/context.go +++ b/services/context/context.go @@ -256,3 +256,4 @@ func (ctx *Context) JSONError(msg any) { panic(fmt.Sprintf("unsupported type: %T", msg)) } } + From ba36164593a413fe15f26959de583f43f5c9cda2 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 27 Sep 2024 12:54:35 -0700 Subject: [PATCH 4/9] Fix lint --- services/context/context.go | 1 - 1 file changed, 1 deletion(-) diff --git a/services/context/context.go b/services/context/context.go index cf8e6875bda2f..42f7c3d9d1d8a 100644 --- a/services/context/context.go +++ b/services/context/context.go @@ -256,4 +256,3 @@ func (ctx *Context) JSONError(msg any) { panic(fmt.Sprintf("unsupported type: %T", msg)) } } - From 4ac892d41bb5c691250bd5c065e8a68ea74cdabe Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 28 Sep 2024 21:00:15 -0700 Subject: [PATCH 5/9] Check task id is zero --- routers/web/user/task.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/routers/web/user/task.go b/routers/web/user/task.go index a49126cf80f81..436163672624f 100644 --- a/routers/web/user/task.go +++ b/routers/web/user/task.go @@ -16,7 +16,14 @@ import ( // TaskStatus returns task's status func TaskStatus(ctx *context.Context) { - task, _, err := admin_model.GetMigratingTaskByID(ctx, ctx.PathParamInt64("task"), 0) + taskID := ctx.PathParamInt64("task") + if taskID <= 0 { + ctx.JSON(http.StatusBadRequest, map[string]any{ + "err": "invalid task ID", + }) + return + } + task, _, err := admin_model.GetMigratingTaskByID(ctx, taskID, 0) if err != nil { if admin_model.IsErrTaskDoesNotExist(err) { ctx.JSON(http.StatusNotFound, map[string]any{ From 54b446221cbbb0e0ea89af1997152f5ce0bec3c9 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 29 Sep 2024 19:43:16 -0700 Subject: [PATCH 6/9] refactor the router --- models/admin/task.go | 21 ------- routers/web/repo/migrate.go | 38 +++++++++++++ routers/web/user/task.go | 82 --------------------------- routers/web/web.go | 9 ++- templates/repo/migrate/migrating.tmpl | 2 +- web_src/js/features/repo-migrate.ts | 6 +- 6 files changed, 49 insertions(+), 109 deletions(-) delete mode 100644 routers/web/user/task.go diff --git a/models/admin/task.go b/models/admin/task.go index c8bc95f981425..10f8e6d57046d 100644 --- a/models/admin/task.go +++ b/models/admin/task.go @@ -179,27 +179,6 @@ func GetMigratingTask(ctx context.Context, repoID int64) (*Task, error) { return &task, nil } -// GetMigratingTaskByID returns the migrating task by repo's id -func GetMigratingTaskByID(ctx context.Context, id, doerID int64) (*Task, *migration.MigrateOptions, error) { - task := Task{ - ID: id, - DoerID: doerID, - Type: structs.TaskTypeMigrateRepo, - } - has, err := db.GetEngine(ctx).Get(&task) - if err != nil { - return nil, nil, err - } else if !has { - return nil, nil, ErrTaskDoesNotExist{id, 0, task.Type} - } - - var opts migration.MigrateOptions - if err := json.Unmarshal([]byte(task.PayloadContent), &opts); err != nil { - return nil, nil, err - } - return &task, &opts, nil -} - // CreateTask creates a task on database func CreateTask(ctx context.Context, task *Task) error { return db.Insert(ctx, task) diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go index 31a65c65ea26a..b37836800e6af 100644 --- a/routers/web/repo/migrate.go +++ b/routers/web/repo/migrate.go @@ -21,6 +21,7 @@ import ( "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/migrations" @@ -288,3 +289,40 @@ func MigrateCancelPost(ctx *context.Context) { } ctx.Redirect(ctx.Repo.Repository.Link()) } + +// MigrateStatus returns migrate task's status +func MigrateStatus(ctx *context.Context) { + task, err := admin_model.GetMigratingTask(ctx, ctx.Repo.Repository.ID) + if err != nil { + if admin_model.IsErrTaskDoesNotExist(err) { + ctx.JSON(http.StatusNotFound, map[string]any{ + "err": "task does not exist or you do not have access to this task", + }) + return + } + log.Error("GetMigratingTask: %v", err) + ctx.JSON(http.StatusInternalServerError, map[string]any{ + "err": http.StatusText(http.StatusInternalServerError), + }) + return + } + + message := task.Message + + if task.Message != "" && task.Message[0] == '{' { + // assume message is actually a translatable string + var translatableMessage admin_model.TranslatableMessage + if err := json.Unmarshal([]byte(message), &translatableMessage); err != nil { + translatableMessage = admin_model.TranslatableMessage{ + Format: "migrate.migrating_failed.error", + Args: []any{task.Message}, + } + } + message = ctx.Locale.TrString(translatableMessage.Format, translatableMessage.Args...) + } + + ctx.JSON(http.StatusOK, map[string]any{ + "status": task.Status, + "message": message, + }) +} diff --git a/routers/web/user/task.go b/routers/web/user/task.go deleted file mode 100644 index 436163672624f..0000000000000 --- a/routers/web/user/task.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2020 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package user - -import ( - "net/http" - - admin_model "code.gitea.io/gitea/models/admin" - access_model "code.gitea.io/gitea/models/perm/access" - "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/services/context" -) - -// TaskStatus returns task's status -func TaskStatus(ctx *context.Context) { - taskID := ctx.PathParamInt64("task") - if taskID <= 0 { - ctx.JSON(http.StatusBadRequest, map[string]any{ - "err": "invalid task ID", - }) - return - } - task, _, err := admin_model.GetMigratingTaskByID(ctx, taskID, 0) - if err != nil { - if admin_model.IsErrTaskDoesNotExist(err) { - ctx.JSON(http.StatusNotFound, map[string]any{ - "err": "task does not exist or you do not have access to this task", - }) - return - } - log.Error("GetMigratingTaskByID: %v", err) - ctx.JSON(http.StatusInternalServerError, map[string]any{ - "err": http.StatusText(http.StatusInternalServerError), - }) - return - } - - if err := task.LoadRepo(ctx); err != nil { - log.Error("LoadRepo: %v", err) - ctx.JSON(http.StatusInternalServerError, map[string]any{ - "err": http.StatusText(http.StatusInternalServerError), - }) - return - } - - perm, err := access_model.GetUserRepoPermission(ctx, task.Repo, ctx.Doer) - if err != nil { - log.Error("LoadRepo: %v", err) - ctx.JSON(http.StatusInternalServerError, map[string]any{ - "err": http.StatusText(http.StatusInternalServerError), - }) - return - } - if !perm.CanRead(unit.TypeCode) { - ctx.JSON(http.StatusNotFound, map[string]any{ - "err": "task does not exist or you do not have access to this task", - }) - return - } - - message := task.Message - - if task.Message != "" && task.Message[0] == '{' { - // assume message is actually a translatable string - var translatableMessage admin_model.TranslatableMessage - if err := json.Unmarshal([]byte(message), &translatableMessage); err != nil { - translatableMessage = admin_model.TranslatableMessage{ - Format: "migrate.migrating_failed.error", - Args: []any{task.Message}, - } - } - message = ctx.Locale.TrString(translatableMessage.Format, translatableMessage.Args...) - } - - ctx.JSON(http.StatusOK, map[string]any{ - "status": task.Status, - "message": message, - }) -} diff --git a/routers/web/web.go b/routers/web/web.go index a3e323f40a8b3..145dcd244f635 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -669,7 +669,6 @@ func registerRoutes(m *web.Router) { m.Get("/forgot_password", auth.ForgotPasswd) m.Post("/forgot_password", auth.ForgotPasswdPost) m.Post("/logout", auth.SignOut) - m.Get("/task/{task}", user.TaskStatus) m.Get("/stopwatches", reqSignIn, user.GetStopwatches) m.Get("/search", ignExploreSignIn, user.Search) m.Group("/oauth2", func() { @@ -1042,6 +1041,14 @@ func registerRoutes(m *web.Router) { }, ignSignIn, context.UserAssignmentWeb(), context.OrgAssignment()) // end "/{username}/-": packages, projects, code + m.Group("/{username}/{reponame}/-", func() { + m.Group("/migrate", func() { + m.Get("/status", repo.MigrateStatus) + }) + }, + ignSignIn, context.RepoAssignment, reqRepoCodeReader, context.RepoRef()) + // end "/{username}/{reponame}/-": migrate + m.Group("/{username}/{reponame}/settings", func() { m.Group("", func() { m.Combo("").Get(repo_setting.Settings). diff --git a/templates/repo/migrate/migrating.tmpl b/templates/repo/migrate/migrating.tmpl index ed03db2ebd7ab..bc07b488f2427 100644 --- a/templates/repo/migrate/migrating.tmpl +++ b/templates/repo/migrate/migrating.tmpl @@ -7,7 +7,7 @@ {{template "base/alert" .}}
-
+
diff --git a/web_src/js/features/repo-migrate.ts b/web_src/js/features/repo-migrate.ts index 4a95a34e5cf67..b75289feec9f1 100644 --- a/web_src/js/features/repo-migrate.ts +++ b/web_src/js/features/repo-migrate.ts @@ -1,19 +1,17 @@ import {hideElem, showElem} from '../utils/dom.ts'; import {GET, POST} from '../modules/fetch.ts'; -const {appSubUrl} = window.config; - export function initRepoMigrationStatusChecker() { const repoMigrating = document.querySelector('#repo_migrating'); if (!repoMigrating) return; document.querySelector('#repo_migrating_retry')?.addEventListener('click', doMigrationRetry); - const task = repoMigrating.getAttribute('data-migrating-task-id'); + const repoLink = repoMigrating.getAttribute('data-migrating-repo-link'); // returns true if the refresh still needs to be called after a while const refresh = async () => { - const res = await GET(`${appSubUrl}/user/task/${task}`); + const res = await GET(`${repoLink}/-/migrate/status`); if (res.status !== 200) return true; // continue to refresh if network error occurs const data = await res.json(); From 1f5279ca859e8e15f83cc5da39ffef84b91faed9 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 30 Sep 2024 13:51:40 +0800 Subject: [PATCH 7/9] Update routers/web/web.go Co-authored-by: wxiaoguang --- routers/web/web.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/routers/web/web.go b/routers/web/web.go index 145dcd244f635..69258bca1818b 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1045,8 +1045,7 @@ func registerRoutes(m *web.Router) { m.Group("/migrate", func() { m.Get("/status", repo.MigrateStatus) }) - }, - ignSignIn, context.RepoAssignment, reqRepoCodeReader, context.RepoRef()) + }, ignSignIn, context.RepoAssignment, reqRepoCodeReader) // end "/{username}/{reponame}/-": migrate m.Group("/{username}/{reponame}/settings", func() { From 3feda5383fd3add4add548bccb693e0bf815277c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 1 Oct 2024 20:58:44 -0700 Subject: [PATCH 8/9] Fix bug --- services/context/repo.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/context/repo.go b/services/context/repo.go index e0d3a0bfd3e43..adf793d6a1cfc 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -607,7 +607,10 @@ func RepoAssignment(ctx *Context) context.CancelFunc { } } - isHomeOrSettings := ctx.Link == ctx.Repo.RepoLink || ctx.Link == ctx.Repo.RepoLink+"/settings" || strings.HasPrefix(ctx.Link, ctx.Repo.RepoLink+"/settings/") + isHomeOrSettings := ctx.Link == ctx.Repo.RepoLink || + ctx.Link == ctx.Repo.RepoLink+"/settings" || + strings.HasPrefix(ctx.Link, ctx.Repo.RepoLink+"/settings/") || + ctx.Link == ctx.Repo.RepoLink+"/-/migrate/status" // Disable everything when the repo is being created if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() { From b08da8406a3a6e082414a4cb0bb283d1e12da14d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 1 Oct 2024 21:06:40 -0700 Subject: [PATCH 9/9] Fix lint --- routers/web/repo/migrate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go index b37836800e6af..3eaf05f38335c 100644 --- a/routers/web/repo/migrate.go +++ b/routers/web/repo/migrate.go @@ -15,13 +15,13 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" - "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/migrations"