Skip to content

Commit 0a2d618

Browse files
authored
GetFeeds must always discard actions with dangling repo_id (#19598) (#19629)
Co-authored-by: Loïc Dachary <[email protected]> (cherry picked from commit b536b65) Conflicts: models/action_test.go The GetFeeds function does not have a Context argument in 1.16. models/action.go The SQL statement is essentially the same in 1.16 but structured differently. The Join() was copied and the created_unix field prefixed with `action`. models/action_list.go in 1.16 the loadRepoOwner method did not exist and it was done in the RetrieveFeeds method of web/feed/profile.go. The safeguard to skip when act.Repo == nil was moved there.
1 parent c8a83ac commit 0a2d618

File tree

5 files changed

+36
-6
lines changed

5 files changed

+36
-6
lines changed

models/action.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
337337

338338
actions := make([]*Action, 0, setting.UI.FeedPagingNum)
339339

340-
if err := db.GetEngine(db.DefaultContext).Limit(setting.UI.FeedPagingNum).Desc("created_unix").Where(cond).Find(&actions); err != nil {
340+
if err := db.GetEngine(db.DefaultContext).Limit(setting.UI.FeedPagingNum).Desc("`action`.created_unix").Where(cond).Join("INNER", "repository", "`repository`.id = `action`.repo_id").Find(&actions); err != nil {
341341
return nil, fmt.Errorf("Find: %v", err)
342342
}
343343

@@ -401,7 +401,7 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {
401401
cond = cond.And(builder.Eq{"act_user_id": opts.RequestedUser.ID})
402402
}
403403
if !opts.IncludePrivate {
404-
cond = cond.And(builder.Eq{"is_private": false})
404+
cond = cond.And(builder.Eq{"`action`.is_private": false})
405405
}
406406
if !opts.IncludeDeleted {
407407
cond = cond.And(builder.Eq{"is_deleted": false})
@@ -414,8 +414,8 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {
414414
} else {
415415
dateHigh := dateLow.Add(86399000000000) // 23h59m59s
416416

417-
cond = cond.And(builder.Gte{"created_unix": dateLow.Unix()})
418-
cond = cond.And(builder.Lte{"created_unix": dateHigh.Unix()})
417+
cond = cond.And(builder.Gte{"`action`.created_unix": dateLow.Unix()})
418+
cond = cond.And(builder.Lte{"`action`.created_unix": dateHigh.Unix()})
419419
}
420420
}
421421

models/action_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,20 @@ func TestNotifyWatchers(t *testing.T) {
129129
OpType: action.OpType,
130130
})
131131
}
132+
133+
func TestGetFeedsCorrupted(t *testing.T) {
134+
assert.NoError(t, unittest.PrepareTestDatabase())
135+
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User)
136+
unittest.AssertExistsAndLoadBean(t, &Action{
137+
ID: 8,
138+
RepoID: 1700,
139+
})
140+
141+
actions, err := GetFeeds(GetFeedsOptions{
142+
RequestedUser: user,
143+
Actor: user,
144+
IncludePrivate: true,
145+
})
146+
assert.NoError(t, err)
147+
assert.Len(t, actions, 0)
148+
}

models/fixtures/action.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,11 @@
5656
repo_id: 8
5757
is_private: false
5858
created_unix: 1603011540 # grouped with id:7
59+
60+
- id: 8
61+
user_id: 1
62+
op_type: 12 # close issue
63+
act_user_id: 1
64+
repo_id: 1700 # dangling intentional
65+
is_private: false
66+
created_unix: 1603011541

models/unittest/consistency.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ func init() {
175175

176176
checkForActionConsistency := func(t assert.TestingT, bean interface{}) {
177177
action := reflectionWrap(bean)
178-
repoRow := AssertExistsAndLoadMap(t, "repository", builder.Eq{"id": action.int("RepoID")})
179-
assert.Equal(t, parseBool(repoRow["is_private"]), action.bool("IsPrivate"), "action: %+v", action)
178+
if action.int("RepoID") != 1700 { // dangling intentional
179+
repoRow := AssertExistsAndLoadMap(t, "repository", builder.Eq{"id": action.int("RepoID")})
180+
assert.Equal(t, parseBool(repoRow["is_private"]), action.bool("IsPrivate"), "action: %+v", action)
181+
}
180182
}
181183

182184
consistencyCheckMap["user"] = checkForUserConsistency

routers/web/feed/profile.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ func RetrieveFeeds(ctx *context.Context, options models.GetFeedsOptions) []*mode
3434
}
3535

3636
for _, act := range actions {
37+
if act.Repo == nil {
38+
continue
39+
}
3740
repoOwner, ok := userCache[act.Repo.OwnerID]
3841
if !ok {
3942
repoOwner, err = user_model.GetUserByID(act.Repo.OwnerID)

0 commit comments

Comments
 (0)