Browse Source

Notifications API: respond with updated notifications (#17064)

* notifications api: return updated notifications in response

* make generate-swagger

* openapi fix

Co-authored-by: zeripath <art27@cantab.net>
tags/v1.16.0-rc1
Norwin 2 years ago
parent
commit
0ffad31b92
No account linked to committer's email address

+ 4
- 4
models/notification.go View File

} }


// SetNotificationStatus change the notification status // SetNotificationStatus change the notification status
func SetNotificationStatus(notificationID int64, user *User, status NotificationStatus) error {
func SetNotificationStatus(notificationID int64, user *User, status NotificationStatus) (*Notification, error) {
notification, err := getNotificationByID(x, notificationID) notification, err := getNotificationByID(x, notificationID)
if err != nil { if err != nil {
return err
return notification, err
} }


if notification.UserID != user.ID { if notification.UserID != user.ID {
return fmt.Errorf("Can't change notification of another user: %d, %d", notification.UserID, user.ID)
return nil, fmt.Errorf("Can't change notification of another user: %d, %d", notification.UserID, user.ID)
} }


notification.Status = status notification.Status = status


_, err = x.ID(notificationID).Update(notification) _, err = x.ID(notificationID).Update(notification)
return err
return notification, err
} }


// GetNotificationByID return notification by ID // GetNotificationByID return notification by ID

+ 6
- 3
models/notification_test.go View File

user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
notf := AssertExistsAndLoadBean(t, notf := AssertExistsAndLoadBean(t,
&Notification{UserID: user.ID, Status: NotificationStatusRead}).(*Notification) &Notification{UserID: user.ID, Status: NotificationStatusRead}).(*Notification)
assert.NoError(t, SetNotificationStatus(notf.ID, user, NotificationStatusPinned))
_, err := SetNotificationStatus(notf.ID, user, NotificationStatusPinned)
assert.NoError(t, err)
AssertExistsAndLoadBean(t, AssertExistsAndLoadBean(t,
&Notification{ID: notf.ID, Status: NotificationStatusPinned}) &Notification{ID: notf.ID, Status: NotificationStatusPinned})


assert.Error(t, SetNotificationStatus(1, user, NotificationStatusRead))
assert.Error(t, SetNotificationStatus(NonexistentID, user, NotificationStatusRead))
_, err = SetNotificationStatus(1, user, NotificationStatusRead)
assert.Error(t, err)
_, err = SetNotificationStatus(NonexistentID, user, NotificationStatusRead)
assert.Error(t, err)
} }


func TestUpdateNotificationStatuses(t *testing.T) { func TestUpdateNotificationStatuses(t *testing.T) {

+ 8
- 5
routers/api/v1/notify/repo.go View File

"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/modules/structs"
) )


func statusStringToNotificationStatus(status string) models.NotificationStatus { func statusStringToNotificationStatus(status string) models.NotificationStatus {
// required: false // required: false
// responses: // responses:
// "205": // "205":
// "$ref": "#/responses/empty"
// "$ref": "#/responses/NotificationThreadList"


lastRead := int64(0) lastRead := int64(0)
qLastRead := ctx.FormTrim("last_read_at") qLastRead := ctx.FormTrim("last_read_at")
targetStatus = models.NotificationStatusRead targetStatus = models.NotificationStatusRead
} }


changed := make([]*structs.NotificationThread, len(nl))

for _, n := range nl { for _, n := range nl {
err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
notif, err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
if err != nil { if err != nil {
ctx.InternalServerError(err) ctx.InternalServerError(err)
return return
} }
ctx.Status(http.StatusResetContent)
_ = notif.LoadAttributes()
changed = append(changed, convert.ToNotificationThread(notif))
} }

ctx.Status(http.StatusResetContent)
ctx.JSON(http.StatusResetContent, changed)
} }

+ 7
- 3
routers/api/v1/notify/threads.go View File

// required: false // required: false
// responses: // responses:
// "205": // "205":
// "$ref": "#/responses/empty"
// "$ref": "#/responses/NotificationThread"
// "403": // "403":
// "$ref": "#/responses/forbidden" // "$ref": "#/responses/forbidden"
// "404": // "404":
targetStatus = models.NotificationStatusRead targetStatus = models.NotificationStatusRead
} }


err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
notif, err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
if err != nil { if err != nil {
ctx.InternalServerError(err) ctx.InternalServerError(err)
return return
} }
ctx.Status(http.StatusResetContent)
if err = notif.LoadAttributes(); err != nil {
ctx.InternalServerError(err)
return
}
ctx.JSON(http.StatusResetContent, convert.ToNotificationThread(notif))
} }


func getThread(ctx *context.APIContext) *models.Notification { func getThread(ctx *context.APIContext) *models.Notification {

+ 8
- 4
routers/api/v1/notify/user.go View File

"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/modules/structs"
) )


// ListNotifications list users's notification threads // ListNotifications list users's notification threads
// required: false // required: false
// responses: // responses:
// "205": // "205":
// "$ref": "#/responses/empty"
// "$ref": "#/responses/NotificationThreadList"


lastRead := int64(0) lastRead := int64(0)
qLastRead := ctx.FormTrim("last_read_at") qLastRead := ctx.FormTrim("last_read_at")
targetStatus = models.NotificationStatusRead targetStatus = models.NotificationStatusRead
} }


changed := make([]*structs.NotificationThread, 0, len(nl))

for _, n := range nl { for _, n := range nl {
err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
notif, err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
if err != nil { if err != nil {
ctx.InternalServerError(err) ctx.InternalServerError(err)
return return
} }
ctx.Status(http.StatusResetContent)
_ = notif.LoadAttributes()
changed = append(changed, convert.ToNotificationThread(notif))
} }


ctx.Status(http.StatusResetContent)
ctx.JSON(http.StatusResetContent, changed)
} }

+ 1
- 1
routers/web/user/notification.go View File

return return
} }


if err := models.SetNotificationStatus(notificationID, c.User, status); err != nil {
if _, err := models.SetNotificationStatus(notificationID, c.User, status); err != nil {
c.ServerError("SetNotificationStatus", err) c.ServerError("SetNotificationStatus", err)
return return
} }

+ 3
- 3
templates/swagger/v1_json.tmpl View File

], ],
"responses": { "responses": {
"205": { "205": {
"$ref": "#/responses/empty"
"$ref": "#/responses/NotificationThreadList"
} }
} }
} }
], ],
"responses": { "responses": {
"205": { "205": {
"$ref": "#/responses/empty"
"$ref": "#/responses/NotificationThread"
}, },
"403": { "403": {
"$ref": "#/responses/forbidden" "$ref": "#/responses/forbidden"
], ],
"responses": { "responses": {
"205": { "205": {
"$ref": "#/responses/empty"
"$ref": "#/responses/NotificationThreadList"
} }
} }
} }

Loading…
Cancel
Save