Skip to content

Commit edef62e

Browse files
authored
Backport: Repo Transfer permission checks (#14792) (#14794)
* Backport: Repo Transfer permission checks (#14792) * update tests
1 parent cdff144 commit edef62e

File tree

4 files changed

+39
-3
lines changed

4 files changed

+39
-3
lines changed

integrations/api_repo_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ func TestAPIRepoTransfer(t *testing.T) {
445445
expectedStatus int
446446
}{
447447
{ctxUserID: 1, newOwner: "user2", teams: nil, expectedStatus: http.StatusAccepted},
448-
{ctxUserID: 2, newOwner: "user1", teams: nil, expectedStatus: http.StatusAccepted},
448+
{ctxUserID: 2, newOwner: "user1", teams: nil, expectedStatus: http.StatusForbidden},
449449
{ctxUserID: 2, newOwner: "user6", teams: nil, expectedStatus: http.StatusForbidden},
450450
{ctxUserID: 1, newOwner: "user2", teams: &[]int64{2}, expectedStatus: http.StatusUnprocessableEntity},
451451
{ctxUserID: 1, newOwner: "user3", teams: &[]int64{5}, expectedStatus: http.StatusForbidden},

routers/api/v1/repo/transfer.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,12 @@ func Transfer(ctx *context.APIContext, opts api.TransferRepoOption) {
9393
}
9494
}
9595

96-
if err = repo_service.TransferOwnership(ctx.User, newOwner, ctx.Repo.Repository, teams); err != nil {
96+
if err = repo_service.StartRepositoryTransfer(ctx.User, newOwner, ctx.Repo.Repository, teams); err != nil {
97+
if models.IsErrCancelled(err) {
98+
ctx.Error(http.StatusForbidden, "transfer", "user has no right to create repo for new owner")
99+
return
100+
}
101+
97102
ctx.InternalServerError(err)
98103
return
99104
}

routers/repo/setting.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,9 +475,12 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
475475
ctx.Repo.GitRepo.Close()
476476
ctx.Repo.GitRepo = nil
477477
}
478-
if err = repo_service.TransferOwnership(ctx.User, newOwner, repo, nil); err != nil {
478+
if err = repo_service.StartRepositoryTransfer(ctx.User, newOwner, repo, nil); err != nil {
479479
if models.IsErrRepoAlreadyExist(err) {
480480
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
481+
} else if models.IsErrCancelled(err) {
482+
// this err msg is not translated, since it was introduced in a backport
483+
ctx.RenderWithErr("user has no right to create repo for new owner", tplSettingsOptions, nil)
481484
} else {
482485
ctx.ServerError("TransferOwnership", err)
483486
}

services/repository/transfer.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,31 @@ func ChangeRepositoryName(doer *models.User, repo *models.Repository, newRepoNam
7272

7373
return nil
7474
}
75+
76+
// StartRepositoryTransfer transfer a repo from one owner to a new one.
77+
// it make repository into pending transfer state, if doer can not create repo for new owner.
78+
func StartRepositoryTransfer(doer, newOwner *models.User, repo *models.Repository, teams []*models.Team) error {
79+
if repo.Status != models.RepositoryReady {
80+
return fmt.Errorf("repository is not ready for transfer")
81+
}
82+
83+
// Admin is always allowed to transfer
84+
if doer.IsAdmin {
85+
return TransferOwnership(doer, newOwner, repo, teams)
86+
}
87+
88+
// If new owner is an org and user can create repos he can transfer directly too
89+
if newOwner.IsOrganization() {
90+
allowed, err := models.CanCreateOrgRepo(newOwner.ID, doer.ID)
91+
if err != nil {
92+
return err
93+
}
94+
if allowed {
95+
return TransferOwnership(doer, newOwner, repo, teams)
96+
}
97+
}
98+
99+
// Block Transfer, new feature will come in v1.14.0
100+
// https://github.com/go-gitea/gitea/pull/14792
101+
return models.ErrCancelled{}
102+
}

0 commit comments

Comments
 (0)