mirror of
https://github.com/go-gitea/gitea
synced 2024-11-21 22:01:18 +01:00
backport #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:
parent
361221c531
commit
2e3a191097
7 changed files with 53 additions and 82 deletions
|
@ -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"
|
||||||
|
@ -284,3 +285,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.ParamsInt64("task"), ctx.Doer.ID)
|
|
||||||
if err != nil {
|
|
||||||
if admin_model.IsErrTaskDoesNotExist(err) {
|
|
||||||
ctx.JSON(http.StatusNotFound, map[string]any{
|
|
||||||
"error": "task `" + strconv.FormatInt(ctx.ParamsInt64("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,
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -667,7 +667,6 @@ func registerRoutes(m *web.Route) {
|
||||||
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() {
|
||||||
|
@ -1036,6 +1035,13 @@ func registerRoutes(m *web.Route) {
|
||||||
}, 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).
|
||||||
|
|
|
@ -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
|
// 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.js';
|
import {hideElem, showElem} from '../utils/dom.js';
|
||||||
import {GET, POST} from '../modules/fetch.js';
|
import {GET, POST} from '../modules/fetch.js';
|
||||||
|
|
||||||
const {appSubUrl} = window.config;
|
|
||||||
|
|
||||||
export function initRepoMigrationStatusChecker() {
|
export function initRepoMigrationStatusChecker() {
|
||||||
const repoMigrating = document.getElementById('repo_migrating');
|
const repoMigrating = document.getElementById('repo_migrating');
|
||||||
if (!repoMigrating) return;
|
if (!repoMigrating) return;
|
||||||
|
|
||||||
document.getElementById('repo_migrating_retry').addEventListener('click', doMigrationRetry);
|
document.getElementById('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();
|
||||||
|
|
Loading…
Reference in a new issue