1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo.git synced 2024-12-22 12:54:53 -05:00

fix: don't show private forks in forks list

- If a repository is forked to a private or limited user/organization,
the fork should not be visible in the list of forks depending on the
doer requesting the list of forks.
- Added integration testing for web and API route.

(cherry picked from commit 061abe6004)
This commit is contained in:
Gusted 2024-11-02 20:55:30 +01:00 committed by Earl Warren
parent 656351d028
commit 7480b6072f
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
5 changed files with 88 additions and 11 deletions

View file

@ -7,6 +7,7 @@ import (
"context" "context"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"xorm.io/builder" "xorm.io/builder"
@ -54,9 +55,9 @@ func GetUserFork(ctx context.Context, repoID, userID int64) (*Repository, error)
return &forkedRepo, nil return &forkedRepo, nil
} }
// GetForks returns all the forks of the repository // GetForks returns all the forks of the repository that are visible to the user.
func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions) ([]*Repository, error) { func GetForks(ctx context.Context, repo *Repository, user *user_model.User, listOptions db.ListOptions) ([]*Repository, int64, error) {
sess := db.GetEngine(ctx) sess := db.GetEngine(ctx).Where(AccessibleRepositoryCondition(user, unit.TypeInvalid))
var forks []*Repository var forks []*Repository
if listOptions.Page == 0 { if listOptions.Page == 0 {
@ -66,7 +67,8 @@ func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions)
sess = db.SetSessionPagination(sess, &listOptions) sess = db.SetSessionPagination(sess, &listOptions)
} }
return forks, sess.Find(&forks, &Repository{ForkID: repo.ID}) count, err := sess.FindAndCount(&forks, &Repository{ForkID: repo.ID})
return forks, count, err
} }
// IncrementRepoForkNum increment repository fork number // IncrementRepoForkNum increment repository fork number

View file

@ -55,7 +55,7 @@ func ListForks(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
forks, err := repo_model.GetForks(ctx, ctx.Repo.Repository, utils.GetListOptions(ctx)) forks, total, err := repo_model.GetForks(ctx, ctx.Repo.Repository, ctx.Doer, utils.GetListOptions(ctx))
if err != nil { if err != nil {
ctx.Error(http.StatusInternalServerError, "GetForks", err) ctx.Error(http.StatusInternalServerError, "GetForks", err)
return return
@ -70,7 +70,7 @@ func ListForks(ctx *context.APIContext) {
apiForks[i] = convert.ToRepo(ctx, fork, permission) apiForks[i] = convert.ToRepo(ctx, fork, permission)
} }
ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumForks)) ctx.SetTotalCountHeader(total)
ctx.JSON(http.StatusOK, apiForks) ctx.JSON(http.StatusOK, apiForks)
} }

View file

@ -1221,11 +1221,8 @@ func Forks(ctx *context.Context) {
page = 1 page = 1
} }
pager := context.NewPagination(ctx.Repo.Repository.NumForks, setting.MaxForksPerPage, page, 5) forks, total, err := repo_model.GetForks(ctx, ctx.Repo.Repository, ctx.Doer, db.ListOptions{
ctx.Data["Page"] = pager Page: page,
forks, err := repo_model.GetForks(ctx, ctx.Repo.Repository, db.ListOptions{
Page: pager.Paginater.Current(),
PageSize: setting.MaxForksPerPage, PageSize: setting.MaxForksPerPage,
}) })
if err != nil { if err != nil {
@ -1233,6 +1230,9 @@ func Forks(ctx *context.Context) {
return return
} }
pager := context.NewPagination(int(total), setting.MaxForksPerPage, page, 5)
ctx.Data["Page"] = pager
for _, fork := range forks { for _, fork := range forks {
if err = fork.LoadOwner(ctx); err != nil { if err = fork.LoadOwner(ctx); err != nil {
ctx.ServerError("LoadOwner", err) ctx.ServerError("LoadOwner", err)

View file

@ -18,6 +18,8 @@ import (
"code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/routers" "code.gitea.io/gitea/routers"
"code.gitea.io/gitea/tests" "code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
) )
func TestAPIForkAsAdminIgnoringLimits(t *testing.T) { func TestAPIForkAsAdminIgnoringLimits(t *testing.T) {
@ -108,3 +110,44 @@ func TestAPIDisabledForkRepo(t *testing.T) {
}) })
}) })
} }
func TestAPIForkListPrivateRepo(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user5")
token := getTokenForLoggedInUser(t, session,
auth_model.AccessTokenScopeWriteRepository,
auth_model.AccessTokenScopeWriteOrganization)
org23 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23, Visibility: api.VisibleTypePrivate})
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{
Organization: &org23.Name,
}).AddTokenAuth(token)
MakeRequest(t, req, http.StatusAccepted)
t.Run("Anomynous", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks")
resp := MakeRequest(t, req, http.StatusOK)
var forks []*api.Repository
DecodeJSON(t, resp, &forks)
assert.Empty(t, forks)
assert.EqualValues(t, "0", resp.Header().Get("X-Total-Count"))
})
t.Run("Logged in", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks").AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
var forks []*api.Repository
DecodeJSON(t, resp, &forks)
assert.Len(t, forks, 1)
assert.EqualValues(t, "1", resp.Header().Get("X-Total-Count"))
})
}

View file

@ -17,6 +17,7 @@ import (
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/routers" "code.gitea.io/gitea/routers"
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
@ -238,3 +239,34 @@ func TestRepoForkToOrg(t *testing.T) {
}) })
}) })
} }
func TestForkListPrivateRepo(t *testing.T) {
forkItemSelector := ".tw-flex.tw-items-center.tw-py-2"
onGiteaRun(t, func(t *testing.T, u *url.URL) {
session := loginUser(t, "user5")
org23 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23, Visibility: structs.VisibleTypePrivate})
testRepoFork(t, session, "user2", "repo1", org23.Name, "repo1")
t.Run("Anomynous", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/user2/repo1/forks")
resp := MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
htmlDoc.AssertElement(t, forkItemSelector, false)
})
t.Run("Logged in", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", "/user2/repo1/forks")
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
htmlDoc.AssertElement(t, forkItemSelector, true)
})
})
}