Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4960a1e

Browse files
authored
feat(coderd): add mark-all-as-read endpoint for inbox notifications (#16976)
[Resolve this issue](coder/internal#506)Add a mark-all-as-read endpoint which is marking as read allnotifications that are not read for the authenticated user.Also adds the DB logic.
1 parentd8d4b9b commit4960a1e

File tree

15 files changed

+262
-0
lines changed

15 files changed

+262
-0
lines changed

‎coderd/apidoc/docs.go

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,7 @@ func New(options *Options) *API {
13951395
r.Use(apiKeyMiddleware)
13961396
r.Route("/inbox",func(r chi.Router) {
13971397
r.Get("/",api.listInboxNotifications)
1398+
r.Put("/mark-all-as-read",api.markAllInboxNotificationsAsRead)
13981399
r.Get("/watch",api.watchInboxNotifications)
13991400
r.Put("/{id}/read-status",api.updateInboxNotificationReadStatus)
14001401
})

‎coderd/database/dbauthz/dbauthz.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3554,6 +3554,16 @@ func (q *querier) ListWorkspaceAgentPortShares(ctx context.Context, workspaceID
35543554
returnq.db.ListWorkspaceAgentPortShares(ctx,workspaceID)
35553555
}
35563556

3557+
func (q*querier)MarkAllInboxNotificationsAsRead(ctx context.Context,arg database.MarkAllInboxNotificationsAsReadParams)error {
3558+
resource:=rbac.ResourceInboxNotification.WithOwner(arg.UserID.String())
3559+
3560+
iferr:=q.authorizeContext(ctx,policy.ActionUpdate,resource);err!=nil {
3561+
returnerr
3562+
}
3563+
3564+
returnq.db.MarkAllInboxNotificationsAsRead(ctx,arg)
3565+
}
3566+
35573567
func (q*querier)OIDCClaimFieldValues(ctx context.Context,args database.OIDCClaimFieldValuesParams) ([]string,error) {
35583568
resource:=rbac.ResourceIdpsyncSettings
35593569
ifargs.OrganizationID!=uuid.Nil {

‎coderd/database/dbauthz/dbauthz_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4653,6 +4653,15 @@ func (s *MethodTestSuite) TestNotifications() {
46534653
ReadAt: sql.NullTime{Time:readAt,Valid:true},
46544654
}).Asserts(rbac.ResourceInboxNotification.WithID(notifID).WithOwner(u.ID.String()),policy.ActionUpdate)
46554655
}))
4656+
4657+
s.Run("MarkAllInboxNotificationsAsRead",s.Subtest(func(db database.Store,check*expects) {
4658+
u:=dbgen.User(s.T(),db, database.User{})
4659+
4660+
check.Args(database.MarkAllInboxNotificationsAsReadParams{
4661+
UserID:u.ID,
4662+
ReadAt: sql.NullTime{Time:dbtestutil.NowInDefaultTimezone(),Valid:true},
4663+
}).Asserts(rbac.ResourceInboxNotification.WithOwner(u.ID.String()),policy.ActionUpdate)
4664+
}))
46564665
}
46574666

