Skip to content

Commit 7cc7db7

Browse files
author
Xinyu Zhou
authored
Add option to prohibit fork if user reached maximum limit of repositories (#21848)
If user has reached the maximum limit of repositories: - Before - disallow create - allow fork without limit - This patch: - disallow create - disallow fork - Add option `ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT` (Default **true**) : enable this allow user fork repositories without maximum number limit fixed #21847 Signed-off-by: Xinyu Zhou <[email protected]>
1 parent 22a6e97 commit 7cc7db7

File tree

9 files changed

+53
-2
lines changed

9 files changed

+53
-2
lines changed

custom/conf/app.example.ini

+3
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,9 @@ ROUTER = console
957957
;; Don't allow download source archive files from UI
958958
;DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false
959959

960+
;; Allow fork repositories without maximum number limit
961+
;ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT = true
962+
960963
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
961964
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
962965
;[repository.editor]

docs/content/doc/advanced/config-cheat-sheet.en-us.md

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build
112112
- `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to adopt unadopted repositories
113113
- `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to delete unadopted repositories
114114
- `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: Don't allow download source archive files from UI
115+
- `ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT`: **true**: Allow fork repositories without maximum number limit
115116

116117
### Repository - Editor (`repository.editor`)
117118

models/user/user.go

+9
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,15 @@ func (u *User) CanEditGitHook() bool {
275275
return !setting.DisableGitHooks && (u.IsAdmin || u.AllowGitHook)
276276
}
277277

278+
// CanForkRepo returns if user login can fork a repository
279+
// It checks especially that the user can create repos, and potentially more
280+
func (u *User) CanForkRepo() bool {
281+
if setting.Repository.AllowForkWithoutMaximumLimit {
282+
return true
283+
}
284+
return u.CanCreateRepo()
285+
}
286+
278287
// CanImportLocal returns true if user can migrate repository by local path.
279288
func (u *User) CanImportLocal() bool {
280289
if !setting.ImportLocalPaths || u == nil {

modules/setting/repository.go

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var (
4848
AllowAdoptionOfUnadoptedRepositories bool
4949
AllowDeleteOfUnadoptedRepositories bool
5050
DisableDownloadSourceArchives bool
51+
AllowForkWithoutMaximumLimit bool
5152

5253
// Repository editor settings
5354
Editor struct {
@@ -160,6 +161,7 @@ var (
160161
DisableMigrations: false,
161162
DisableStars: false,
162163
DefaultBranch: "main",
164+
AllowForkWithoutMaximumLimit: true,
163165

164166
// Repository editor settings
165167
Editor: struct {

routers/api/v1/repo/fork.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func CreateFork(ctx *context.APIContext) {
141141
Description: repo.Description,
142142
})
143143
if err != nil {
144-
if repo_model.IsErrRepoAlreadyExist(err) {
144+
if repo_model.IsErrReachLimitOfRepo(err) || repo_model.IsErrRepoAlreadyExist(err) {
145145
ctx.Error(http.StatusConflict, "ForkRepository", err)
146146
} else {
147147
ctx.Error(http.StatusInternalServerError, "ForkRepository", err)

routers/web/repo/pull.go

+13
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
182182
func Fork(ctx *context.Context) {
183183
ctx.Data["Title"] = ctx.Tr("new_fork")
184184

185+
if ctx.Doer.CanForkRepo() {
186+
ctx.Data["CanForkRepo"] = true
187+
} else {
188+
maxCreationLimit := ctx.Doer.MaxCreationLimit()
189+
msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
190+
ctx.Data["Flash"] = ctx.Flash
191+
ctx.Flash.Error(msg)
192+
}
193+
185194
getForkRepository(ctx)
186195
if ctx.Written() {
187196
return
@@ -254,6 +263,10 @@ func ForkPost(ctx *context.Context) {
254263
if err != nil {
255264
ctx.Data["Err_RepoName"] = true
256265
switch {
266+
case repo_model.IsErrReachLimitOfRepo(err):
267+
maxCreationLimit := ctxUser.MaxCreationLimit()
268+
msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit)
269+
ctx.RenderWithErr(msg, tplFork, &form)
257270
case repo_model.IsErrRepoAlreadyExist(err):
258271
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form)
259272
case db.IsErrNameReserved(err):

services/repository/fork.go

+7
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ type ForkRepoOptions struct {
5151

5252
// ForkRepository forks a repository
5353
func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts ForkRepoOptions) (*repo_model.Repository, error) {
54+
// Fork is prohibited, if user has reached maximum limit of repositories
55+
if !owner.CanForkRepo() {
56+
return nil, repo_model.ErrReachLimitOfRepo{
57+
Limit: owner.MaxRepoCreation,
58+
}
59+
}
60+
5461
forkedRepo, err := repo_model.GetUserFork(ctx, opts.BaseRepo.ID, owner.ID)
5562
if err != nil {
5663
return nil, err

services/repository/fork_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"code.gitea.io/gitea/models/unittest"
1111
user_model "code.gitea.io/gitea/models/user"
1212
"code.gitea.io/gitea/modules/git"
13+
"code.gitea.io/gitea/modules/setting"
1314

1415
"github.com/stretchr/testify/assert"
1516
)
@@ -29,4 +30,19 @@ func TestForkRepository(t *testing.T) {
2930
assert.Nil(t, fork)
3031
assert.Error(t, err)
3132
assert.True(t, IsErrForkAlreadyExist(err))
33+
34+
// user not reached maximum limit of repositories
35+
assert.False(t, repo_model.IsErrReachLimitOfRepo(err))
36+
37+
// change AllowForkWithoutMaximumLimit to false for the test
38+
setting.Repository.AllowForkWithoutMaximumLimit = false
39+
// user has reached maximum limit of repositories
40+
user.MaxRepoCreation = 0
41+
fork2, err := ForkRepository(git.DefaultContext, user, user, ForkRepoOptions{
42+
BaseRepo: repo,
43+
Name: "test",
44+
Description: "test",
45+
})
46+
assert.Nil(t, fork2)
47+
assert.True(t, repo_model.IsErrReachLimitOfRepo(err))
3248
}

templates/repo/pulls/fork.tmpl

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
<div class="inline field">
6060
<label></label>
61-
<button class="ui green button">
61+
<button class="ui green button{{if not .CanForkRepo}} disabled{{end}}">
6262
{{.locale.Tr "repo.fork_repo"}}
6363
</button>
6464
</div>

0 commit comments

Comments
 (0)