Skip to content

Commit ec85511

Browse files
fix deadlock caused by differing contexts when retrieving group ancestry with ParentGroupCond/GetParentGroupChain when using a sqlite db
1 parent 3f32ea7 commit ec85511

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

models/group/group.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func ParentGroupCondByRepoID(ctx context.Context, repoID int64, idStr string) bu
195195
if err != nil {
196196
return builder.In(idStr)
197197
}
198-
return ParentGroupCond(idStr, g.ID)
198+
return ParentGroupCond(ctx, idStr, g.ID)
199199
}
200200

201201
type FindGroupsOptions struct {
@@ -313,8 +313,8 @@ func GetParentGroupIDChain(ctx context.Context, groupID int64) (ids []int64, err
313313
}
314314

315315
// ParentGroupCond returns a condition matching a group and its ancestors
316-
func ParentGroupCond(idStr string, groupID int64) builder.Cond {
317-
groupList, err := GetParentGroupIDChain(db.DefaultContext, groupID)
316+
func ParentGroupCond(ctx context.Context, idStr string, groupID int64) builder.Cond {
317+
groupList, err := GetParentGroupIDChain(ctx, groupID)
318318
if err != nil {
319319
log.Info("Error building group cond: %w", err)
320320
return builder.NotIn(idStr)
@@ -331,7 +331,7 @@ func UpdateGroup(ctx context.Context, group *Group) error {
331331
func MoveGroup(ctx context.Context, group *Group, newParent int64, newSortOrder int) error {
332332
sess := db.GetEngine(ctx)
333333
ng, err := GetGroupByID(ctx, newParent)
334-
if err != nil && !IsErrGroupNotExist(err) {
334+
if !IsErrGroupNotExist(err) {
335335
return err
336336
}
337337
if ng != nil {

models/organization/team_group.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
func GetTeamsWithAccessToGroup(ctx context.Context, orgID, groupID int64, mode perm.AccessMode) ([]*Team, error) {
1212
teams := make([]*Team, 0)
13-
inCond := group_model.ParentGroupCond("group_team.group_id", groupID)
13+
inCond := group_model.ParentGroupCond(ctx, "group_team.group_id", groupID)
1414
return teams, db.GetEngine(ctx).Distinct("team.*").Where("group_team.access_mode >= ?", mode).
1515
Join("INNER", "group_team", "group_team.team_id = team.id and group_team.org_id = ?", orgID).
1616
And("group_team.org_id = ?", orgID).
@@ -21,7 +21,7 @@ func GetTeamsWithAccessToGroup(ctx context.Context, orgID, groupID int64, mode p
2121

2222
func GetTeamsWithAccessToGroupUnit(ctx context.Context, orgID, groupID int64, mode perm.AccessMode, unitType unit.Type) ([]*Team, error) {
2323
teams := make([]*Team, 0)
24-
inCond := group_model.ParentGroupCond("group_team.group_id", groupID)
24+
inCond := group_model.ParentGroupCond(ctx, "group_team.group_id", groupID)
2525
return teams, db.GetEngine(ctx).Where("group_team.access_mode >= ?", mode).
2626
Join("INNER", "group_team", "group_team.team_id = team.id").
2727
Join("INNER", "group_unit", "group_unit.team_id = team.id").

models/shared/group/org_group.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package group
2+
3+
import (
4+
"code.gitea.io/gitea/models/db"
5+
group_model "code.gitea.io/gitea/models/group"
6+
organization_model "code.gitea.io/gitea/models/organization"
7+
user_model "code.gitea.io/gitea/models/user"
8+
"context"
9+
"xorm.io/builder"
10+
)
11+
12+
// FindGroupMembers finds all users who have access to a group via team membership
13+
func FindGroupMembers(ctx context.Context, groupID int64, opts *organization_model.FindOrgMembersOpts) (user_model.UserList, error) {
14+
cond := builder.
15+
Select("`team_user`.uid").
16+
From("team_user").
17+
InnerJoin("org_user", "`org_user`.uid = team_user.uid").
18+
InnerJoin("group_team", "`group_team`.team_id = team_user.team_id").
19+
Where(builder.Eq{"`org_user`.org_id": opts.OrgID}).
20+
And(group_model.ParentGroupCond(context.TODO(), "`group_team`.group_id", groupID))
21+
if opts.PublicOnly() {
22+
cond = cond.And(builder.Eq{"`org_user`.is_public": true})
23+
}
24+
sess := db.GetEngine(ctx).Where(builder.In("`user`.id", cond))
25+
if opts.ListOptions.PageSize > 0 {
26+
sess = db.SetSessionPagination(sess, opts)
27+
users := make([]*user_model.User, 0, opts.ListOptions.PageSize)
28+
return users, sess.Find(&users)
29+
}
30+
31+
var users []*user_model.User
32+
err := sess.Find(&users)
33+
return users, err
34+
}
35+
36+
func GetGroupTeams(ctx context.Context, groupID int64) (teams []*organization_model.Team, err error) {
37+
err = db.GetEngine(ctx).
38+
Where("`group_team`.group_id = ?", groupID).
39+
Join("INNER", "group_team", "`group_team`.team_id = `team`.id").
40+
Asc("`team`.name").
41+
Find(&teams)
42+
return
43+
}
44+
45+
func IsGroupMember(ctx context.Context, groupID, userID int64) (bool, error) {
46+
return db.GetEngine(ctx).
47+
Where("`group_team`.group_id = ?", groupID).
48+
Join("INNER", "group_team", "`group_team`.team_id = `team_user`.team_id").
49+
And("`team_user`.uid = ?", userID).
50+
Table("team_user").
51+
Exist()
52+
}

0 commit comments

Comments
 (0)