@@ -1186,44 +1186,55 @@ type IssuesOptions struct {
1186
1186
// prioritize issues from this repo
1187
1187
PriorityRepoID int64
1188
1188
IsArchived util.OptionalBool
1189
+ Org * Organization // issues permission scope
1190
+ Team * Team // issues permission scope
1191
+ User * user_model.User // issues permission scope
1189
1192
}
1190
1193
1191
1194
// sortIssuesSession sort an issues-related session based on the provided
1192
1195
// sortType string
1193
1196
func sortIssuesSession (sess * xorm.Session , sortType string , priorityRepoID int64 ) {
1194
1197
switch sortType {
1195
1198
case "oldest" :
1196
- sess .Asc ("issue.created_unix" )
1199
+ sess .Asc ("issue.created_unix" ). Asc ( "issue.id" )
1197
1200
case "recentupdate" :
1198
- sess .Desc ("issue.updated_unix" )
1201
+ sess .Desc ("issue.updated_unix" ). Desc ( "issue.created_unix" ). Desc ( "issue.id" )
1199
1202
case "leastupdate" :
1200
- sess .Asc ("issue.updated_unix" )
1203
+ sess .Asc ("issue.updated_unix" ). Asc ( "issue.created_unix" ). Asc ( "issue.id" )
1201
1204
case "mostcomment" :
1202
- sess .Desc ("issue.num_comments" )
1205
+ sess .Desc ("issue.num_comments" ). Desc ( "issue.created_unix" ). Desc ( "issue.id" )
1203
1206
case "leastcomment" :
1204
- sess .Asc ("issue.num_comments" )
1207
+ sess .Asc ("issue.num_comments" ). Desc ( "issue.created_unix" ). Desc ( "issue.id" )
1205
1208
case "priority" :
1206
- sess .Desc ("issue.priority" )
1209
+ sess .Desc ("issue.priority" ). Desc ( "issue.created_unix" ). Desc ( "issue.id" )
1207
1210
case "nearduedate" :
1208
1211
// 253370764800 is 01/01/9999 @ 12:00am (UTC)
1209
1212
sess .Join ("LEFT" , "milestone" , "issue.milestone_id = milestone.id" ).
1210
1213
OrderBy ("CASE " +
1211
1214
"WHEN issue.deadline_unix = 0 AND (milestone.deadline_unix = 0 OR milestone.deadline_unix IS NULL) THEN 253370764800 " +
1212
1215
"WHEN milestone.deadline_unix = 0 OR milestone.deadline_unix IS NULL THEN issue.deadline_unix " +
1213
1216
"WHEN milestone.deadline_unix < issue.deadline_unix OR issue.deadline_unix = 0 THEN milestone.deadline_unix " +
1214
- "ELSE issue.deadline_unix END ASC" )
1217
+ "ELSE issue.deadline_unix END ASC" ).
1218
+ Desc ("issue.created_unix" ).
1219
+ Desc ("issue.id" )
1215
1220
case "farduedate" :
1216
1221
sess .Join ("LEFT" , "milestone" , "issue.milestone_id = milestone.id" ).
1217
1222
OrderBy ("CASE " +
1218
1223
"WHEN milestone.deadline_unix IS NULL THEN issue.deadline_unix " +
1219
1224
"WHEN milestone.deadline_unix < issue.deadline_unix OR issue.deadline_unix = 0 THEN milestone.deadline_unix " +
1220
- "ELSE issue.deadline_unix END DESC" )
1225
+ "ELSE issue.deadline_unix END DESC" ).
1226
+ Desc ("issue.created_unix" ).
1227
+ Desc ("issue.id" )
1221
1228
case "priorityrepo" :
1222
- sess .OrderBy ("CASE WHEN issue.repo_id = " + strconv .FormatInt (priorityRepoID , 10 ) + " THEN 1 ELSE 2 END, issue.created_unix DESC" )
1229
+ sess .OrderBy ("CASE " +
1230
+ "WHEN issue.repo_id = " + strconv .FormatInt (priorityRepoID , 10 ) + " THEN 1 " +
1231
+ "ELSE 2 END ASC" ).
1232
+ Desc ("issue.created_unix" ).
1233
+ Desc ("issue.id" )
1223
1234
case "project-column-sorting" :
1224
- sess .Asc ("project_issue.sorting" )
1235
+ sess .Asc ("project_issue.sorting" ). Desc ( "issue.created_unix" ). Desc ( "issue.id" )
1225
1236
default :
1226
- sess .Desc ("issue.created_unix" )
1237
+ sess .Desc ("issue.created_unix" ). Desc ( "issue.id" )
1227
1238
}
1228
1239
}
1229
1240
@@ -1329,6 +1340,44 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
1329
1340
From ("milestone" ).
1330
1341
Where (builder .In ("name" , opts .IncludeMilestones )))
1331
1342
}
1343
+
1344
+ if opts .User != nil {
1345
+ sess .And (
1346
+ issuePullAccessibleRepoCond ("issue.repo_id" , opts .User .ID , opts .Org , opts .Team , opts .IsPull .IsTrue ()),
1347
+ )
1348
+ }
1349
+ }
1350
+
1351
+ // issuePullAccessibleRepoCond userID must not be zero, this condition require join repository table
1352
+ func issuePullAccessibleRepoCond (repoIDstr string , userID int64 , org * Organization , team * Team , isPull bool ) builder.Cond {
1353
+ var cond = builder .NewCond ()
1354
+ var unitType = unit .TypeIssues
1355
+ if isPull {
1356
+ unitType = unit .TypePullRequests
1357
+ }
1358
+ if org != nil {
1359
+ if team != nil {
1360
+ cond = cond .And (teamUnitsRepoCond (repoIDstr , userID , org .ID , team .ID , unitType )) // special team member repos
1361
+ } else {
1362
+ cond = cond .And (
1363
+ builder .Or (
1364
+ userOrgUnitRepoCond (repoIDstr , userID , org .ID , unitType ), // team member repos
1365
+ userOrgPublicUnitRepoCond (userID , org .ID ), // user org public non-member repos, TODO: check repo has issues
1366
+ ),
1367
+ )
1368
+ }
1369
+ } else {
1370
+ cond = cond .And (
1371
+ builder .Or (
1372
+ userOwnedRepoCond (userID ), // owned repos
1373
+ userCollaborationRepoCond (repoIDstr , userID ), // collaboration repos
1374
+ userAssignedRepoCond (repoIDstr , userID ), // user has been assigned accessible public repos
1375
+ userMentionedRepoCond (repoIDstr , userID ), // user has been mentioned accessible public repos
1376
+ userCreateIssueRepoCond (repoIDstr , userID , isPull ), // user has created issue/pr accessible public repos
1377
+ ),
1378
+ )
1379
+ }
1380
+ return cond
1332
1381
}
1333
1382
1334
1383
func applyReposCondition (sess * xorm.Session , repoIDs []int64 ) * xorm.Session {
@@ -1638,15 +1687,16 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats,
1638
1687
1639
1688
// UserIssueStatsOptions contains parameters accepted by GetUserIssueStats.
1640
1689
type UserIssueStatsOptions struct {
1641
- UserID int64
1642
- RepoIDs []int64
1643
- UserRepoIDs []int64
1644
- FilterMode int
1645
- IsPull bool
1646
- IsClosed bool
1647
- IssueIDs []int64
1648
- IsArchived util.OptionalBool
1649
- LabelIDs []int64
1690
+ UserID int64
1691
+ RepoIDs []int64
1692
+ FilterMode int
1693
+ IsPull bool
1694
+ IsClosed bool
1695
+ IssueIDs []int64
1696
+ IsArchived util.OptionalBool
1697
+ LabelIDs []int64
1698
+ Org * Organization
1699
+ Team * Team
1650
1700
}
1651
1701
1652
1702
// GetUserIssueStats returns issue statistic information for dashboard by given conditions.
@@ -1663,28 +1713,34 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
1663
1713
cond = cond .And (builder .In ("issue.id" , opts .IssueIDs ))
1664
1714
}
1665
1715
1716
+ if opts .UserID > 0 {
1717
+ cond = cond .And (issuePullAccessibleRepoCond ("issue.repo_id" , opts .UserID , opts .Org , opts .Team , opts .IsPull ))
1718
+ }
1719
+
1666
1720
sess := func (cond builder.Cond ) * xorm.Session {
1667
1721
s := db .GetEngine (db .DefaultContext ).Where (cond )
1668
1722
if len (opts .LabelIDs ) > 0 {
1669
1723
s .Join ("INNER" , "issue_label" , "issue_label.issue_id = issue.id" ).
1670
1724
In ("issue_label.label_id" , opts .LabelIDs )
1671
1725
}
1672
- if opts .IsArchived != util .OptionalBoolNone {
1673
- s .Join ("INNER" , "repository" , "issue.repo_id = repository.id" ).
1674
- And (builder.Eq {"repository.is_archived" : opts .IsArchived .IsTrue ()})
1726
+ if opts .UserID > 0 || opts .IsArchived != util .OptionalBoolNone {
1727
+ s .Join ("INNER" , "repository" , "issue.repo_id = repository.id" )
1728
+ if opts .IsArchived != util .OptionalBoolNone {
1729
+ s .And (builder.Eq {"repository.is_archived" : opts .IsArchived .IsTrue ()})
1730
+ }
1675
1731
}
1676
1732
return s
1677
1733
}
1678
1734
1679
1735
switch opts .FilterMode {
1680
1736
case FilterModeAll :
1681
- stats .OpenCount , err = applyReposCondition ( sess (cond ), opts . UserRepoIDs ).
1737
+ stats .OpenCount , err = sess (cond ).
1682
1738
And ("issue.is_closed = ?" , false ).
1683
1739
Count (new (Issue ))
1684
1740
if err != nil {
1685
1741
return nil , err
1686
1742
}
1687
- stats .ClosedCount , err = applyReposCondition ( sess (cond ), opts . UserRepoIDs ).
1743
+ stats .ClosedCount , err = sess (cond ).
1688
1744
And ("issue.is_closed = ?" , true ).
1689
1745
Count (new (Issue ))
1690
1746
if err != nil {
@@ -1760,7 +1816,7 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
1760
1816
return nil , err
1761
1817
}
1762
1818
1763
- stats .YourRepositoriesCount , err = applyReposCondition ( sess (cond ), opts . UserRepoIDs ).Count (new (Issue ))
1819
+ stats .YourRepositoriesCount , err = sess (cond ).Count (new (Issue ))
1764
1820
if err != nil {
1765
1821
return nil , err
1766
1822
}
0 commit comments