mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-31 10:22:17 +00:00
fix(repo): honor ALLOW_FORK_INTO_SAME_OWNER for organizations (#40025)
With `[repository] ALLOW_FORK_INTO_SAME_OWNER = true` a user can fork their own repository, but an organization still cannot fork a repository it owns. The fork button check and the owner list on the fork page compared the organization with the repository owner directly instead of asking `CanUserForkBetweenOwners`, and the walk over parent repositories dropped the owning organization whenever the setting was on. Organizations now follow the setting the same way users already do, and nothing changes when it is off. Fixes https://github.com/go-gitea/gitea/issues/40021 Assisted-by: Claude Code:claude-opus-5-5
This commit is contained in:
1 parent
eb3bc196ec
commit
140fac63e2
4 files changed
+42
-10
No files matched your search
@@ -35,7 +35,7 @@ func CanUserForkRepo(ctx context.Context, user *user_model.User, repo *repo_mode
|
||||
return false, err
|
||||
}
|
||||
for _, org := range ownedOrgs {
|
||||
if repo.OwnerID != org.ID && !repo_model.HasForkedRepo(ctx, org.ID, repo.ID) {
|
||||
if CanUserForkBetweenOwners(repo.OwnerID, org.ID) && !repo_model.HasForkedRepo(ctx, org.ID, repo.ID) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@ package repository
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.dev/models/db"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/test"
|
||||
|
||||
@@ -13,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
func TestCanUserForkBetweenOwners(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.Repository.AllowForkIntoSameOwner)
|
||||
defer test.MockVariableValue(&setting.Repository.AllowForkIntoSameOwner)()
|
||||
|
||||
setting.Repository.AllowForkIntoSameOwner = true
|
||||
assert.True(t, CanUserForkBetweenOwners(1, 1))
|
||||
@@ -23,3 +27,26 @@ func TestCanUserForkBetweenOwners(t *testing.T) {
|
||||
assert.False(t, CanUserForkBetweenOwners(1, 1))
|
||||
assert.True(t, CanUserForkBetweenOwners(1, 2))
|
||||
}
|
||||
|
||||
func TestCanUserForkRepoIntoOwningOrg(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
defer test.MockVariableValue(&setting.Repository.AllowForkIntoSameOwner)()
|
||||
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
||||
// user2's own fork leaves org3, the owner, as the only target
|
||||
assert.NoError(t, db.Insert(t.Context(), &repo_model.Repository{
|
||||
OwnerID: 2, Name: "repo3-fork", LowerName: "repo3-fork",
|
||||
IsFork: true, ForkID: 3,
|
||||
}))
|
||||
|
||||
setting.Repository.AllowForkIntoSameOwner = true
|
||||
ok, err := CanUserForkRepo(t.Context(), user2, repo3)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, ok)
|
||||
|
||||
setting.Repository.AllowForkIntoSameOwner = false
|
||||
ok, err = CanUserForkRepo(t.Context(), user2, repo3)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, ok)
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
|
||||
"gitea.dev/models/db"
|
||||
git_model "gitea.dev/models/git"
|
||||
@@ -60,7 +61,7 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
|
||||
}
|
||||
var orgs []*organization.Organization
|
||||
for _, org := range ownedOrgs {
|
||||
if forkRepo.OwnerID != org.ID && !repo_model.HasForkedRepo(ctx, org.ID, forkRepo.ID) {
|
||||
if repository.CanUserForkBetweenOwners(forkRepo.OwnerID, org.ID) && !repo_model.HasForkedRepo(ctx, org.ID, forkRepo.ID) {
|
||||
orgs = append(orgs, org)
|
||||
}
|
||||
}
|
||||
@@ -69,14 +70,10 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
|
||||
for {
|
||||
if !repository.CanUserForkBetweenOwners(ctx.Doer.ID, traverseParentRepo.OwnerID) {
|
||||
canForkToUser = false
|
||||
} else {
|
||||
for i, org := range orgs {
|
||||
if org.ID == traverseParentRepo.OwnerID {
|
||||
orgs = append(orgs[:i], orgs[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
orgs = slices.DeleteFunc(orgs, func(org *organization.Organization) bool {
|
||||
return !repository.CanUserForkBetweenOwners(org.ID, traverseParentRepo.OwnerID)
|
||||
})
|
||||
|
||||
if !traverseParentRepo.IsFork {
|
||||
break
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
org_model "gitea.dev/models/organization"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/test"
|
||||
org_service "gitea.dev/services/org"
|
||||
@@ -80,6 +81,13 @@ func TestRepoForkToOrg(t *testing.T) {
|
||||
assert.False(t, exists, "Forking should not be allowed anymore")
|
||||
}
|
||||
|
||||
func TestRepoForkIntoSameOrg(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
defer test.MockVariableValue(&setting.Repository.AllowForkIntoSameOwner, true)()
|
||||
session := loginUser(t, "user2")
|
||||
testRepoFork(t, session, "org3", "repo3", "org3", "repo3-fork", "")
|
||||
}
|
||||
|
||||
func TestForkListLimitedAndPrivateRepos(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
forkItemSelector := ".fork-list .item"
|
||||
|
||||
Reference in new issue
Block a user