mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 10:44:12 +01:00 
			
		
		
		
	Add subject-type filter to list notification API endpoints (#16177)
Close #15886
This commit is contained in:
		
							parent
							
								
									f4d3bf7867
								
							
						
					
					
						commit
						9273601064
					
				@ -74,6 +74,7 @@ type FindNotificationOptions struct {
 | 
				
			|||||||
	RepoID            int64
 | 
						RepoID            int64
 | 
				
			||||||
	IssueID           int64
 | 
						IssueID           int64
 | 
				
			||||||
	Status            []NotificationStatus
 | 
						Status            []NotificationStatus
 | 
				
			||||||
 | 
						Source            []NotificationSource
 | 
				
			||||||
	UpdatedAfterUnix  int64
 | 
						UpdatedAfterUnix  int64
 | 
				
			||||||
	UpdatedBeforeUnix int64
 | 
						UpdatedBeforeUnix int64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -93,6 +94,9 @@ func (opts *FindNotificationOptions) ToCond() builder.Cond {
 | 
				
			|||||||
	if len(opts.Status) > 0 {
 | 
						if len(opts.Status) > 0 {
 | 
				
			||||||
		cond = cond.And(builder.In("notification.status", opts.Status))
 | 
							cond = cond.And(builder.In("notification.status", opts.Status))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if len(opts.Source) > 0 {
 | 
				
			||||||
 | 
							cond = cond.And(builder.In("notification.source", opts.Source))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if opts.UpdatedAfterUnix != 0 {
 | 
						if opts.UpdatedAfterUnix != 0 {
 | 
				
			||||||
		cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix})
 | 
							cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -111,13 +115,13 @@ func (opts *FindNotificationOptions) ToSession(e Engine) *xorm.Session {
 | 
				
			|||||||
	return sess
 | 
						return sess
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getNotifications(e Engine, options FindNotificationOptions) (nl NotificationList, err error) {
 | 
					func getNotifications(e Engine, options *FindNotificationOptions) (nl NotificationList, err error) {
 | 
				
			||||||
	err = options.ToSession(e).OrderBy("notification.updated_unix DESC").Find(&nl)
 | 
						err = options.ToSession(e).OrderBy("notification.updated_unix DESC").Find(&nl)
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetNotifications returns all notifications that fit to the given options.
 | 
					// GetNotifications returns all notifications that fit to the given options.
 | 
				
			||||||
func GetNotifications(opts FindNotificationOptions) (NotificationList, error) {
 | 
					func GetNotifications(opts *FindNotificationOptions) (NotificationList, error) {
 | 
				
			||||||
	return getNotifications(x, opts)
 | 
						return getNotifications(x, opts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -6,10 +6,12 @@ package notify
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/api/v1/utils"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewAvailable check if unread notifications exist
 | 
					// NewAvailable check if unread notifications exist
 | 
				
			||||||
@ -22,3 +24,44 @@ func NewAvailable(ctx *context.APIContext) {
 | 
				
			|||||||
	//     "$ref": "#/responses/NotificationCount"
 | 
						//     "$ref": "#/responses/NotificationCount"
 | 
				
			||||||
	ctx.JSON(http.StatusOK, api.NotificationCount{New: models.CountUnread(ctx.User)})
 | 
						ctx.JSON(http.StatusOK, api.NotificationCount{New: models.CountUnread(ctx.User)})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getFindNotificationOptions(ctx *context.APIContext) *models.FindNotificationOptions {
 | 
				
			||||||
 | 
						before, since, err := utils.GetQueryBeforeSince(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						opts := &models.FindNotificationOptions{
 | 
				
			||||||
 | 
							ListOptions:       utils.GetListOptions(ctx),
 | 
				
			||||||
 | 
							UserID:            ctx.User.ID,
 | 
				
			||||||
 | 
							UpdatedBeforeUnix: before,
 | 
				
			||||||
 | 
							UpdatedAfterUnix:  since,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !ctx.QueryBool("all") {
 | 
				
			||||||
 | 
							statuses := ctx.QueryStrings("status-types")
 | 
				
			||||||
 | 
							opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread", "pinned"})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						subjectTypes := ctx.QueryStrings("subject-type")
 | 
				
			||||||
 | 
						if len(subjectTypes) != 0 {
 | 
				
			||||||
 | 
							opts.Source = subjectToSource(subjectTypes)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return opts
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func subjectToSource(value []string) (result []models.NotificationSource) {
 | 
				
			||||||
 | 
						for _, v := range value {
 | 
				
			||||||
 | 
							switch strings.ToLower(v) {
 | 
				
			||||||
 | 
							case "issue":
 | 
				
			||||||
 | 
								result = append(result, models.NotificationSourceIssue)
 | 
				
			||||||
 | 
							case "pull":
 | 
				
			||||||
 | 
								result = append(result, models.NotificationSourcePullRequest)
 | 
				
			||||||
 | 
							case "commit":
 | 
				
			||||||
 | 
								result = append(result, models.NotificationSourceCommit)
 | 
				
			||||||
 | 
							case "repository":
 | 
				
			||||||
 | 
								result = append(result, models.NotificationSourceRepository)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,6 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/convert"
 | 
						"code.gitea.io/gitea/modules/convert"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/api/v1/utils"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func statusStringToNotificationStatus(status string) models.NotificationStatus {
 | 
					func statusStringToNotificationStatus(status string) models.NotificationStatus {
 | 
				
			||||||
@ -67,7 +66,6 @@ func ListRepoNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: If true, show notifications marked as read. Default value is false
 | 
						//   description: If true, show notifications marked as read. Default value is false
 | 
				
			||||||
	//   type: string
 | 
						//   type: string
 | 
				
			||||||
	//   required: false
 | 
					 | 
				
			||||||
	// - name: status-types
 | 
						// - name: status-types
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned"
 | 
						//   description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned"
 | 
				
			||||||
@ -75,19 +73,24 @@ func ListRepoNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
	//   collectionFormat: multi
 | 
						//   collectionFormat: multi
 | 
				
			||||||
	//   items:
 | 
						//   items:
 | 
				
			||||||
	//     type: string
 | 
						//     type: string
 | 
				
			||||||
	//   required: false
 | 
						// - name: subject-type
 | 
				
			||||||
 | 
						//   in: query
 | 
				
			||||||
 | 
						//   description: "filter notifications by subject type"
 | 
				
			||||||
 | 
						//   type: array
 | 
				
			||||||
 | 
						//   collectionFormat: multi
 | 
				
			||||||
 | 
						//   items:
 | 
				
			||||||
 | 
						//     type: string
 | 
				
			||||||
 | 
						//     enum: [issue,pull,commit,repository]
 | 
				
			||||||
	// - name: since
 | 
						// - name: since
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
 | 
						//   description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
 | 
				
			||||||
	//   type: string
 | 
						//   type: string
 | 
				
			||||||
	//   format: date-time
 | 
						//   format: date-time
 | 
				
			||||||
	//   required: false
 | 
					 | 
				
			||||||
	// - name: before
 | 
						// - name: before
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
 | 
						//   description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
 | 
				
			||||||
	//   type: string
 | 
						//   type: string
 | 
				
			||||||
	//   format: date-time
 | 
						//   format: date-time
 | 
				
			||||||
	//   required: false
 | 
					 | 
				
			||||||
	// - name: page
 | 
						// - name: page
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: page number of results to return (1-based)
 | 
						//   description: page number of results to return (1-based)
 | 
				
			||||||
@ -99,24 +102,12 @@ func ListRepoNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
	// responses:
 | 
						// responses:
 | 
				
			||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/NotificationThreadList"
 | 
						//     "$ref": "#/responses/NotificationThreadList"
 | 
				
			||||||
 | 
						opts := getFindNotificationOptions(ctx)
 | 
				
			||||||
	before, since, err := utils.GetQueryBeforeSince(ctx)
 | 
						if ctx.Written() {
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err)
 | 
					 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	opts := models.FindNotificationOptions{
 | 
						opts.RepoID = ctx.Repo.Repository.ID
 | 
				
			||||||
		ListOptions:       utils.GetListOptions(ctx),
 | 
					 | 
				
			||||||
		UserID:            ctx.User.ID,
 | 
					 | 
				
			||||||
		RepoID:            ctx.Repo.Repository.ID,
 | 
					 | 
				
			||||||
		UpdatedBeforeUnix: before,
 | 
					 | 
				
			||||||
		UpdatedAfterUnix:  since,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !ctx.QueryBool("all") {
 | 
					 | 
				
			||||||
		statuses := ctx.QueryStrings("status-types")
 | 
					 | 
				
			||||||
		opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread", "pinned"})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nl, err := models.GetNotifications(opts)
 | 
						nl, err := models.GetNotifications(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.InternalServerError(err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
@ -192,7 +183,7 @@ func ReadRepoNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts := models.FindNotificationOptions{
 | 
						opts := &models.FindNotificationOptions{
 | 
				
			||||||
		UserID:            ctx.User.ID,
 | 
							UserID:            ctx.User.ID,
 | 
				
			||||||
		RepoID:            ctx.Repo.Repository.ID,
 | 
							RepoID:            ctx.Repo.Repository.ID,
 | 
				
			||||||
		UpdatedBeforeUnix: lastRead,
 | 
							UpdatedBeforeUnix: lastRead,
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,6 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/convert"
 | 
						"code.gitea.io/gitea/modules/convert"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/api/v1/utils"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListNotifications list users's notification threads
 | 
					// ListNotifications list users's notification threads
 | 
				
			||||||
@ -29,7 +28,6 @@ func ListNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: If true, show notifications marked as read. Default value is false
 | 
						//   description: If true, show notifications marked as read. Default value is false
 | 
				
			||||||
	//   type: string
 | 
						//   type: string
 | 
				
			||||||
	//   required: false
 | 
					 | 
				
			||||||
	// - name: status-types
 | 
						// - name: status-types
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned."
 | 
						//   description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned."
 | 
				
			||||||
@ -37,19 +35,24 @@ func ListNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
	//   collectionFormat: multi
 | 
						//   collectionFormat: multi
 | 
				
			||||||
	//   items:
 | 
						//   items:
 | 
				
			||||||
	//     type: string
 | 
						//     type: string
 | 
				
			||||||
	//   required: false
 | 
						// - name: subject-type
 | 
				
			||||||
 | 
						//   in: query
 | 
				
			||||||
 | 
						//   description: "filter notifications by subject type"
 | 
				
			||||||
 | 
						//   type: array
 | 
				
			||||||
 | 
						//   collectionFormat: multi
 | 
				
			||||||
 | 
						//   items:
 | 
				
			||||||
 | 
						//     type: string
 | 
				
			||||||
 | 
						//     enum: [issue,pull,commit,repository]
 | 
				
			||||||
	// - name: since
 | 
						// - name: since
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
 | 
						//   description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
 | 
				
			||||||
	//   type: string
 | 
						//   type: string
 | 
				
			||||||
	//   format: date-time
 | 
						//   format: date-time
 | 
				
			||||||
	//   required: false
 | 
					 | 
				
			||||||
	// - name: before
 | 
						// - name: before
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
 | 
						//   description: Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
 | 
				
			||||||
	//   type: string
 | 
						//   type: string
 | 
				
			||||||
	//   format: date-time
 | 
						//   format: date-time
 | 
				
			||||||
	//   required: false
 | 
					 | 
				
			||||||
	// - name: page
 | 
						// - name: page
 | 
				
			||||||
	//   in: query
 | 
						//   in: query
 | 
				
			||||||
	//   description: page number of results to return (1-based)
 | 
						//   description: page number of results to return (1-based)
 | 
				
			||||||
@ -61,22 +64,11 @@ func ListNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
	// responses:
 | 
						// responses:
 | 
				
			||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/NotificationThreadList"
 | 
						//     "$ref": "#/responses/NotificationThreadList"
 | 
				
			||||||
 | 
						opts := getFindNotificationOptions(ctx)
 | 
				
			||||||
	before, since, err := utils.GetQueryBeforeSince(ctx)
 | 
						if ctx.Written() {
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err)
 | 
					 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	opts := models.FindNotificationOptions{
 | 
					
 | 
				
			||||||
		ListOptions:       utils.GetListOptions(ctx),
 | 
					 | 
				
			||||||
		UserID:            ctx.User.ID,
 | 
					 | 
				
			||||||
		UpdatedBeforeUnix: before,
 | 
					 | 
				
			||||||
		UpdatedAfterUnix:  since,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !ctx.QueryBool("all") {
 | 
					 | 
				
			||||||
		statuses := ctx.QueryStrings("status-types")
 | 
					 | 
				
			||||||
		opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread", "pinned"})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nl, err := models.GetNotifications(opts)
 | 
						nl, err := models.GetNotifications(opts)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.InternalServerError(err)
 | 
							ctx.InternalServerError(err)
 | 
				
			||||||
@ -141,7 +133,7 @@ func ReadNotifications(ctx *context.APIContext) {
 | 
				
			|||||||
			lastRead = tmpLastRead.Unix()
 | 
								lastRead = tmpLastRead.Unix()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	opts := models.FindNotificationOptions{
 | 
						opts := &models.FindNotificationOptions{
 | 
				
			||||||
		UserID:            ctx.User.ID,
 | 
							UserID:            ctx.User.ID,
 | 
				
			||||||
		UpdatedBeforeUnix: lastRead,
 | 
							UpdatedBeforeUnix: lastRead,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -645,6 +645,22 @@
 | 
				
			|||||||
            "name": "status-types",
 | 
					            "name": "status-types",
 | 
				
			||||||
            "in": "query"
 | 
					            "in": "query"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "array",
 | 
				
			||||||
 | 
					            "items": {
 | 
				
			||||||
 | 
					              "enum": [
 | 
				
			||||||
 | 
					                "issue",
 | 
				
			||||||
 | 
					                "pull",
 | 
				
			||||||
 | 
					                "commit",
 | 
				
			||||||
 | 
					                "repository"
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					              "type": "string"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "collectionFormat": "multi",
 | 
				
			||||||
 | 
					            "description": "filter notifications by subject type",
 | 
				
			||||||
 | 
					            "name": "subject-type",
 | 
				
			||||||
 | 
					            "in": "query"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            "type": "string",
 | 
					            "type": "string",
 | 
				
			||||||
            "format": "date-time",
 | 
					            "format": "date-time",
 | 
				
			||||||
@ -6805,6 +6821,22 @@
 | 
				
			|||||||
            "name": "status-types",
 | 
					            "name": "status-types",
 | 
				
			||||||
            "in": "query"
 | 
					            "in": "query"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "array",
 | 
				
			||||||
 | 
					            "items": {
 | 
				
			||||||
 | 
					              "enum": [
 | 
				
			||||||
 | 
					                "issue",
 | 
				
			||||||
 | 
					                "pull",
 | 
				
			||||||
 | 
					                "commit",
 | 
				
			||||||
 | 
					                "repository"
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					              "type": "string"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "collectionFormat": "multi",
 | 
				
			||||||
 | 
					            "description": "filter notifications by subject type",
 | 
				
			||||||
 | 
					            "name": "subject-type",
 | 
				
			||||||
 | 
					            "in": "query"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            "type": "string",
 | 
					            "type": "string",
 | 
				
			||||||
            "format": "date-time",
 | 
					            "format": "date-time",
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user