mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-30 09:41:11 -05:00
Calculate PublicOnly
for org membership only once (#32234)
Refactoring of #32211 this move the PublicOnly() filter calcuation next to the DB querys and let it be decided by the Doer --- *Sponsored by Kithara Software GmbH* (cherry picked from commit 43c252dfeaf9ab03c4db3e7ac5169bc0d69901ac) Conflicts: models/organization/org_test.go models/organization/org_user_test.go routers/web/org/home.go rather simple conflict resolution but not trivial tests/integration/user_count_test.go had to be adapted (simple) because it does not exist in Gitea and uses the modified model
This commit is contained in:
parent
45435a8789
commit
7751bb64cb
8 changed files with 76 additions and 56 deletions
|
@ -141,8 +141,9 @@ func (org *Organization) LoadTeams(ctx context.Context) ([]*Team, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMembers returns all members of organization.
|
// GetMembers returns all members of organization.
|
||||||
func (org *Organization) GetMembers(ctx context.Context) (user_model.UserList, map[int64]bool, error) {
|
func (org *Organization) GetMembers(ctx context.Context, doer *user_model.User) (user_model.UserList, map[int64]bool, error) {
|
||||||
return FindOrgMembers(ctx, &FindOrgMembersOpts{
|
return FindOrgMembers(ctx, &FindOrgMembersOpts{
|
||||||
|
Doer: doer,
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -195,16 +196,22 @@ func (org *Organization) CanCreateRepo() bool {
|
||||||
// FindOrgMembersOpts represensts find org members conditions
|
// FindOrgMembersOpts represensts find org members conditions
|
||||||
type FindOrgMembersOpts struct {
|
type FindOrgMembersOpts struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
OrgID int64
|
Doer *user_model.User
|
||||||
PublicOnly bool
|
IsDoerMember bool
|
||||||
|
OrgID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts FindOrgMembersOpts) PublicOnly() bool {
|
||||||
|
return opts.Doer == nil || !(opts.IsDoerMember || opts.Doer.IsAdmin)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountOrgMembers counts the organization's members
|
// CountOrgMembers counts the organization's members
|
||||||
func CountOrgMembers(ctx context.Context, opts *FindOrgMembersOpts) (int64, error) {
|
func CountOrgMembers(ctx context.Context, opts *FindOrgMembersOpts) (int64, error) {
|
||||||
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
|
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
|
||||||
if opts.PublicOnly {
|
if opts.PublicOnly() {
|
||||||
sess.And("is_public = ?", true)
|
sess.And("is_public = ?", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Count(new(OrgUser))
|
return sess.Count(new(OrgUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,9 +531,10 @@ func GetOrgsCanCreateRepoByUserID(ctx context.Context, userID int64) ([]*Organiz
|
||||||
// GetOrgUsersByOrgID returns all organization-user relations by organization ID.
|
// GetOrgUsersByOrgID returns all organization-user relations by organization ID.
|
||||||
func GetOrgUsersByOrgID(ctx context.Context, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
func GetOrgUsersByOrgID(ctx context.Context, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
||||||
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
|
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
|
||||||
if opts.PublicOnly {
|
if opts.PublicOnly() {
|
||||||
sess.And("is_public = ?", true)
|
sess.And("is_public = ?", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.ListOptions.PageSize > 0 {
|
if opts.ListOptions.PageSize > 0 {
|
||||||
sess = db.SetSessionPagination(sess, opts)
|
sess = db.SetSessionPagination(sess, opts)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
package organization_test
|
package organization_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
@ -104,7 +105,7 @@ func TestUser_GetTeams(t *testing.T) {
|
||||||
func TestUser_GetMembers(t *testing.T) {
|
func TestUser_GetMembers(t *testing.T) {
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||||
members, _, err := org.GetMembers(db.DefaultContext)
|
members, _, err := org.GetMembers(db.DefaultContext, &user_model.User{IsAdmin: true})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, members, 3) {
|
if assert.Len(t, members, 3) {
|
||||||
assert.Equal(t, int64(2), members[0].ID)
|
assert.Equal(t, int64(2), members[0].ID)
|
||||||
|
@ -211,37 +212,42 @@ func TestFindOrgs(t *testing.T) {
|
||||||
func TestGetOrgUsersByOrgID(t *testing.T) {
|
func TestGetOrgUsersByOrgID(t *testing.T) {
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
orgUsers, err := organization.GetOrgUsersByOrgID(db.DefaultContext, &organization.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
ListOptions: db.ListOptions{},
|
Doer: &user_model.User{IsAdmin: true},
|
||||||
OrgID: 3,
|
OrgID: 3,
|
||||||
PublicOnly: false,
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
if assert.Len(t, orgUsers, 3) {
|
|
||||||
assert.Equal(t, organization.OrgUser{
|
|
||||||
ID: orgUsers[0].ID,
|
|
||||||
OrgID: 3,
|
|
||||||
UID: 2,
|
|
||||||
IsPublic: true,
|
|
||||||
}, *orgUsers[0])
|
|
||||||
assert.Equal(t, organization.OrgUser{
|
|
||||||
ID: orgUsers[1].ID,
|
|
||||||
OrgID: 3,
|
|
||||||
UID: 4,
|
|
||||||
IsPublic: false,
|
|
||||||
}, *orgUsers[1])
|
|
||||||
assert.Equal(t, organization.OrgUser{
|
|
||||||
ID: orgUsers[2].ID,
|
|
||||||
OrgID: 3,
|
|
||||||
UID: 28,
|
|
||||||
IsPublic: true,
|
|
||||||
}, *orgUsers[2])
|
|
||||||
}
|
}
|
||||||
|
assert.False(t, opts.PublicOnly())
|
||||||
|
orgUsers, err := organization.GetOrgUsersByOrgID(db.DefaultContext, opts)
|
||||||
|
require.NoError(t, err)
|
||||||
|
sort.Slice(orgUsers, func(i, j int) bool {
|
||||||
|
return orgUsers[i].ID < orgUsers[j].ID
|
||||||
|
})
|
||||||
|
assert.EqualValues(t, []*organization.OrgUser{{
|
||||||
|
ID: 1,
|
||||||
|
OrgID: 3,
|
||||||
|
UID: 2,
|
||||||
|
IsPublic: true,
|
||||||
|
}, {
|
||||||
|
ID: 2,
|
||||||
|
OrgID: 3,
|
||||||
|
UID: 4,
|
||||||
|
IsPublic: false,
|
||||||
|
}, {
|
||||||
|
ID: 9,
|
||||||
|
OrgID: 3,
|
||||||
|
UID: 28,
|
||||||
|
IsPublic: true,
|
||||||
|
}}, orgUsers)
|
||||||
|
|
||||||
|
opts = &organization.FindOrgMembersOpts{OrgID: 3}
|
||||||
|
assert.True(t, opts.PublicOnly())
|
||||||
|
orgUsers, err = organization.GetOrgUsersByOrgID(db.DefaultContext, opts)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, orgUsers, 2)
|
||||||
|
|
||||||
orgUsers, err = organization.GetOrgUsersByOrgID(db.DefaultContext, &organization.FindOrgMembersOpts{
|
orgUsers, err = organization.GetOrgUsersByOrgID(db.DefaultContext, &organization.FindOrgMembersOpts{
|
||||||
ListOptions: db.ListOptions{},
|
ListOptions: db.ListOptions{},
|
||||||
OrgID: unittest.NonexistentID,
|
OrgID: unittest.NonexistentID,
|
||||||
PublicOnly: false,
|
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Empty(t, orgUsers)
|
assert.Empty(t, orgUsers)
|
||||||
|
|
|
@ -95,7 +95,7 @@ func TestUserListIsPublicMember(t *testing.T) {
|
||||||
func testUserListIsPublicMember(t *testing.T, orgID int64, expected map[int64]bool) {
|
func testUserListIsPublicMember(t *testing.T, orgID int64, expected map[int64]bool) {
|
||||||
org, err := organization.GetOrgByID(db.DefaultContext, orgID)
|
org, err := organization.GetOrgByID(db.DefaultContext, orgID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, membersIsPublic, err := org.GetMembers(db.DefaultContext)
|
_, membersIsPublic, err := org.GetMembers(db.DefaultContext, &user_model.User{IsAdmin: true})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expected, membersIsPublic)
|
assert.Equal(t, expected, membersIsPublic)
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ func TestUserListIsUserOrgOwner(t *testing.T) {
|
||||||
func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bool) {
|
func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bool) {
|
||||||
org, err := organization.GetOrgByID(db.DefaultContext, orgID)
|
org, err := organization.GetOrgByID(db.DefaultContext, orgID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
members, _, err := org.GetMembers(db.DefaultContext)
|
members, _, err := org.GetMembers(db.DefaultContext, &user_model.User{IsAdmin: true})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expected, organization.IsUserOrgOwner(db.DefaultContext, members, orgID))
|
assert.Equal(t, expected, organization.IsUserOrgOwner(db.DefaultContext, members, orgID))
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// listMembers list an organization's members
|
// listMembers list an organization's members
|
||||||
func listMembers(ctx *context.APIContext, publicOnly bool) {
|
func listMembers(ctx *context.APIContext, isMember bool) {
|
||||||
opts := &organization.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
OrgID: ctx.Org.Organization.ID,
|
Doer: ctx.Doer,
|
||||||
PublicOnly: publicOnly,
|
IsDoerMember: isMember,
|
||||||
ListOptions: utils.GetListOptions(ctx),
|
OrgID: ctx.Org.Organization.ID,
|
||||||
|
ListOptions: utils.GetListOptions(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := organization.CountOrgMembers(ctx, opts)
|
count, err := organization.CountOrgMembers(ctx, opts)
|
||||||
|
@ -73,16 +74,19 @@ func ListMembers(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
publicOnly := true
|
var (
|
||||||
|
isMember bool
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
if ctx.Doer != nil {
|
if ctx.Doer != nil {
|
||||||
isMember, err := ctx.Org.Organization.IsOrgMember(ctx, ctx.Doer.ID)
|
isMember, err = ctx.Org.Organization.IsOrgMember(ctx, ctx.Doer.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
|
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
publicOnly = !isMember && !ctx.Doer.IsAdmin
|
|
||||||
}
|
}
|
||||||
listMembers(ctx, publicOnly)
|
listMembers(ctx, isMember)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListPublicMembers list an organization's public members
|
// ListPublicMembers list an organization's public members
|
||||||
|
@ -112,7 +116,7 @@ func ListPublicMembers(ctx *context.APIContext) {
|
||||||
// "404":
|
// "404":
|
||||||
// "$ref": "#/responses/notFound"
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
listMembers(ctx, true)
|
listMembers(ctx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsMember check if a user is a member of an organization
|
// IsMember check if a user is a member of an organization
|
||||||
|
|
|
@ -110,10 +110,12 @@ func Home(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := &organization.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
OrgID: org.ID,
|
Doer: ctx.Doer,
|
||||||
PublicOnly: ctx.Org.PublicMemberOnly,
|
OrgID: org.ID,
|
||||||
ListOptions: db.ListOptions{Page: 1, PageSize: 25},
|
IsDoerMember: ctx.Org.IsMember,
|
||||||
|
ListOptions: db.ListOptions{Page: 1, PageSize: 25},
|
||||||
}
|
}
|
||||||
|
|
||||||
members, _, err := organization.FindOrgMembers(ctx, opts)
|
members, _, err := organization.FindOrgMembers(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("FindOrgMembers", err)
|
ctx.ServerError("FindOrgMembers", err)
|
||||||
|
|
|
@ -33,8 +33,8 @@ func Members(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := &organization.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
OrgID: org.ID,
|
Doer: ctx.Doer,
|
||||||
PublicOnly: true,
|
OrgID: org.ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Doer != nil {
|
if ctx.Doer != nil {
|
||||||
|
@ -43,9 +43,9 @@ func Members(ctx *context.Context) {
|
||||||
ctx.Error(http.StatusInternalServerError, "IsOrgMember")
|
ctx.Error(http.StatusInternalServerError, "IsOrgMember")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
opts.PublicOnly = !isMember && !ctx.Doer.IsAdmin
|
opts.IsDoerMember = isMember
|
||||||
}
|
}
|
||||||
ctx.Data["PublicOnly"] = opts.PublicOnly
|
ctx.Data["PublicOnly"] = opts.PublicOnly()
|
||||||
|
|
||||||
total, err := organization.CountOrgMembers(ctx, opts)
|
total, err := organization.CountOrgMembers(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -26,7 +26,6 @@ type Organization struct {
|
||||||
Organization *organization.Organization
|
Organization *organization.Organization
|
||||||
OrgLink string
|
OrgLink string
|
||||||
CanCreateOrgRepo bool
|
CanCreateOrgRepo bool
|
||||||
PublicMemberOnly bool // Only display public members
|
|
||||||
|
|
||||||
Team *organization.Team
|
Team *organization.Team
|
||||||
Teams []*organization.Team
|
Teams []*organization.Team
|
||||||
|
@ -176,10 +175,10 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
|
||||||
ctx.Data["OrgLink"] = ctx.Org.OrgLink
|
ctx.Data["OrgLink"] = ctx.Org.OrgLink
|
||||||
|
|
||||||
// Member
|
// Member
|
||||||
ctx.Org.PublicMemberOnly = ctx.Doer == nil || !ctx.Org.IsMember && !ctx.Doer.IsAdmin
|
|
||||||
opts := &organization.FindOrgMembersOpts{
|
opts := &organization.FindOrgMembersOpts{
|
||||||
OrgID: org.ID,
|
Doer: ctx.Doer,
|
||||||
PublicOnly: ctx.Org.PublicMemberOnly,
|
OrgID: org.ID,
|
||||||
|
IsDoerMember: ctx.Org.IsMember,
|
||||||
}
|
}
|
||||||
ctx.Data["NumMembers"], err = organization.CountOrgMembers(ctx, opts)
|
ctx.Data["NumMembers"], err = organization.CountOrgMembers(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -75,8 +75,9 @@ func (countTest *userCountTest) Init(t *testing.T, doerID, userID int64) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
countTest.memberCount, err = organization.CountOrgMembers(db.DefaultContext, &organization.FindOrgMembersOpts{
|
countTest.memberCount, err = organization.CountOrgMembers(db.DefaultContext, &organization.FindOrgMembersOpts{
|
||||||
OrgID: org.ID,
|
Doer: countTest.doer,
|
||||||
PublicOnly: !isMember,
|
OrgID: org.ID,
|
||||||
|
IsDoerMember: isMember,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue