Skip to content

Commit 1dbd9aa

Browse files
authored
Merge branch 'main' into fix-test-lfs
2 parents 5e8c40e + 4c924bf commit 1dbd9aa

File tree

6 files changed

+160
-20
lines changed

6 files changed

+160
-20
lines changed

models/fixtures/org_user.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,9 @@
129129
uid: 2
130130
org_id: 35
131131
is_public: true
132+
133+
-
134+
id: 23
135+
uid: 20
136+
org_id: 17
137+
is_public: false

models/fixtures/user.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@
623623
num_stars: 0
624624
num_repos: 2
625625
num_teams: 3
626-
num_members: 4
626+
num_members: 5
627627
visibility: 0
628628
repo_admin_change_team_access: false
629629
theme: ""

models/organization/org.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"code.gitea.io/gitea/modules/util"
2323

2424
"xorm.io/builder"
25+
"xorm.io/xorm"
2526
)
2627

2728
// ________ .__ __ .__
@@ -205,11 +206,28 @@ func (opts FindOrgMembersOpts) PublicOnly() bool {
205206
return opts.Doer == nil || !(opts.IsDoerMember || opts.Doer.IsAdmin)
206207
}
207208

209+
// applyTeamMatesOnlyFilter make sure restricted users only see public team members and there own team mates
210+
func (opts FindOrgMembersOpts) applyTeamMatesOnlyFilter(sess *xorm.Session) {
211+
if opts.Doer != nil && opts.IsDoerMember && opts.Doer.IsRestricted {
212+
teamMates := builder.Select("DISTINCT team_user.uid").
213+
From("team_user").
214+
Where(builder.In("team_user.team_id", getUserTeamIDsQueryBuilder(opts.OrgID, opts.Doer.ID))).
215+
And(builder.Eq{"team_user.org_id": opts.OrgID})
216+
217+
sess.And(
218+
builder.In("org_user.uid", teamMates).
219+
Or(builder.Eq{"org_user.is_public": true}),
220+
)
221+
}
222+
}
223+
208224
// CountOrgMembers counts the organization's members
209225
func CountOrgMembers(ctx context.Context, opts *FindOrgMembersOpts) (int64, error) {
210226
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
211227
if opts.PublicOnly() {
212-
sess.And("is_public = ?", true)
228+
sess = sess.And("is_public = ?", true)
229+
} else {
230+
opts.applyTeamMatesOnlyFilter(sess)
213231
}
214232

215233
return sess.Count(new(OrgUser))
@@ -533,7 +551,9 @@ func GetOrgsCanCreateRepoByUserID(ctx context.Context, userID int64) ([]*Organiz
533551
func GetOrgUsersByOrgID(ctx context.Context, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
534552
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
535553
if opts.PublicOnly() {
536-
sess.And("is_public = ?", true)
554+
sess = sess.And("is_public = ?", true)
555+
} else {
556+
opts.applyTeamMatesOnlyFilter(sess)
537557
}
538558

539559
if opts.ListOptions.PageSize > 0 {
@@ -664,6 +684,15 @@ func (org *Organization) getUserTeamIDs(ctx context.Context, userID int64) ([]in
664684
Find(&teamIDs)
665685
}
666686

687+
func getUserTeamIDsQueryBuilder(orgID, userID int64) *builder.Builder {
688+
return builder.Select("team.id").From("team").
689+
InnerJoin("team_user", "team_user.team_id = team.id").
690+
Where(builder.Eq{
691+
"team_user.org_id": orgID,
692+
"team_user.uid": userID,
693+
})
694+
}
695+
667696
// TeamsWithAccessToRepo returns all teams that have given access level to the repository.
668697
func (org *Organization) TeamsWithAccessToRepo(ctx context.Context, repoID int64, mode perm.AccessMode) ([]*Team, error) {
669698
return GetTeamsWithAccessToRepo(ctx, org.ID, repoID, mode)

models/organization/org_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package organization_test
55

66
import (
7+
"slices"
78
"sort"
89
"testing"
910

@@ -181,6 +182,75 @@ func TestIsPublicMembership(t *testing.T) {
181182
test(unittest.NonexistentID, unittest.NonexistentID, false)
182183
}
183184

185+
func TestRestrictedUserOrgMembers(t *testing.T) {
186+
assert.NoError(t, unittest.PrepareTestDatabase())
187+
188+
restrictedUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{
189+
ID: 29,
190+
IsRestricted: true,
191+
})
192+
if !assert.True(t, restrictedUser.IsRestricted) {
193+
return // ensure fixtures return restricted user
194+
}
195+
196+
testCases := []struct {
197+
name string
198+
opts *organization.FindOrgMembersOpts
199+
expectedUIDs []int64
200+
}{
201+
{
202+
name: "restricted user sees public members and teammates",
203+
opts: &organization.FindOrgMembersOpts{
204+
OrgID: 17, // org17 where user29 is in team9
205+
Doer: restrictedUser,
206+
IsDoerMember: true,
207+
},
208+
expectedUIDs: []int64{2, 15, 20, 29}, // Public members (2) + teammates in team9 (15, 20, 29)
209+
},
210+
{
211+
name: "restricted user sees only public members when not member",
212+
opts: &organization.FindOrgMembersOpts{
213+
OrgID: 3, // org3 where user29 is not a member
214+
Doer: restrictedUser,
215+
},
216+
expectedUIDs: []int64{2, 28}, // Only public members
217+
},
218+
{
219+
name: "non logged in only shows public members",
220+
opts: &organization.FindOrgMembersOpts{
221+
OrgID: 3,
222+
},
223+
expectedUIDs: []int64{2, 28}, // Only public members
224+
},
225+
{
226+
name: "non restricted user sees all members",
227+
opts: &organization.FindOrgMembersOpts{
228+
OrgID: 17,
229+
Doer: unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15}),
230+
IsDoerMember: true,
231+
},
232+
expectedUIDs: []int64{2, 15, 18, 20, 29}, // All members
233+
},
234+
}
235+
236+
for _, tc := range testCases {
237+
t.Run(tc.name, func(t *testing.T) {
238+
count, err := organization.CountOrgMembers(db.DefaultContext, tc.opts)
239+
assert.NoError(t, err)
240+
assert.EqualValues(t, len(tc.expectedUIDs), count)
241+
242+
members, err := organization.GetOrgUsersByOrgID(db.DefaultContext, tc.opts)
243+
assert.NoError(t, err)
244+
memberUIDs := make([]int64, 0, len(members))
245+
for _, member := range members {
246+
memberUIDs = append(memberUIDs, member.UID)
247+
}
248+
slices.Sort(memberUIDs)
249+
assert.EqualValues(t, tc.expectedUIDs, memberUIDs)
250+
})
251+
}
252+
}
253+
184254
func TestFindOrgs(t *testing.T) {
185255
assert.NoError(t, unittest.PrepareTestDatabase())
186256

modules/packages/cargo/parser.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,24 @@ func parsePackage(r io.Reader) (*Package, error) {
136136

137137
dependencies := make([]*Dependency, 0, len(meta.Deps))
138138
for _, dep := range meta.Deps {
139+
// https://doc.rust-lang.org/cargo/reference/registry-web-api.html#publish
140+
// It is a string of the new package name if the dependency is renamed, otherwise empty
141+
name := dep.ExplicitNameInToml
142+
pkg := &dep.Name
143+
if name == "" {
144+
name = dep.Name
145+
pkg = nil
146+
}
139147
dependencies = append(dependencies, &Dependency{
140-
Name: dep.Name,
148+
Name: name,
141149
Req: dep.VersionReq,
142150
Features: dep.Features,
143151
Optional: dep.Optional,
144152
DefaultFeatures: dep.DefaultFeatures,
145153
Target: dep.Target,
146154
Kind: dep.Kind,
147155
Registry: dep.Registry,
156+
Package: pkg,
148157
})
149158
}
150159

modules/packages/cargo/parser_test.go

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ import (
1313
"github.com/stretchr/testify/assert"
1414
)
1515

16-
const (
17-
description = "Package Description"
18-
author = "KN4CK3R"
19-
homepage = "https://gitea.io/"
20-
license = "MIT"
21-
)
22-
2316
func TestParsePackage(t *testing.T) {
24-
createPackage := func(name, version string) io.Reader {
25-
metadata := `{
17+
const (
18+
description = "Package Description"
19+
author = "KN4CK3R"
20+
homepage = "https://gitea.io/"
21+
license = "MIT"
22+
payload = "gitea test dummy payload" // a fake payload for test only
23+
)
24+
makeDefaultPackageMeta := func(name, version string) string {
25+
return `{
2626
"name":"` + name + `",
2727
"vers":"` + version + `",
2828
"description":"` + description + `",
@@ -36,18 +36,19 @@ func TestParsePackage(t *testing.T) {
3636
"homepage":"` + homepage + `",
3737
"license":"` + license + `"
3838
}`
39-
39+
}
40+
createPackage := func(metadata string) io.Reader {
4041
var buf bytes.Buffer
4142
binary.Write(&buf, binary.LittleEndian, uint32(len(metadata)))
4243
buf.WriteString(metadata)
43-
binary.Write(&buf, binary.LittleEndian, uint32(4))
44-
buf.WriteString("test")
44+
binary.Write(&buf, binary.LittleEndian, uint32(len(payload)))
45+
buf.WriteString(payload)
4546
return &buf
4647
}
4748

4849
t.Run("InvalidName", func(t *testing.T) {
4950
for _, name := range []string{"", "0test", "-test", "_test", strings.Repeat("a", 65)} {
50-
data := createPackage(name, "1.0.0")
51+
data := createPackage(makeDefaultPackageMeta(name, "1.0.0"))
5152

5253
cp, err := ParsePackage(data)
5354
assert.Nil(t, cp)
@@ -57,7 +58,7 @@ func TestParsePackage(t *testing.T) {
5758

5859
t.Run("InvalidVersion", func(t *testing.T) {
5960
for _, version := range []string{"", "1.", "-1.0", "1.0.0/1"} {
60-
data := createPackage("test", version)
61+
data := createPackage(makeDefaultPackageMeta("test", version))
6162

6263
cp, err := ParsePackage(data)
6364
assert.Nil(t, cp)
@@ -66,7 +67,7 @@ func TestParsePackage(t *testing.T) {
6667
})
6768

6869
t.Run("Valid", func(t *testing.T) {
69-
data := createPackage("test", "1.0.0")
70+
data := createPackage(makeDefaultPackageMeta("test", "1.0.0"))
7071

7172
cp, err := ParsePackage(data)
7273
assert.NotNil(t, cp)
@@ -78,9 +79,34 @@ func TestParsePackage(t *testing.T) {
7879
assert.Equal(t, []string{author}, cp.Metadata.Authors)
7980
assert.Len(t, cp.Metadata.Dependencies, 1)
8081
assert.Equal(t, "dep", cp.Metadata.Dependencies[0].Name)
82+
assert.Nil(t, cp.Metadata.Dependencies[0].Package)
8183
assert.Equal(t, homepage, cp.Metadata.ProjectURL)
8284
assert.Equal(t, license, cp.Metadata.License)
8385
content, _ := io.ReadAll(cp.Content)
84-
assert.Equal(t, "test", string(content))
86+
assert.Equal(t, payload, string(content))
87+
})
88+
89+
t.Run("Renamed", func(t *testing.T) {
90+
data := createPackage(`{
91+
"name":"test-pkg",
92+
"vers":"1.0",
93+
"description":"test-desc",
94+
"authors": ["test-author"],
95+
"deps":[
96+
{
97+
"name":"dep-renamed",
98+
"explicit_name_in_toml":"dep-explicit",
99+
"version_req":"1.0"
100+
}
101+
],
102+
"homepage":"https://gitea.io/",
103+
"license":"MIT"
104+
}`)
105+
cp, err := ParsePackage(data)
106+
assert.NoError(t, err)
107+
assert.Equal(t, "test-pkg", cp.Name)
108+
assert.Equal(t, "https://gitea.io/", cp.Metadata.ProjectURL)
109+
assert.Equal(t, "dep-explicit", cp.Metadata.Dependencies[0].Name)
110+
assert.Equal(t, "dep-renamed", *cp.Metadata.Dependencies[0].Package)
85111
})
86112
}

0 commit comments

Comments
 (0)