loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow admins to fork repos even when creation limits are exhausted (#3277)

This is a continuation of #2728, with a test case added.

Fixes #2633.

I kept @zareck 's commit as is, because I believe it is correct. We can't move the check to `owner.CanForkRepo()`, because `owner` is the future owner of the forked repo, and may be an organization. We need to check the admin permission of the `doer`, like in the case of repository creation.

I verified that the test fails without the `ForkRepository` change, and passes with it.

Co-authored-by: Cassio Zareck <cassiomilczareck@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3277
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Gergely Nagy <forgejo@gergo.csillger.hu>
Co-committed-by: Gergely Nagy <forgejo@gergo.csillger.hu>

authored by

Gergely Nagy
Cassio Zareck
Gergely Nagy
and committed by
Earl Warren
ea4071ca 33d06175

+64 -1
+1 -1
services/repository/fork.go
··· 54 54 // ForkRepository forks a repository 55 55 func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts ForkRepoOptions) (*repo_model.Repository, error) { 56 56 // Fork is prohibited, if user has reached maximum limit of repositories 57 - if !owner.CanForkRepo() { 57 + if !doer.IsAdmin && !owner.CanForkRepo() { 58 58 return nil, repo_model.ErrReachLimitOfRepo{ 59 59 Limit: owner.MaxRepoCreation, 60 60 }
+63
tests/integration/api_fork_test.go
··· 5 5 package integration 6 6 7 7 import ( 8 + "fmt" 8 9 "net/http" 9 10 "net/url" 10 11 "testing" 11 12 13 + auth_model "code.gitea.io/gitea/models/auth" 14 + "code.gitea.io/gitea/models/unittest" 15 + user_model "code.gitea.io/gitea/models/user" 12 16 "code.gitea.io/gitea/modules/setting" 13 17 api "code.gitea.io/gitea/modules/structs" 14 18 "code.gitea.io/gitea/modules/test" 15 19 "code.gitea.io/gitea/routers" 16 20 "code.gitea.io/gitea/tests" 17 21 ) 22 + 23 + func TestAPIForkAsAdminIgnoringLimits(t *testing.T) { 24 + defer tests.PrepareTestEnv(t)() 25 + defer test.MockVariableValue(&setting.Repository.AllowForkWithoutMaximumLimit, false)() 26 + defer test.MockVariableValue(&setting.Repository.MaxCreationLimit, 0)() 27 + 28 + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"}) 29 + userSession := loginUser(t, user.Name) 30 + userToken := getTokenForLoggedInUser(t, userSession, auth_model.AccessTokenScopeWriteRepository) 31 + adminUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true}) 32 + adminSession := loginUser(t, adminUser.Name) 33 + adminToken := getTokenForLoggedInUser(t, adminSession, 34 + auth_model.AccessTokenScopeWriteRepository, 35 + auth_model.AccessTokenScopeWriteOrganization) 36 + 37 + originForkURL := "/api/v1/repos/user12/repo10/forks" 38 + orgName := "fork-org" 39 + 40 + // Create an organization 41 + req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{ 42 + UserName: orgName, 43 + }).AddTokenAuth(adminToken) 44 + MakeRequest(t, req, http.StatusCreated) 45 + 46 + // Create a team 47 + teamToCreate := &api.CreateTeamOption{ 48 + Name: "testers", 49 + IncludesAllRepositories: true, 50 + Permission: "write", 51 + Units: []string{"repo.code", "repo.issues"}, 52 + } 53 + 54 + req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams", orgName), &teamToCreate).AddTokenAuth(adminToken) 55 + resp := MakeRequest(t, req, http.StatusCreated) 56 + var team api.Team 57 + DecodeJSON(t, resp, &team) 58 + 59 + // Add user2 to the team 60 + req = NewRequestf(t, "PUT", "/api/v1/teams/%d/members/user2", team.ID).AddTokenAuth(adminToken) 61 + MakeRequest(t, req, http.StatusNoContent) 62 + 63 + t.Run("forking as regular user", func(t *testing.T) { 64 + defer tests.PrintCurrentTest(t)() 65 + 66 + req := NewRequestWithJSON(t, "POST", originForkURL, &api.CreateForkOption{ 67 + Organization: &orgName, 68 + }).AddTokenAuth(userToken) 69 + MakeRequest(t, req, http.StatusConflict) 70 + }) 71 + 72 + t.Run("forking as an instance admin", func(t *testing.T) { 73 + defer tests.PrintCurrentTest(t)() 74 + 75 + req := NewRequestWithJSON(t, "POST", originForkURL, &api.CreateForkOption{ 76 + Organization: &orgName, 77 + }).AddTokenAuth(adminToken) 78 + MakeRequest(t, req, http.StatusAccepted) 79 + }) 80 + } 18 81 19 82 func TestCreateForkNoLogin(t *testing.T) { 20 83 defer tests.PrepareTestEnv(t)()