Skip to content

Commit b536b65

Browse files
singuliereLoïc Dachary
andauthored
GetFeeds must always discard actions with dangling repo_id (#19598)
* GetFeeds must always discard actions with dangling repo_id See https://discourse.gitea.io/t/blank-page-after-login/5051/12 for a panic in 1.16.6. * add comment to explain the dangling ID in the fixture * loadRepoOwner must not attempt to use a nil action.Repo * make fmt Co-authored-by: Loïc Dachary <[email protected]>
1 parent 04fc4b7 commit b536b65

File tree

5 files changed

+37
-7
lines changed

5 files changed

+37
-7
lines changed

models/action.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -340,14 +340,14 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, error) {
340340
}
341341

342342
e := db.GetEngine(ctx)
343-
sess := e.Where(cond)
343+
sess := e.Where(cond).Join("INNER", "repository", "`repository`.id = `action`.repo_id")
344344

345345
opts.SetDefaultValues()
346346
sess = db.SetSessionPagination(sess, &opts)
347347

348348
actions := make([]*Action, 0, opts.PageSize)
349349

350-
if err := sess.Desc("created_unix").Find(&actions); err != nil {
350+
if err := sess.Desc("`action`.created_unix").Find(&actions); err != nil {
351351
return nil, fmt.Errorf("Find: %v", err)
352352
}
353353

@@ -417,7 +417,7 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {
417417
}
418418

419419
if !opts.IncludePrivate {
420-
cond = cond.And(builder.Eq{"is_private": false})
420+
cond = cond.And(builder.Eq{"`action`.is_private": false})
421421
}
422422
if !opts.IncludeDeleted {
423423
cond = cond.And(builder.Eq{"is_deleted": false})
@@ -430,8 +430,8 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {
430430
} else {
431431
dateHigh := dateLow.Add(86399000000000) // 23h59m59s
432432

433-
cond = cond.And(builder.Gte{"created_unix": dateLow.Unix()})
434-
cond = cond.And(builder.Lte{"created_unix": dateHigh.Unix()})
433+
cond = cond.And(builder.Gte{"`action`.created_unix": dateLow.Unix()})
434+
cond = cond.And(builder.Lte{"`action`.created_unix": dateHigh.Unix()})
435435
}
436436
}
437437

models/action_list.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ func (actions ActionList) loadRepoOwner(e db.Engine, userMap map[int64]*user_mod
8080
}
8181

8282
for _, action := range actions {
83+
if action.Repo == nil {
84+
continue
85+
}
8386
repoOwner, ok := userMap[action.Repo.OwnerID]
8487
if !ok {
8588
repoOwner, err = user_model.GetUserByID(action.Repo.OwnerID)

models/action_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,20 @@ func TestNotifyWatchers(t *testing.T) {
211211
OpType: action.OpType,
212212
})
213213
}
214+
215+
func TestGetFeedsCorrupted(t *testing.T) {
216+
assert.NoError(t, unittest.PrepareTestDatabase())
217+
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User)
218+
unittest.AssertExistsAndLoadBean(t, &Action{
219+
ID: 8,
220+
RepoID: 1700,
221+
})
222+
223+
actions, err := GetFeeds(db.DefaultContext, GetFeedsOptions{
224+
RequestedUser: user,
225+
Actor: user,
226+
IncludePrivate: true,
227+
})
228+
assert.NoError(t, err)
229+
assert.Len(t, actions, 0)
230+
}

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 # public
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

0 commit comments

Comments
 (0)