46584667
func (s*MethodTestSuite)TestOAuth2ProviderApps() {

‎coderd/database/dbmem/dbmem.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9500,6 +9500,21 @@ func (q *FakeQuerier) ListWorkspaceAgentPortShares(_ context.Context, workspaceI
95009500
returnshares,nil
95019501
}
95029502

9503+
func (q*FakeQuerier)MarkAllInboxNotificationsAsRead(_ context.Context,arg database.MarkAllInboxNotificationsAsReadParams)error {
9504+
err:=validateDatabaseType(arg)
9505+
iferr!=nil {
9506+
returnerr
9507+
}
9508+
9509+
foridx,notif:=rangeq.inboxNotifications {
9510+
ifnotif.UserID==arg.UserID&&!notif.ReadAt.Valid {
9511+
q.inboxNotifications[idx].ReadAt=arg.ReadAt
9512+
}
9513+
}
9514+
9515+
returnnil
9516+
}
9517+
95039518
// nolint:forcetypeassert
95049519
func (q*FakeQuerier)OIDCClaimFieldValues(_ context.Context,args database.OIDCClaimFieldValuesParams) ([]string,error) {
95059520
orgMembers:=q.getOrganizationMemberNoLock(args.OrganizationID)

‎coderd/database/dbmetrics/querymetrics.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dbmock/dbmock.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries.sql.go

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries/notificationsinbox.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,11 @@ SET
5757
read_at= $1
5858
WHERE
5959
id= $2;
60+
61+
-- name: MarkAllInboxNotificationsAsRead :exec
62+
UPDATE
63+
inbox_notifications
64+
SET
65+
read_at= $1
66+
WHERE
67+
user_id= $2and read_at ISNULL;

‎coderd/inboxnotifications.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,31 @@ func (api *API) updateInboxNotificationReadStatus(rw http.ResponseWriter, r *htt
344344
UnreadCount:int(unreadCount),
345345
})
346346
}
347+
348+
// markAllInboxNotificationsAsRead marks as read all unread notifications for authenticated user.
349+
// @Summary Mark all unread notifications as read
350+
// @ID mark-all-unread-notifications-as-read
351+
// @Security CoderSessionToken
352+
// @Tags Notifications
353+
// @Success 204
354+
// @Router /notifications/inbox/mark-all-as-read [put]
355+
func (api*API)markAllInboxNotificationsAsRead(rw http.ResponseWriter,r*http.Request) {
356+
var (
357+
ctx=r.Context()
358+
apikey=httpmw.APIKey(r)
359+
)
360+
361+
err:=api.Database.MarkAllInboxNotificationsAsRead(ctx, database.MarkAllInboxNotificationsAsReadParams{
362+
UserID:apikey.UserID,
363+
ReadAt: sql.NullTime{Time:dbtime.Now(),Valid:true},
364+
})
365+
iferr!=nil {
366+
api.Logger.Error(ctx,"failed to mark all unread notifications as read",slog.Error(err))
367+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
368+
Message:"Failed to mark all unread notifications as read.",
369+
})
370+
return
371+
}
372+
373+
rw.WriteHeader(http.StatusNoContent)
374+
}

