gitea_hat/routers/hat/repo/transfer.go

93 lines
2.8 KiB
Go

package repo
import (
"fmt"
"net/http"
"code.gitea.io/gitea/models"
organization "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
"code.gitea.io/gitea/modules/log"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
hat_repo_service "code.gitea.io/gitea/services/repository"
)
func Transfer(ctx *context.APIContext) {
opts := web.GetForm(ctx).(*api.TransferRepoOption)
newOwner, err := user_model.GetUserByName(ctx, opts.NewOwner)
if err != nil {
if user_model.IsErrUserNotExist(err) {
ctx.Error(http.StatusNotFound, "", "The new owner does not exist or cannot be found")
return
}
ctx.InternalServerError(err)
return
}
if newOwner.Type == user_model.UserTypeOrganization {
if !ctx.Doer.IsAdmin && newOwner.Visibility == api.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) {
ctx.Error(http.StatusNotFound, "", "The new owner does ot exist or cannot be found")
return
}
}
var teams []*organization.Team
if opts.TeamIDs != nil {
if !newOwner.IsOrganization() {
ctx.Error(http.StatusUnprocessableEntity, "repoTrasfer", "Teams can only be added to organization-owned repositories")
return
}
org := convert.ToOrganization(organization.OrgFromUser(newOwner))
for _, tID := range *opts.TeamIDs {
team, err := organization.GetTeamByID(ctx, tID)
if err != nil {
ctx.Error(http.StatusUnprocessableEntity, "team", fmt.Errorf("team %d not found", tID))
return
}
if team.OrgID != org.ID {
ctx.Error(http.StatusForbidden, "team", fmt.Errorf("team %d belongs not to org %d", tID, org.ID))
return
}
teams = append(teams, team)
}
}
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
ctx.Repo.GitRepo = nil
}
oldFullName := ctx.Repo.Repository.FullName()
if err := hat_repo_service.TransferOwnership(ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil {
if models.IsErrRepoTransferInProgress(err) {
ctx.Error(http.StatusConflict, "TransferOwnership", err)
return
}
if repo_model.IsErrRepoAlreadyExist(err) {
ctx.Error(http.StatusUnprocessableEntity, "TransferOwnership", err)
return
}
ctx.InternalServerError(err)
return
}
if ctx.Repo.Repository.Status == repo_model.RepositoryPendingTransfer {
log.Trace("Repository transfer initiated: %s -> %s", oldFullName, ctx.Repo.Repository.FullName())
ctx.JSON(http.StatusCreated, convert.ToRepo(ctx.Repo.Repository, perm.AccessModeAdmin))
}
log.Trace("Repository transferred: %s -> %s", oldFullName, ctx.Repo.Repository.FullName())
ctx.JSON(http.StatusAccepted, convert.ToRepo(ctx.Repo.Repository, perm.AccessModeAdmin))
}