@@ -6,6 +6,7 @@ package organization | |||
import ( | |||
"context" | |||
"fmt" | |||
"code.gitea.io/gitea/models/db" | |||
user_model "code.gitea.io/gitea/models/user" | |||
@@ -81,3 +82,43 @@ func CanCreateOrgRepo(orgID, uid int64) (bool, error) { | |||
And("team_user.org_id = ?", orgID). | |||
Exist(new(Team)) | |||
} | |||
// IsUserOrgOwner returns true if user is in the owner team of given organization. | |||
func IsUserOrgOwner(users user_model.UserList, orgID int64) map[int64]bool { | |||
results := make(map[int64]bool, len(users)) | |||
for _, user := range users { | |||
results[user.ID] = false // Set default to false | |||
} | |||
ownerMaps, err := loadOrganizationOwners(db.DefaultContext, users, orgID) | |||
if err == nil { | |||
for _, owner := range ownerMaps { | |||
results[owner.UID] = true | |||
} | |||
} | |||
return results | |||
} | |||
func loadOrganizationOwners(ctx context.Context, users user_model.UserList, orgID int64) (map[int64]*TeamUser, error) { | |||
if len(users) == 0 { | |||
return nil, nil | |||
} | |||
ownerTeam, err := GetOwnerTeam(ctx, orgID) | |||
if err != nil { | |||
if IsErrTeamNotExist(err) { | |||
log.Error("Organization does not have owner team: %d", orgID) | |||
return nil, nil | |||
} | |||
return nil, err | |||
} | |||
userIDs := users.GetUserIDs() | |||
ownerMaps := make(map[int64]*TeamUser) | |||
err = db.GetEngine(ctx).In("uid", userIDs). | |||
And("org_id=?", orgID). | |||
And("team_id=?", ownerTeam.ID). | |||
Find(&ownerMaps) | |||
if err != nil { | |||
return nil, fmt.Errorf("find team users: %v", err) | |||
} | |||
return ownerMaps, nil | |||
} |
@@ -70,3 +70,57 @@ func testIsUserOrgOwner(t *testing.T, uid, orgID int64, expected bool) { | |||
assert.NoError(t, err) | |||
assert.Equal(t, expected, is) | |||
} | |||
func TestUserListIsPublicMember(t *testing.T) { | |||
assert.NoError(t, unittest.PrepareTestDatabase()) | |||
tt := []struct { | |||
orgid int64 | |||
expected map[int64]bool | |||
}{ | |||
{3, map[int64]bool{2: true, 4: false, 28: true}}, | |||
{6, map[int64]bool{5: true, 28: true}}, | |||
{7, map[int64]bool{5: false}}, | |||
{25, map[int64]bool{24: true}}, | |||
{22, map[int64]bool{}}, | |||
} | |||
for _, v := range tt { | |||
t.Run(fmt.Sprintf("IsPublicMemberOfOrdIg%d", v.orgid), func(t *testing.T) { | |||
testUserListIsPublicMember(t, v.orgid, v.expected) | |||
}) | |||
} | |||
} | |||
func testUserListIsPublicMember(t *testing.T, orgID int64, expected map[int64]bool) { | |||
org, err := GetOrgByID(orgID) | |||
assert.NoError(t, err) | |||
_, membersIsPublic, err := org.GetMembers() | |||
assert.NoError(t, err) | |||
assert.Equal(t, expected, membersIsPublic) | |||
} | |||
func TestUserListIsUserOrgOwner(t *testing.T) { | |||
assert.NoError(t, unittest.PrepareTestDatabase()) | |||
tt := []struct { | |||
orgid int64 | |||
expected map[int64]bool | |||
}{ | |||
{3, map[int64]bool{2: true, 4: false, 28: false}}, | |||
{6, map[int64]bool{5: true, 28: false}}, | |||
{7, map[int64]bool{5: true}}, | |||
{25, map[int64]bool{24: false}}, // ErrTeamNotExist | |||
{22, map[int64]bool{}}, // No member | |||
} | |||
for _, v := range tt { | |||
t.Run(fmt.Sprintf("IsUserOrgOwnerOfOrdIg%d", v.orgid), func(t *testing.T) { | |||
testUserListIsUserOrgOwner(t, v.orgid, v.expected) | |||
}) | |||
} | |||
} | |||
func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bool) { | |||
org, err := GetOrgByID(orgID) | |||
assert.NoError(t, err) | |||
members, _, err := org.GetMembers() | |||
assert.NoError(t, err) | |||
assert.Equal(t, expected, IsUserOrgOwner(members, orgID)) | |||
} |
@@ -1,55 +0,0 @@ | |||
// Copyright 2019 The Gitea Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package models | |||
import ( | |||
"context" | |||
"fmt" | |||
"code.gitea.io/gitea/models/db" | |||
"code.gitea.io/gitea/models/organization" | |||
user_model "code.gitea.io/gitea/models/user" | |||
"code.gitea.io/gitea/modules/log" | |||
) | |||
// IsUserOrgOwner returns true if user is in the owner team of given organization. | |||
func IsUserOrgOwner(users user_model.UserList, orgID int64) map[int64]bool { | |||
results := make(map[int64]bool, len(users)) | |||
for _, user := range users { | |||
results[user.ID] = false // Set default to false | |||
} | |||
ownerMaps, err := loadOrganizationOwners(db.DefaultContext, users, orgID) | |||
if err == nil { | |||
for _, owner := range ownerMaps { | |||
results[owner.UID] = true | |||
} | |||
} | |||
return results | |||
} | |||
func loadOrganizationOwners(ctx context.Context, users user_model.UserList, orgID int64) (map[int64]*organization.TeamUser, error) { | |||
if len(users) == 0 { | |||
return nil, nil | |||
} | |||
ownerTeam, err := organization.GetOwnerTeam(ctx, orgID) | |||
if err != nil { | |||
if organization.IsErrTeamNotExist(err) { | |||
log.Error("Organization does not have owner team: %d", orgID) | |||
return nil, nil | |||
} | |||
return nil, err | |||
} | |||
userIDs := users.GetUserIDs() | |||
ownerMaps := make(map[int64]*organization.TeamUser) | |||
err = db.GetEngine(ctx).In("uid", userIDs). | |||
And("org_id=?", orgID). | |||
And("team_id=?", ownerTeam.ID). | |||
Find(&ownerMaps) | |||
if err != nil { | |||
return nil, fmt.Errorf("find team users: %v", err) | |||
} | |||
return ownerMaps, nil | |||
} |
@@ -1,69 +0,0 @@ | |||
// Copyright 2019 The Gitea Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package models | |||
import ( | |||
"fmt" | |||
"testing" | |||
"code.gitea.io/gitea/models/organization" | |||
"code.gitea.io/gitea/models/unittest" | |||
"github.com/stretchr/testify/assert" | |||
) | |||
func TestUserListIsPublicMember(t *testing.T) { | |||
assert.NoError(t, unittest.PrepareTestDatabase()) | |||
tt := []struct { | |||
orgid int64 | |||
expected map[int64]bool | |||
}{ | |||
{3, map[int64]bool{2: true, 4: false, 28: true}}, | |||
{6, map[int64]bool{5: true, 28: true}}, | |||
{7, map[int64]bool{5: false}}, | |||
{25, map[int64]bool{24: true}}, | |||
{22, map[int64]bool{}}, | |||
} | |||
for _, v := range tt { | |||
t.Run(fmt.Sprintf("IsPublicMemberOfOrdIg%d", v.orgid), func(t *testing.T) { | |||
testUserListIsPublicMember(t, v.orgid, v.expected) | |||
}) | |||
} | |||
} | |||
func testUserListIsPublicMember(t *testing.T, orgID int64, expected map[int64]bool) { | |||
org, err := organization.GetOrgByID(orgID) | |||
assert.NoError(t, err) | |||
_, membersIsPublic, err := org.GetMembers() | |||
assert.NoError(t, err) | |||
assert.Equal(t, expected, membersIsPublic) | |||
} | |||
func TestUserListIsUserOrgOwner(t *testing.T) { | |||
assert.NoError(t, unittest.PrepareTestDatabase()) | |||
tt := []struct { | |||
orgid int64 | |||
expected map[int64]bool | |||
}{ | |||
{3, map[int64]bool{2: true, 4: false, 28: false}}, | |||
{6, map[int64]bool{5: true, 28: false}}, | |||
{7, map[int64]bool{5: true}}, | |||
{25, map[int64]bool{24: false}}, // ErrTeamNotExist | |||
{22, map[int64]bool{}}, // No member | |||
} | |||
for _, v := range tt { | |||
t.Run(fmt.Sprintf("IsUserOrgOwnerOfOrdIg%d", v.orgid), func(t *testing.T) { | |||
testUserListIsUserOrgOwner(t, v.orgid, v.expected) | |||
}) | |||
} | |||
} | |||
func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bool) { | |||
org, err := organization.GetOrgByID(orgID) | |||
assert.NoError(t, err) | |||
members, _, err := org.GetMembers() | |||
assert.NoError(t, err) | |||
assert.Equal(t, expected, IsUserOrgOwner(members, orgID)) | |||
} |
@@ -63,7 +63,7 @@ func Members(ctx *context.Context) { | |||
ctx.Data["Page"] = pager | |||
ctx.Data["Members"] = members | |||
ctx.Data["MembersIsPublicMember"] = membersIsPublic | |||
ctx.Data["MembersIsUserOrgOwner"] = models.IsUserOrgOwner(members, org.ID) | |||
ctx.Data["MembersIsUserOrgOwner"] = organization.IsUserOrgOwner(members, org.ID) | |||
ctx.Data["MembersTwoFaStatus"] = members.GetTwoFaStatus() | |||
ctx.HTML(http.StatusOK, tplMembers) |