‎coderd/inboxnotifications_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func TestInboxNotification_Watch(t *testing.T) {
3737
// I skip these tests specifically on windows as for now they are flaky - only on Windows.
3838
// For now the idea is that the runner takes too long to insert the entries, could be worth
3939
// investigating a manual Tx.
40+
// see: https://github.com/coder/internal/issues/503
4041
ifruntime.GOOS=="windows" {
4142
t.Skip("our runners are randomly taking too long to insert entries")
4243
}
@@ -312,6 +313,7 @@ func TestInboxNotifications_List(t *testing.T) {
312313
// I skip these tests specifically on windows as for now they are flaky - only on Windows.
313314
// For now the idea is that the runner takes too long to insert the entries, could be worth
314315
// investigating a manual Tx.
316+
// see: https://github.com/coder/internal/issues/503
315317
ifruntime.GOOS=="windows" {
316318
t.Skip("our runners are randomly taking too long to insert entries")
317319
}
@@ -595,6 +597,7 @@ func TestInboxNotifications_ReadStatus(t *testing.T) {
595597
// I skip these tests specifically on windows as for now they are flaky - only on Windows.
596598
// For now the idea is that the runner takes too long to insert the entries, could be worth
597599
// investigating a manual Tx.
600+
// see: https://github.com/coder/internal/issues/503
598601
ifruntime.GOOS=="windows" {
599602
t.Skip("our runners are randomly taking too long to insert entries")
600603
}
@@ -730,3 +733,76 @@ func TestInboxNotifications_ReadStatus(t *testing.T) {
730733
require.Empty(t,updatedNotif.Notification)
731734
})
732735
}
736+
737+
funcTestInboxNotifications_MarkAllAsRead(t*testing.T) {
738+
t.Parallel()
739+
740+
// I skip these tests specifically on windows as for now they are flaky - only on Windows.
741+
// For now the idea is that the runner takes too long to insert the entries, could be worth
742+
// investigating a manual Tx.
743+
// see: https://github.com/coder/internal/issues/503
744+
ifruntime.GOOS=="windows" {
745+
t.Skip("our runners are randomly taking too long to insert entries")
746+
}
747+
748+
t.Run("ok",func(t*testing.T) {
749+
t.Parallel()
750+
client,_,api:=coderdtest.NewWithAPI(t,&coderdtest.Options{})
751+
firstUser:=coderdtest.CreateFirstUser(t,client)
752+
client,member:=coderdtest.CreateAnotherUser(t,client,firstUser.OrganizationID)
753+
754+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
755+
defercancel()
756+
757+
notifs,err:=client.ListInboxNotifications(ctx, codersdk.ListInboxNotificationsRequest{})
758+
require.NoError(t,err)
759+
require.NotNil(t,notifs)
760+
require.Equal(t,0,notifs.UnreadCount)
761+
require.Empty(t,notifs.Notifications)
762+
763+
fori:=range20 {
764+
dbgen.NotificationInbox(t,api.Database, database.InsertInboxNotificationParams{
765+
ID:uuid.New(),
766+
UserID:member.ID,
767+
TemplateID:notifications.TemplateWorkspaceOutOfMemory,
768+
Title:fmt.Sprintf("Notification %d",i),
769+
Actions:json.RawMessage("[]"),
770+
Content:fmt.Sprintf("Content of the notif %d",i),
771+
CreatedAt:dbtime.Now(),
772+
})
773+
}
774+
775+
notifs,err=client.ListInboxNotifications(ctx, codersdk.ListInboxNotificationsRequest{})
776+
require.NoError(t,err)
777+
require.NotNil(t,notifs)
778+
require.Equal(t,20,notifs.UnreadCount)
779+
require.Len(t,notifs.Notifications,20)
780+
781+
err=client.MarkAllInboxNotificationsAsRead(ctx)
782+
require.NoError(t,err)
783+
784+
notifs,err=client.ListInboxNotifications(ctx, codersdk.ListInboxNotificationsRequest{})
785+
require.NoError(t,err)
786+
require.NotNil(t,notifs)
787+
require.Equal(t,0,notifs.UnreadCount)
788+
require.Len(t,notifs.Notifications,20)
789+
790+
fori:=range10 {
791+
dbgen.NotificationInbox(t,api.Database, database.InsertInboxNotificationParams{
792+
ID:uuid.New(),
793+
UserID:member.ID,
794+
TemplateID:notifications.TemplateWorkspaceOutOfMemory,
795+
Title:fmt.Sprintf("Notification %d",i),
796+
Actions:json.RawMessage("[]"),
797+
Content:fmt.Sprintf("Content of the notif %d",i),
798+
CreatedAt:dbtime.Now(),
799+
})
800+
}
801+
802+
notifs,err=client.ListInboxNotifications(ctx, codersdk.ListInboxNotificationsRequest{})
803+
require.NoError(t,err)
804+
require.NotNil(t,notifs)
805+
require.Equal(t,10,notifs.UnreadCount)
806+
require.Len(t,notifs.Notifications,25)
807+
})
808+
}

‎codersdk/inboxnotification.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,21 @@ func (c *Client) UpdateInboxNotificationReadStatus(ctx context.Context, notifID
109109
varrespUpdateInboxNotificationReadStatusResponse
110110
returnresp,json.NewDecoder(res.Body).Decode(&resp)
111111
}
112+
113+
func (c*Client)MarkAllInboxNotificationsAsRead(ctx context.Context)error {
114+
res,err:=c.Request(
115+
ctx,http.MethodPut,
116+
"/api/v2/notifications/inbox/mark-all-as-read",
117+
nil,
118+
)
119+
iferr!=nil {
120+
returnerr
121+
}
122+
deferres.Body.Close()
123+
124+
ifres.StatusCode!=http.StatusNoContent {
125+
returnReadBodyAsError(res)
126+
}
127+
128+
returnnil
129+
}

‎docs/reference/api/notifications.md

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp