diff options
author | Xinyu Zhou <i@sourcehut.net> | 2022-12-28 05:21:14 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-27 15:21:14 -0600 |
commit | 7cc7db73b922143a1288d26b39eee9e8e59f7106 (patch) | |
tree | da812b01e5953781a820f05edee52c93efef4bec | |
parent | 22a6e9759739af05a862fb5098aec0659aed2e84 (diff) | |
download | gitea-7cc7db73b922143a1288d26b39eee9e8e59f7106.tar.gz gitea-7cc7db73b922143a1288d26b39eee9e8e59f7106.zip |
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 https://github.com/go-gitea/gitea/issues/21847
Signed-off-by: Xinyu Zhou <i@sourcehut.net>
-rw-r--r-- | custom/conf/app.example.ini | 3 | ||||
-rw-r--r-- | docs/content/doc/advanced/config-cheat-sheet.en-us.md | 1 | ||||
-rw-r--r-- | models/user/user.go | 9 | ||||
-rw-r--r-- | modules/setting/repository.go | 2 | ||||
-rw-r--r-- | routers/api/v1/repo/fork.go | 2 | ||||
-rw-r--r-- | routers/web/repo/pull.go | 13 | ||||
-rw-r--r-- | services/repository/fork.go | 7 | ||||
-rw-r--r-- | services/repository/fork_test.go | 16 | ||||
-rw-r--r-- | templates/repo/pulls/fork.tmpl | 2 |
9 files changed, 53 insertions, 2 deletions
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 754eab452f..cec5e8cf03 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -957,6 +957,9 @@ ROUTER = console ;; Don't allow download source archive files from UI ;DISABLE_DOWNLOAD_SOURCE_ARCHIVES = false +;; Allow fork repositories without maximum number limit +;ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT = true + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;[repository.editor] diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 9d7a375ad3..3ccef3130c 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -112,6 +112,7 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build - `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to adopt unadopted repositories - `ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES`: **false**: Allow non-admin users to delete unadopted repositories - `DISABLE_DOWNLOAD_SOURCE_ARCHIVES`: **false**: Don't allow download source archive files from UI +- `ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT`: **true**: Allow fork repositories without maximum number limit ### Repository - Editor (`repository.editor`) diff --git a/models/user/user.go b/models/user/user.go index 71b036b06f..825223201b 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -275,6 +275,15 @@ func (u *User) CanEditGitHook() bool { return !setting.DisableGitHooks && (u.IsAdmin || u.AllowGitHook) } +// CanForkRepo returns if user login can fork a repository +// It checks especially that the user can create repos, and potentially more +func (u *User) CanForkRepo() bool { + if setting.Repository.AllowForkWithoutMaximumLimit { + return true + } + return u.CanCreateRepo() +} + // CanImportLocal returns true if user can migrate repository by local path. func (u *User) CanImportLocal() bool { if !setting.ImportLocalPaths || u == nil { diff --git a/modules/setting/repository.go b/modules/setting/repository.go index ea288d2ed2..d78b63a1f3 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -48,6 +48,7 @@ var ( AllowAdoptionOfUnadoptedRepositories bool AllowDeleteOfUnadoptedRepositories bool DisableDownloadSourceArchives bool + AllowForkWithoutMaximumLimit bool // Repository editor settings Editor struct { @@ -160,6 +161,7 @@ var ( DisableMigrations: false, DisableStars: false, DefaultBranch: "main", + AllowForkWithoutMaximumLimit: true, // Repository editor settings Editor: struct { diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go index f2cd10e711..97c1dc7ba7 100644 --- a/routers/api/v1/repo/fork.go +++ b/routers/api/v1/repo/fork.go @@ -141,7 +141,7 @@ func CreateFork(ctx *context.APIContext) { Description: repo.Description, }) if err != nil { - if repo_model.IsErrRepoAlreadyExist(err) { + if repo_model.IsErrReachLimitOfRepo(err) || repo_model.IsErrRepoAlreadyExist(err) { ctx.Error(http.StatusConflict, "ForkRepository", err) } else { ctx.Error(http.StatusInternalServerError, "ForkRepository", err) diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index bea6bfe433..8929a183ee 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -182,6 +182,15 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository { func Fork(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("new_fork") + if ctx.Doer.CanForkRepo() { + ctx.Data["CanForkRepo"] = true + } else { + maxCreationLimit := ctx.Doer.MaxCreationLimit() + msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit) + ctx.Data["Flash"] = ctx.Flash + ctx.Flash.Error(msg) + } + getForkRepository(ctx) if ctx.Written() { return @@ -254,6 +263,10 @@ func ForkPost(ctx *context.Context) { if err != nil { ctx.Data["Err_RepoName"] = true switch { + case repo_model.IsErrReachLimitOfRepo(err): + maxCreationLimit := ctxUser.MaxCreationLimit() + msg := ctx.TrN(maxCreationLimit, "repo.form.reach_limit_of_creation_1", "repo.form.reach_limit_of_creation_n", maxCreationLimit) + ctx.RenderWithErr(msg, tplFork, &form) case repo_model.IsErrRepoAlreadyExist(err): ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplFork, &form) case db.IsErrNameReserved(err): diff --git a/services/repository/fork.go b/services/repository/fork.go index 3ed0f4ffa5..ad534be887 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -51,6 +51,13 @@ type ForkRepoOptions struct { // ForkRepository forks a repository func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts ForkRepoOptions) (*repo_model.Repository, error) { + // Fork is prohibited, if user has reached maximum limit of repositories + if !owner.CanForkRepo() { + return nil, repo_model.ErrReachLimitOfRepo{ + Limit: owner.MaxRepoCreation, + } + } + forkedRepo, err := repo_model.GetUserFork(ctx, opts.BaseRepo.ID, owner.ID) if err != nil { return nil, err diff --git a/services/repository/fork_test.go b/services/repository/fork_test.go index c809ed4529..452798b25b 100644 --- a/services/repository/fork_test.go +++ b/services/repository/fork_test.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" ) @@ -29,4 +30,19 @@ func TestForkRepository(t *testing.T) { assert.Nil(t, fork) assert.Error(t, err) assert.True(t, IsErrForkAlreadyExist(err)) + + // user not reached maximum limit of repositories + assert.False(t, repo_model.IsErrReachLimitOfRepo(err)) + + // change AllowForkWithoutMaximumLimit to false for the test + setting.Repository.AllowForkWithoutMaximumLimit = false + // user has reached maximum limit of repositories + user.MaxRepoCreation = 0 + fork2, err := ForkRepository(git.DefaultContext, user, user, ForkRepoOptions{ + BaseRepo: repo, + Name: "test", + Description: "test", + }) + assert.Nil(t, fork2) + assert.True(t, repo_model.IsErrReachLimitOfRepo(err)) } diff --git a/templates/repo/pulls/fork.tmpl b/templates/repo/pulls/fork.tmpl index 28ba8e2e25..4e20642cf6 100644 --- a/templates/repo/pulls/fork.tmpl +++ b/templates/repo/pulls/fork.tmpl @@ -58,7 +58,7 @@ <div class="inline field"> <label></label> - <button class="ui green button"> + <button class="ui green button{{if not .CanForkRepo}} disabled{{end}}"> {{.locale.Tr "repo.fork_repo"}} </button> </div> |