summaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
author6543 <6543@obermui.de>2021-03-01 01:47:30 +0100
committerGitHub <noreply@github.com>2021-03-01 01:47:30 +0100
commita4148c0f12fe5a93d2c9a40f24d4813bcfef4ff8 (patch)
tree92edf61ff2447e067a676832844a129050b4ec0f /routers
parente0900310c4354311362ef69d15c302c215eaa2a2 (diff)
downloadgitea-a4148c0f12fe5a93d2c9a40f24d4813bcfef4ff8.tar.gz
gitea-a4148c0f12fe5a93d2c9a40f24d4813bcfef4ff8.zip
Repository transfer has to be confirmed, if user can not create repo for new owner (#14792)
* make repo as "pending transfer" if on transfer start doer has no right to create repo in new destination * if new pending transfer ocured, create UI & Mail notifications
Diffstat (limited to 'routers')
-rw-r--r--routers/api/v1/repo/transfer.go20
-rw-r--r--routers/repo/repo.go35
-rw-r--r--routers/repo/setting.go44
-rw-r--r--routers/repo/view.go8
4 files changed, 98 insertions, 9 deletions
diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go
index 656ace032e..2e052aa4ff 100644
--- a/routers/api/v1/repo/transfer.go
+++ b/routers/api/v1/repo/transfer.go
@@ -96,17 +96,27 @@ func Transfer(ctx *context.APIContext) {
}
}
- if err = repo_service.TransferOwnership(ctx.User, newOwner, ctx.Repo.Repository, teams); err != nil {
+ if err := repo_service.StartRepositoryTransfer(ctx.User, newOwner, ctx.Repo.Repository, teams); err != nil {
+ if models.IsErrRepoTransferInProgress(err) {
+ ctx.Error(http.StatusConflict, "CreatePendingRepositoryTransfer", err)
+ return
+ }
+
+ if models.IsErrRepoAlreadyExist(err) {
+ ctx.Error(http.StatusUnprocessableEntity, "CreatePendingRepositoryTransfer", err)
+ return
+ }
+
ctx.InternalServerError(err)
return
}
- newRepo, err := models.GetRepositoryByName(newOwner.ID, ctx.Repo.Repository.Name)
- if err != nil {
- ctx.InternalServerError(err)
+ if ctx.Repo.Repository.Status == models.RepositoryPendingTransfer {
+ log.Trace("Repository transfer initiated: %s -> %s", ctx.Repo.Repository.FullName(), newOwner.Name)
+ ctx.JSON(http.StatusCreated, convert.ToRepo(ctx.Repo.Repository, models.AccessModeAdmin))
return
}
log.Trace("Repository transferred: %s -> %s", ctx.Repo.Repository.FullName(), newOwner.Name)
- ctx.JSON(http.StatusAccepted, convert.ToRepo(newRepo, models.AccessModeAdmin))
+ ctx.JSON(http.StatusAccepted, convert.ToRepo(ctx.Repo.Repository, models.AccessModeAdmin))
}
diff --git a/routers/repo/repo.go b/routers/repo/repo.go
index a8cfb9ad7c..6fa566e7d6 100644
--- a/routers/repo/repo.go
+++ b/routers/repo/repo.go
@@ -6,6 +6,7 @@
package repo
import (
+ "errors"
"fmt"
"strings"
"time"
@@ -274,6 +275,10 @@ func Action(ctx *context.Context) {
err = models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
case "unstar":
err = models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
+ case "accept_transfer":
+ err = acceptOrRejectRepoTransfer(ctx, true)
+ case "reject_transfer":
+ err = acceptOrRejectRepoTransfer(ctx, false)
case "desc": // FIXME: this is not used
if !ctx.Repo.IsOwner() {
ctx.Error(404)
@@ -293,6 +298,36 @@ func Action(ctx *context.Context) {
ctx.RedirectToFirst(ctx.Query("redirect_to"), ctx.Repo.RepoLink)
}
+func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
+ repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository)
+ if err != nil {
+ return err
+ }
+
+ if err := repoTransfer.LoadAttributes(); err != nil {
+ return err
+ }
+
+ if !repoTransfer.CanUserAcceptTransfer(ctx.User) {
+ return errors.New("user does not have enough permissions")
+ }
+
+ if accept {
+ if err := repo_service.TransferOwnership(repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams); err != nil {
+ return err
+ }
+ ctx.Flash.Success(ctx.Tr("repo.settings.transfer.success"))
+ } else {
+ if err := models.CancelRepositoryTransfer(ctx.Repo.Repository); err != nil {
+ return err
+ }
+ ctx.Flash.Success(ctx.Tr("repo.settings.transfer.rejected"))
+ }
+
+ ctx.Redirect(ctx.Repo.Repository.HTMLURL())
+ return nil
+}
+
// RedirectDownload return a file based on the following infos:
func RedirectDownload(ctx *context.Context) {
var (
diff --git a/routers/repo/setting.go b/routers/repo/setting.go
index 3e22e8804e..b35828d7b1 100644
--- a/routers/repo/setting.go
+++ b/routers/repo/setting.go
@@ -477,18 +477,54 @@ func SettingsPost(ctx *context.Context) {
ctx.Repo.GitRepo.Close()
ctx.Repo.GitRepo = nil
}
- if err = repo_service.TransferOwnership(ctx.User, newOwner, repo, nil); err != nil {
+
+ if err := repo_service.StartRepositoryTransfer(ctx.User, newOwner, repo, nil); err != nil {
if models.IsErrRepoAlreadyExist(err) {
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
+ } else if models.IsErrRepoTransferInProgress(err) {
+ ctx.RenderWithErr(ctx.Tr("repo.settings.transfer_in_progress"), tplSettingsOptions, nil)
} else {
ctx.ServerError("TransferOwnership", err)
}
+
+ return
+ }
+
+ log.Trace("Repository transfer process was started: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newOwner)
+ ctx.Flash.Success(ctx.Tr("repo.settings.transfer_started", newOwner.DisplayName()))
+ ctx.Redirect(setting.AppSubURL + "/" + ctx.Repo.Owner.Name + "/" + repo.Name + "/settings")
+
+ case "cancel_transfer":
+ if !ctx.Repo.IsOwner() {
+ ctx.Error(404)
+ return
+ }
+
+ repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository)
+ if err != nil {
+ if models.IsErrNoPendingTransfer(err) {
+ ctx.Flash.Error("repo.settings.transfer_abort_invalid")
+ ctx.Redirect(setting.AppSubURL + "/" + ctx.User.Name + "/" + repo.Name + "/settings")
+ } else {
+ ctx.ServerError("GetPendingRepositoryTransfer", err)
+ }
+
+ return
+ }
+
+ if err := repoTransfer.LoadAttributes(); err != nil {
+ ctx.ServerError("LoadRecipient", err)
+ return
+ }
+
+ if err := models.CancelRepositoryTransfer(ctx.Repo.Repository); err != nil {
+ ctx.ServerError("CancelRepositoryTransfer", err)
return
}
- log.Trace("Repository transferred: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newOwner)
- ctx.Flash.Success(ctx.Tr("repo.settings.transfer_succeed"))
- ctx.Redirect(setting.AppSubURL + "/" + newOwner.Name + "/" + repo.Name)
+ log.Trace("Repository transfer process was cancelled: %s/%s ", ctx.Repo.Owner.Name, repo.Name)
+ ctx.Flash.Success(ctx.Tr("repo.settings.transfer_abort_success", repoTransfer.Recipient.Name))
+ ctx.Redirect(setting.AppSubURL + "/" + ctx.Repo.Owner.Name + "/" + repo.Name + "/settings")
case "delete":
if !ctx.Repo.IsOwner() {
diff --git a/routers/repo/view.go b/routers/repo/view.go
index a5e3cbe3e4..39f16d183c 100644
--- a/routers/repo/view.go
+++ b/routers/repo/view.go
@@ -586,6 +586,14 @@ func Home(ctx *context.Context) {
return
}
+ if ctx.IsSigned {
+ // Set repo notification-status read if unread
+ if err := ctx.Repo.Repository.ReadBy(ctx.User.ID); err != nil {
+ ctx.ServerError("ReadBy", err)
+ return
+ }
+ }
+
var firstUnit *models.Unit
for _, repoUnit := range ctx.Repo.Units {
if repoUnit.Type == models.UnitTypeCode {