Skip to content

Commit 9273601

Browse files
authored
Add subject-type filter to list notification API endpoints (#16177)
Close #15886
1 parent f4d3bf7 commit 9273601

File tree

5 files changed

+105
-43
lines changed

5 files changed

+105
-43
lines changed

models/notification.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type FindNotificationOptions struct {
7474
RepoID int64
7575
IssueID int64
7676
Status []NotificationStatus
77+
Source []NotificationSource
7778
UpdatedAfterUnix int64
7879
UpdatedBeforeUnix int64
7980
}
@@ -93,6 +94,9 @@ func (opts *FindNotificationOptions) ToCond() builder.Cond {
9394
if len(opts.Status) > 0 {
9495
cond = cond.And(builder.In("notification.status", opts.Status))
9596
}
97+
if len(opts.Source) > 0 {
98+
cond = cond.And(builder.In("notification.source", opts.Source))
99+
}
96100
if opts.UpdatedAfterUnix != 0 {
97101
cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix})
98102
}
@@ -111,13 +115,13 @@ func (opts *FindNotificationOptions) ToSession(e Engine) *xorm.Session {
111115
return sess
112116
}
113117

114-
func getNotifications(e Engine, options FindNotificationOptions) (nl NotificationList, err error) {
118+
func getNotifications(e Engine, options *FindNotificationOptions) (nl NotificationList, err error) {
115119
err = options.ToSession(e).OrderBy("notification.updated_unix DESC").Find(&nl)
116120
return
117121
}
118122

119123
// GetNotifications returns all notifications that fit to the given options.
120-
func GetNotifications(opts FindNotificationOptions) (NotificationList, error) {
124+
func GetNotifications(opts *FindNotificationOptions) (NotificationList, error) {
121125
return getNotifications(x, opts)
122126
}
123127

routers/api/v1/notify/notifications.go

+43
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ package notify
66

77
import (
88
"net/http"
9+
"strings"
910

1011
"code.gitea.io/gitea/models"
1112
"code.gitea.io/gitea/modules/context"
1213
api "code.gitea.io/gitea/modules/structs"
14+
"code.gitea.io/gitea/routers/api/v1/utils"
1315
)
1416

1517
// NewAvailable check if unread notifications exist
@@ -22,3 +24,44 @@ func NewAvailable(ctx *context.APIContext) {
2224
// "$ref": "#/responses/NotificationCount"
2325
ctx.JSON(http.StatusOK, api.NotificationCount{New: models.CountUnread(ctx.User)})
2426
}
27+
28+
func getFindNotificationOptions(ctx *context.APIContext) *models.FindNotificationOptions {
29+
before, since, err := utils.GetQueryBeforeSince(ctx)
30+
if err != nil {
31+
ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err)
32+
return nil
33+
}
34+
opts := &models.FindNotificationOptions{
35+
ListOptions: utils.GetListOptions(ctx),
36+
UserID: ctx.User.ID,
37+
UpdatedBeforeUnix: before,
38+
UpdatedAfterUnix: since,
39+
}
40+
if !ctx.QueryBool("all") {
41+
statuses := ctx.QueryStrings("status-types")
42+
opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread", "pinned"})
43+
}
44+
45+
subjectTypes := ctx.QueryStrings("subject-type")
46+
if len(subjectTypes) != 0 {
47+
opts.Source = subjectToSource(subjectTypes)
48+
}
49+
50+
return opts
51+
}
52+
53+
func subjectToSource(value []string) (result []models.NotificationSource) {
54+
for _, v := range value {
55+
switch strings.ToLower(v) {
56+
case "issue":
57+
result = append(result, models.NotificationSourceIssue)
58+
case "pull":
59+
result = append(result, models.NotificationSourcePullRequest)
60+
case "commit":
61+
result = append(result, models.NotificationSourceCommit)
62+
case "repository":
63+
result = append(result, models.NotificationSourceRepository)
64+
}
65+
}
66+
return
67+
}

routers/api/v1/notify/repo.go

+12-21
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"code.gitea.io/gitea/modules/context"
1414
"code.gitea.io/gitea/modules/convert"
1515
"code.gitea.io/gitea/modules/log"
16-
"code.gitea.io/gitea/routers/api/v1/utils"
1716
)
1817

