* notifications api: return updated notifications in response * make generate-swagger * openapi fix Co-authored-by: zeripath <art27@cantab.net>tags/v1.16.0-rc1
} | } | ||||
// 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 |
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) { |
"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) | |||||
} | } |
// 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 { |
"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) | |||||
} | } |
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 | ||||
} | } |
], | ], | ||||
"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" | |||||
} | } | ||||
} | } | ||||
} | } |