mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Fix javascript error when an anonymous user visiting migration page (#32144)
This PR fixes javascript errors when an anonymous user visits the
migration page.
It also makes task view checking more restrictive.
The router moved from `/user/task/{id}/status` to
`/username/reponame/-/migrate/status` because it's a migrate status.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
			
			
This commit is contained in:
		| @@ -179,27 +179,6 @@ func GetMigratingTask(ctx context.Context, repoID int64) (*Task, error) { | |||||||
| 	return &task, nil | 	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 | // CreateTask creates a task on database | ||||||
| func CreateTask(ctx context.Context, task *Task) error { | func CreateTask(ctx context.Context, task *Task) error { | ||||||
| 	return db.Insert(ctx, task) | 	return db.Insert(ctx, task) | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ import ( | |||||||
| 	repo_model "code.gitea.io/gitea/models/repo" | 	repo_model "code.gitea.io/gitea/models/repo" | ||||||
| 	user_model "code.gitea.io/gitea/models/user" | 	user_model "code.gitea.io/gitea/models/user" | ||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
|  | 	"code.gitea.io/gitea/modules/json" | ||||||
| 	"code.gitea.io/gitea/modules/lfs" | 	"code.gitea.io/gitea/modules/lfs" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| @@ -288,3 +289,40 @@ func MigrateCancelPost(ctx *context.Context) { | |||||||
| 	} | 	} | ||||||
| 	ctx.Redirect(ctx.Repo.Repository.Link()) | 	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, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,53 +0,0 @@ | |||||||
| // Copyright 2020 The Gitea Authors. All rights reserved. |  | ||||||
| // SPDX-License-Identifier: MIT |  | ||||||
|  |  | ||||||
| package user |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"net/http" |  | ||||||
| 	"strconv" |  | ||||||
|  |  | ||||||
| 	admin_model "code.gitea.io/gitea/models/admin" |  | ||||||
| 	"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) |  | ||||||
| 	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", |  | ||||||
| 			}) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		ctx.JSON(http.StatusInternalServerError, map[string]any{ |  | ||||||
| 			"err": err, |  | ||||||
| 		}) |  | ||||||
| 		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, |  | ||||||
| 		"repo-id":   task.RepoID, |  | ||||||
| 		"repo-name": opts.RepoName, |  | ||||||
| 		"start":     task.StartTime, |  | ||||||
| 		"end":       task.EndTime, |  | ||||||
| 	}) |  | ||||||
| } |  | ||||||
| @@ -669,7 +669,6 @@ func registerRoutes(m *web.Router) { | |||||||
| 		m.Get("/forgot_password", auth.ForgotPasswd) | 		m.Get("/forgot_password", auth.ForgotPasswd) | ||||||
| 		m.Post("/forgot_password", auth.ForgotPasswdPost) | 		m.Post("/forgot_password", auth.ForgotPasswdPost) | ||||||
| 		m.Post("/logout", auth.SignOut) | 		m.Post("/logout", auth.SignOut) | ||||||
| 		m.Get("/task/{task}", reqSignIn, user.TaskStatus) |  | ||||||
| 		m.Get("/stopwatches", reqSignIn, user.GetStopwatches) | 		m.Get("/stopwatches", reqSignIn, user.GetStopwatches) | ||||||
| 		m.Get("/search", ignExploreSignIn, user.Search) | 		m.Get("/search", ignExploreSignIn, user.Search) | ||||||
| 		m.Group("/oauth2", func() { | 		m.Group("/oauth2", func() { | ||||||
| @@ -1042,6 +1041,13 @@ func registerRoutes(m *web.Router) { | |||||||
| 	}, ignSignIn, context.UserAssignmentWeb(), context.OrgAssignment()) | 	}, ignSignIn, context.UserAssignmentWeb(), context.OrgAssignment()) | ||||||
| 	// end "/{username}/-": packages, projects, code | 	// end "/{username}/-": packages, projects, code | ||||||
|  |  | ||||||
|  | 	m.Group("/{username}/{reponame}/-", func() { | ||||||
|  | 		m.Group("/migrate", func() { | ||||||
|  | 			m.Get("/status", repo.MigrateStatus) | ||||||
|  | 		}) | ||||||
|  | 	}, ignSignIn, context.RepoAssignment, reqRepoCodeReader) | ||||||
|  | 	// end "/{username}/{reponame}/-": migrate | ||||||
|  |  | ||||||
| 	m.Group("/{username}/{reponame}/settings", func() { | 	m.Group("/{username}/{reponame}/settings", func() { | ||||||
| 		m.Group("", func() { | 		m.Group("", func() { | ||||||
| 			m.Combo("").Get(repo_setting.Settings). | 			m.Combo("").Get(repo_setting.Settings). | ||||||
|   | |||||||
| @@ -614,7 +614,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 | 	// Disable everything when the repo is being created | ||||||
| 	if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() { | 	if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() { | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| 				{{template "base/alert" .}} | 				{{template "base/alert" .}} | ||||||
| 				<div class="home"> | 				<div class="home"> | ||||||
| 					<div class="ui stackable middle very relaxed page grid"> | 					<div class="ui stackable middle very relaxed page grid"> | ||||||
| 						<div id="repo_migrating" class="sixteen wide center aligned centered column" data-migrating-task-id="{{.MigrateTask.ID}}"> | 						<div id="repo_migrating" class="sixteen wide center aligned centered column" data-migrating-repo-link="{{.Link}}"> | ||||||
| 							<div> | 							<div> | ||||||
| 								<img src="{{AssetUrlPrefix}}/img/loading.png"> | 								<img src="{{AssetUrlPrefix}}/img/loading.png"> | ||||||
| 							</div> | 							</div> | ||||||
|   | |||||||
| @@ -1,19 +1,17 @@ | |||||||
| import {hideElem, showElem} from '../utils/dom.ts'; | import {hideElem, showElem} from '../utils/dom.ts'; | ||||||
| import {GET, POST} from '../modules/fetch.ts'; | import {GET, POST} from '../modules/fetch.ts'; | ||||||
|  |  | ||||||
| const {appSubUrl} = window.config; |  | ||||||
|  |  | ||||||
| export function initRepoMigrationStatusChecker() { | export function initRepoMigrationStatusChecker() { | ||||||
|   const repoMigrating = document.querySelector('#repo_migrating'); |   const repoMigrating = document.querySelector('#repo_migrating'); | ||||||
|   if (!repoMigrating) return; |   if (!repoMigrating) return; | ||||||
|  |  | ||||||
|   document.querySelector('#repo_migrating_retry').addEventListener('click', doMigrationRetry); |   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 |   // returns true if the refresh still needs to be called after a while | ||||||
|   const refresh = async () => { |   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 |     if (res.status !== 200) return true; // continue to refresh if network error occurs | ||||||
|  |  | ||||||
|     const data = await res.json(); |     const data = await res.json(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Lunny Xiao
					Lunny Xiao