1918
func statusStringToNotificationStatus(status string) models.NotificationStatus {
@@ -67,27 +66,31 @@ func ListRepoNotifications(ctx *context.APIContext) {
6766
// in: query
6867
// description: If true, show notifications marked as read. Default value is false
6968
// type: string
70-
// required: false
7169
// - name: status-types
7270
// in: query
7371
// description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned"
7472
// type: array
7573
// collectionFormat: multi
7674
// items:
7775
// type: string
78-
// required: false
76+
// - name: subject-type
77+
// in: query
78+
// description: "filter notifications by subject type"
79+
// type: array
80+
// collectionFormat: multi
81+
// items:
82+
// type: string
83+
// enum: [issue,pull,commit,repository]
7984
// - name: since
8085
// in: query
8186
// description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
8287
// type: string
8388
// format: date-time
84-
// required: false
8589
// - name: before
8690
// in: query
8791
// description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
8892
// type: string
8993
// format: date-time
90-
// required: false
9194
// - name: page
9295
// in: query
9396
// description: page number of results to return (1-based)
@@ -99,24 +102,12 @@ func ListRepoNotifications(ctx *context.APIContext) {
99102
// responses:
100103
// "200":
101104
// "$ref": "#/responses/NotificationThreadList"
102-
103-
before, since, err := utils.GetQueryBeforeSince(ctx)
104-
if err != nil {
105-
ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err)
105+
opts := getFindNotificationOptions(ctx)
106+
if ctx.Written() {
106107
return
107108
}
108-
opts := models.FindNotificationOptions{
109-
ListOptions: utils.GetListOptions(ctx),
110-
UserID: ctx.User.ID,
111-
RepoID: ctx.Repo.Repository.ID,
112-
UpdatedBeforeUnix: before,
113-
UpdatedAfterUnix: since,
114-
}
109+
opts.RepoID = ctx.Repo.Repository.ID
115110

116-
if !ctx.QueryBool("all") {
117-
statuses := ctx.QueryStrings("status-types")
118-
opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread", "pinned"})
119-
}
120111
nl, err := models.GetNotifications(opts)
121112
if err != nil {
122113
ctx.InternalServerError(err)
@@ -192,7 +183,7 @@ func ReadRepoNotifications(ctx *context.APIContext) {
192183
}
193184
}
194185

195-
opts := models.FindNotificationOptions{
186+
opts := &models.FindNotificationOptions{
196187
UserID: ctx.User.ID,
197188
RepoID: ctx.Repo.Repository.ID,
198189
UpdatedBeforeUnix: lastRead,

routers/api/v1/notify/user.go

+12-20
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"code.gitea.io/gitea/models"
1313
"code.gitea.io/gitea/modules/context"
1414
"code.gitea.io/gitea/modules/convert"
15-
"code.gitea.io/gitea/routers/api/v1/utils"
1615
)
1716

1817
// ListNotifications list users's notification threads
@@ -29,27 +28,31 @@ func ListNotifications(ctx *context.APIContext) {
2928
// in: query
3029
// description: If true, show notifications marked as read. Default value is false
3130
// type: string
32-
// required: false
3331
// - name: status-types
3432
// in: query
3533
// description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned."
3634
// type: array
3735
// collectionFormat: multi
3836
// items:
3937
// type: string
40-
// required: false
38+
// - name: subject-type
39+
// in: query
40+
// description: "filter notifications by subject type"
41+
// type: array
42+
// collectionFormat: multi
43+
// items:
44+
// type: string
45+
// enum: [issue,pull,commit,repository]
4146
// - name: since
4247
// in: query
4348
// description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
4449
// type: string
4550
// format: date-time
46-
// required: false
4751
// - name: before
4852
// in: query
4953
// description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
5054
// type: string
5155
// format: date-time
52-
// required: false
5356
// - name: page
5457
// in: query
5558
// description: page number of results to return (1-based)
@@ -61,22 +64,11 @@ func ListNotifications(ctx *context.APIContext) {
6164
// responses:
6265
// "200":
6366
// "$ref": "#/responses/NotificationThreadList"
64-
65-
before, since, err := utils.GetQueryBeforeSince(ctx)
66-
if err != nil {
67-
ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err)
67+
opts := getFindNotificationOptions(ctx)
68+
if ctx.Written() {
6869
return
6970
}
70-
opts := models.FindNotificationOptions{
71-
ListOptions: utils.GetListOptions(ctx),
72-
UserID: ctx.User.ID,
73-
UpdatedBeforeUnix: before,
74-
UpdatedAfterUnix: since,
75-
}
76-
if !ctx.QueryBool("all") {
77-
statuses := ctx.QueryStrings("status-types")
78-
opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread", "pinned"})
79-
}
71+
8072
nl, err := models.GetNotifications(opts)
8173
if err != nil {
8274
ctx.InternalServerError(err)
@@ -141,7 +133,7 @@ func ReadNotifications(ctx *context.APIContext) {
141133
lastRead = tmpLastRead.Unix()
142134
}
143135
}
144-
opts := models.FindNotificationOptions{
136+
opts := &models.FindNotificationOptions{
145137
UserID: ctx.User.ID,
146138
UpdatedBeforeUnix: lastRead,
147139
}

templates/swagger/v1_json.tmpl

+32
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,22 @@
645645
"name": "status-types",
646646
"in": "query"
647647
},
648+
{
649+
"type": "array",
650+
"items": {
651+
"enum": [
652+
"issue",
653+
"pull",
654+
"commit",
655+
"repository"
656+
],
657+
"type": "string"
658+
},
659+
"collectionFormat": "multi",
660+
"description": "filter notifications by subject type",
661+
"name": "subject-type",
662+
"in": "query"
663+
},
648664
{
649665
"type": "string",
650666
"format": "date-time",
@@ -6805,6 +6821,22 @@
68056821
"name": "status-types",
68066822
"in": "query"
68076823
},
6824+
{
6825+
"type": "array",
6826+
"items": {
6827+
"enum": [
6828+
"issue",
6829+
"pull",
6830+
"commit",
6831+
"repository"
6832+
],
6833+
"type": "string"
6834+
},
6835+
"collectionFormat": "multi",
6836+
"description": "filter notifications by subject type",
6837+
"name": "subject-type",
6838+
"in": "query"
6839+
},
68086840
{
68096841
"type": "string",
68106842
"format": "date-time",

0 commit comments

Comments
 (0)