mirror of
https://github.com/go-gitea/gitea
synced 2024-12-22 16:44:26 +00:00
Refactor find forks and fix possible bugs that weak permissions check (#32528)
- Move models/GetForks to services/FindForks - Add doer as a parameter of FindForks to check permissions - Slight performance optimization for get forks API with batch loading of repository units - Add tests for forking repository to organizations --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
parent
f122aaf9ff
commit
4f879a00df
@ -54,21 +54,6 @@ func GetUserFork(ctx context.Context, repoID, userID int64) (*Repository, error)
|
|||||||
return &forkedRepo, nil
|
return &forkedRepo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetForks returns all the forks of the repository
|
|
||||||
func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions) ([]*Repository, error) {
|
|
||||||
sess := db.GetEngine(ctx)
|
|
||||||
|
|
||||||
var forks []*Repository
|
|
||||||
if listOptions.Page == 0 {
|
|
||||||
forks = make([]*Repository, 0, repo.NumForks)
|
|
||||||
} else {
|
|
||||||
forks = make([]*Repository, 0, listOptions.PageSize)
|
|
||||||
sess = db.SetSessionPagination(sess, &listOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
return forks, sess.Find(&forks, &Repository{ForkID: repo.ID})
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncrementRepoForkNum increment repository fork number
|
// IncrementRepoForkNum increment repository fork number
|
||||||
func IncrementRepoForkNum(ctx context.Context, repoID int64) error {
|
func IncrementRepoForkNum(ctx context.Context, repoID int64) error {
|
||||||
_, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", repoID)
|
_, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", repoID)
|
||||||
|
@ -98,8 +98,7 @@ func (repos RepositoryList) IDs() []int64 {
|
|||||||
return repoIDs
|
return repoIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttributes loads the attributes for the given RepositoryList
|
func (repos RepositoryList) LoadOwners(ctx context.Context) error {
|
||||||
func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
|
|
||||||
if len(repos) == 0 {
|
if len(repos) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -107,10 +106,6 @@ func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
|
|||||||
userIDs := container.FilterSlice(repos, func(repo *Repository) (int64, bool) {
|
userIDs := container.FilterSlice(repos, func(repo *Repository) (int64, bool) {
|
||||||
return repo.OwnerID, true
|
return repo.OwnerID, true
|
||||||
})
|
})
|
||||||
repoIDs := make([]int64, len(repos))
|
|
||||||
for i := range repos {
|
|
||||||
repoIDs[i] = repos[i].ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load owners.
|
// Load owners.
|
||||||
users := make(map[int64]*user_model.User, len(userIDs))
|
users := make(map[int64]*user_model.User, len(userIDs))
|
||||||
@ -123,12 +118,19 @@ func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
|
|||||||
for i := range repos {
|
for i := range repos {
|
||||||
repos[i].Owner = users[repos[i].OwnerID]
|
repos[i].Owner = users[repos[i].OwnerID]
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repos RepositoryList) LoadLanguageStats(ctx context.Context) error {
|
||||||
|
if len(repos) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Load primary language.
|
// Load primary language.
|
||||||
stats := make(LanguageStatList, 0, len(repos))
|
stats := make(LanguageStatList, 0, len(repos))
|
||||||
if err := db.GetEngine(ctx).
|
if err := db.GetEngine(ctx).
|
||||||
Where("`is_primary` = ? AND `language` != ?", true, "other").
|
Where("`is_primary` = ? AND `language` != ?", true, "other").
|
||||||
In("`repo_id`", repoIDs).
|
In("`repo_id`", repos.IDs()).
|
||||||
Find(&stats); err != nil {
|
Find(&stats); err != nil {
|
||||||
return fmt.Errorf("find primary languages: %w", err)
|
return fmt.Errorf("find primary languages: %w", err)
|
||||||
}
|
}
|
||||||
@ -141,10 +143,18 @@ func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadAttributes loads the attributes for the given RepositoryList
|
||||||
|
func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
|
||||||
|
if err := repos.LoadOwners(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return repos.LoadLanguageStats(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// SearchRepoOptions holds the search options
|
// SearchRepoOptions holds the search options
|
||||||
type SearchRepoOptions struct {
|
type SearchRepoOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
|
@ -55,11 +55,20 @@ 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_service.FindForks(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, "FindForks", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err := repo_model.RepositoryList(forks).LoadOwners(ctx); err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "LoadOwners", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := repo_model.RepositoryList(forks).LoadUnits(ctx); err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "LoadUnits", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
apiForks := make([]*api.Repository, len(forks))
|
apiForks := make([]*api.Repository, len(forks))
|
||||||
for i, fork := range forks {
|
for i, fork := range forks {
|
||||||
permission, err := access_model.GetUserRepoPermission(ctx, fork, ctx.Doer)
|
permission, err := access_model.GetUserRepoPermission(ctx, fork, ctx.Doer)
|
||||||
@ -70,7 +79,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1151,26 +1151,25 @@ func Forks(ctx *context.Context) {
|
|||||||
if page <= 0 {
|
if page <= 0 {
|
||||||
page = 1
|
page = 1
|
||||||
}
|
}
|
||||||
|
pageSize := setting.ItemsPerPage
|
||||||
|
|
||||||
pager := context.NewPagination(ctx.Repo.Repository.NumForks, setting.ItemsPerPage, page, 5)
|
forks, total, err := repo_service.FindForks(ctx, ctx.Repo.Repository, ctx.Doer, db.ListOptions{
|
||||||
ctx.Data["Page"] = pager
|
Page: page,
|
||||||
|
PageSize: pageSize,
|
||||||
forks, err := repo_model.GetForks(ctx, ctx.Repo.Repository, db.ListOptions{
|
|
||||||
Page: pager.Paginater.Current(),
|
|
||||||
PageSize: setting.ItemsPerPage,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetForks", err)
|
ctx.ServerError("FindForks", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fork := range forks {
|
if err := repo_model.RepositoryList(forks).LoadOwners(ctx); err != nil {
|
||||||
if err = fork.LoadOwner(ctx); err != nil {
|
ctx.ServerError("LoadAttributes", err)
|
||||||
ctx.ServerError("LoadOwner", err)
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pager := context.NewPagination(int(total), pageSize, page, 5)
|
||||||
|
ctx.Data["Page"] = pager
|
||||||
|
|
||||||
ctx.Data["Forks"] = forks
|
ctx.Data["Forks"] = forks
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplForks)
|
ctx.HTML(http.StatusOK, tplForks)
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
@ -20,6 +21,8 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
notify_service "code.gitea.io/gitea/services/notify"
|
notify_service "code.gitea.io/gitea/services/notify"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrForkAlreadyExist represents a "ForkAlreadyExist" kind of error.
|
// ErrForkAlreadyExist represents a "ForkAlreadyExist" kind of error.
|
||||||
@ -247,3 +250,24 @@ func ConvertForkToNormalRepository(ctx context.Context, repo *repo_model.Reposit
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type findForksOptions struct {
|
||||||
|
db.ListOptions
|
||||||
|
RepoID int64
|
||||||
|
Doer *user_model.User
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts findForksOptions) ToConds() builder.Cond {
|
||||||
|
return builder.Eq{"fork_id": opts.RepoID}.And(
|
||||||
|
repo_model.AccessibleRepositoryCondition(opts.Doer, unit.TypeInvalid),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindForks returns all the forks of the repository
|
||||||
|
func FindForks(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, listOptions db.ListOptions) ([]*repo_model.Repository, int64, error) {
|
||||||
|
return db.FindAndCount[repo_model.Repository](ctx, findForksOptions{
|
||||||
|
ListOptions: listOptions,
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Doer: doer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -5,12 +5,14 @@
|
|||||||
<h2 class="ui dividing header">
|
<h2 class="ui dividing header">
|
||||||
{{ctx.Locale.Tr "repo.forks"}}
|
{{ctx.Locale.Tr "repo.forks"}}
|
||||||
</h2>
|
</h2>
|
||||||
|
<div class="flex-list">
|
||||||
{{range .Forks}}
|
{{range .Forks}}
|
||||||
<div class="tw-flex tw-items-center tw-py-2">
|
<div class="flex-item tw-border-0 repo-fork-item">
|
||||||
<span class="tw-mr-1">{{ctx.AvatarUtils.Avatar .Owner}}</span>
|
<span>{{ctx.AvatarUtils.Avatar .Owner}}</span>
|
||||||
<a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / <a href="{{.Link}}">{{.Name}}</a>
|
<span><a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / <a href="{{.Link}}">{{.Name}}</a></span>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{template "base/paginate" .}}
|
{{template "base/paginate" .}}
|
||||||
|
@ -7,8 +7,16 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
org_model "code.gitea.io/gitea/models/organization"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateForkNoLogin(t *testing.T) {
|
func TestCreateForkNoLogin(t *testing.T) {
|
||||||
@ -16,3 +24,75 @@ func TestCreateForkNoLogin(t *testing.T) {
|
|||||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{})
|
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{})
|
||||||
MakeRequest(t, req, http.StatusUnauthorized)
|
MakeRequest(t, req, http.StatusUnauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPIForkListLimitedAndPrivateRepos(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
user1Sess := loginUser(t, "user1")
|
||||||
|
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
|
||||||
|
|
||||||
|
// fork into a limited org
|
||||||
|
limitedOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 22})
|
||||||
|
assert.EqualValues(t, api.VisibleTypeLimited, limitedOrg.Visibility)
|
||||||
|
|
||||||
|
ownerTeam1, err := org_model.OrgFromUser(limitedOrg).GetOwnerTeam(db.DefaultContext)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, models.AddTeamMember(db.DefaultContext, ownerTeam1, user1))
|
||||||
|
user1Token := getTokenForLoggedInUser(t, user1Sess, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteOrganization)
|
||||||
|
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{
|
||||||
|
Organization: &limitedOrg.Name,
|
||||||
|
}).AddTokenAuth(user1Token)
|
||||||
|
MakeRequest(t, req, http.StatusAccepted)
|
||||||
|
|
||||||
|
// fork into a private org
|
||||||
|
user4Sess := loginUser(t, "user4")
|
||||||
|
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user4"})
|
||||||
|
privateOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23})
|
||||||
|
assert.EqualValues(t, api.VisibleTypePrivate, privateOrg.Visibility)
|
||||||
|
|
||||||
|
ownerTeam2, err := org_model.OrgFromUser(privateOrg).GetOwnerTeam(db.DefaultContext)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, models.AddTeamMember(db.DefaultContext, ownerTeam2, user4))
|
||||||
|
user4Token := getTokenForLoggedInUser(t, user4Sess, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteOrganization)
|
||||||
|
req = NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{
|
||||||
|
Organization: &privateOrg.Name,
|
||||||
|
}).AddTokenAuth(user4Token)
|
||||||
|
MakeRequest(t, req, http.StatusAccepted)
|
||||||
|
|
||||||
|
t.Run("Anonymous", 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(user1Token)
|
||||||
|
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"))
|
||||||
|
|
||||||
|
assert.NoError(t, models.AddTeamMember(db.DefaultContext, ownerTeam2, user1))
|
||||||
|
|
||||||
|
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks").AddTokenAuth(user1Token)
|
||||||
|
resp = MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
forks = []*api.Repository{}
|
||||||
|
DecodeJSON(t, resp, &forks)
|
||||||
|
|
||||||
|
assert.Len(t, forks, 2)
|
||||||
|
assert.EqualValues(t, "2", resp.Header().Get("X-Total-Count"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -9,8 +9,12 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
org_model "code.gitea.io/gitea/models/organization"
|
||||||
"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/structs"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -74,3 +78,51 @@ func TestRepoForkToOrg(t *testing.T) {
|
|||||||
_, exists := htmlDoc.doc.Find(`a.ui.button[href*="/fork"]`).Attr("href")
|
_, exists := htmlDoc.doc.Find(`a.ui.button[href*="/fork"]`).Attr("href")
|
||||||
assert.False(t, exists, "Forking should not be allowed anymore")
|
assert.False(t, exists, "Forking should not be allowed anymore")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestForkListLimitedAndPrivateRepos(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
forkItemSelector := ".repo-fork-item"
|
||||||
|
|
||||||
|
user1Sess := loginUser(t, "user1")
|
||||||
|
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user1"})
|
||||||
|
|
||||||
|
// fork to a limited org
|
||||||
|
limitedOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 22})
|
||||||
|
assert.EqualValues(t, structs.VisibleTypeLimited, limitedOrg.Visibility)
|
||||||
|
ownerTeam1, err := org_model.OrgFromUser(limitedOrg).GetOwnerTeam(db.DefaultContext)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, models.AddTeamMember(db.DefaultContext, ownerTeam1, user1))
|
||||||
|
testRepoFork(t, user1Sess, "user2", "repo1", limitedOrg.Name, "repo1", "")
|
||||||
|
|
||||||
|
// fork to a private org
|
||||||
|
user4Sess := loginUser(t, "user4")
|
||||||
|
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user4"})
|
||||||
|
privateOrg := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23})
|
||||||
|
assert.EqualValues(t, structs.VisibleTypePrivate, privateOrg.Visibility)
|
||||||
|
ownerTeam2, err := org_model.OrgFromUser(privateOrg).GetOwnerTeam(db.DefaultContext)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, models.AddTeamMember(db.DefaultContext, ownerTeam2, user4))
|
||||||
|
testRepoFork(t, user4Sess, "user2", "repo1", privateOrg.Name, "repo1", "")
|
||||||
|
|
||||||
|
t.Run("Anonymous", 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)
|
||||||
|
assert.EqualValues(t, 0, htmlDoc.Find(forkItemSelector).Length())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Logged in", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequest(t, "GET", "/user2/repo1/forks")
|
||||||
|
resp := user1Sess.MakeRequest(t, req, http.StatusOK)
|
||||||
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
assert.EqualValues(t, 1, htmlDoc.Find(forkItemSelector).Length())
|
||||||
|
|
||||||
|
assert.NoError(t, models.AddTeamMember(db.DefaultContext, ownerTeam2, user1))
|
||||||
|
resp = user1Sess.MakeRequest(t, req, http.StatusOK)
|
||||||
|
htmlDoc = NewHTMLParser(t, resp.Body)
|
||||||
|
assert.EqualValues(t, 2, htmlDoc.Find(forkItemSelector).Length())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user