diff --git a/models/activities/action.go b/models/activities/action.go index ed63b070fd..8fc8fa6438 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -451,6 +451,7 @@ type GetFeedsOptions struct { db.ListOptions RequestedUser *user_model.User // the user we want activity for RequestedTeam *organization.Team // the team we want activity for + RequestedGroup *group_model.Group // the group we want activity for RequestedRepo *repo_model.Repository // the repo we want activity for RequestedGroup *group_model.Group // the repo group we want activity for Actor *user_model.User // the user viewing the activity @@ -531,8 +532,16 @@ func ActivityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder. if opts.Actor == nil || !opts.Actor.IsAdmin { cond = cond.And(builder.In("repo_id", repo_model.AccessibleRepoIDsQuery(opts.Actor))) } - - if opts.RequestedRepo != nil { + if opts.RequestedGroup != nil { + cond = cond.And(builder.In("`action`.repo_id", + builder.Select("id"). + From("repository"). + Where(builder.Or( + builder.In("`repository`.group_id", group_model.ChildGroupCond(opts.RequestedGroup.ID)), + builder.Eq{"`repository`.group_id": opts.RequestedGroup.ID}), + ), + )) + } else if opts.RequestedRepo != nil { // repo's actions could have duplicate items, see the comment of NotifyWatchers // so here we only filter the "original items", aka: user_id == act_user_id cond = cond.And( diff --git a/models/group/group.go b/models/group/group.go index 1cc114409d..9e379f0cfe 100644 --- a/models/group/group.go +++ b/models/group/group.go @@ -363,6 +363,23 @@ func ParentGroupCond(ctx context.Context, idStr string, groupID int64) builder.C return builder.In(idStr, groupList) } +// ChildGroupCond returns a condition recursively matching a group and its descendants +func ChildGroupCond(firstParent int64) builder.Cond { + if firstParent < 0 { + firstParent = 0 + } + return builder.Expr(`with recursive groups as ( + select * from repo_group + WHERE parent_group_id = ? + + union all + + select subgroup.* + from repo_group subgroup + join groups g on g.id = subgroup.parent_group_id + ) select g.id from groups g`, firstParent) +} + func UpdateGroup(ctx context.Context, group *Group) error { sess := db.GetEngine(ctx) _, err := sess.Table(group.TableName()).ID(group.ID).Update(group)