mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(coderd): add mark-all-as-read endpoint for inbox notifications (#16976)
[Resolve this issue](https://github.com/coder/internal/issues/506) Add a mark-all-as-read endpoint which is marking as read all notifications that are not read for the authenticated user. Also adds the DB logic.
This commit is contained in:
@@ -3554,6 +3554,16 @@ func (q *querier) ListWorkspaceAgentPortShares(ctx context.Context, workspaceID
|
||||
return q.db.ListWorkspaceAgentPortShares(ctx, workspaceID)
|
||||
}
|
||||
|
||||
func (q *querier) MarkAllInboxNotificationsAsRead(ctx context.Context, arg database.MarkAllInboxNotificationsAsReadParams) error {
|
||||
resource := rbac.ResourceInboxNotification.WithOwner(arg.UserID.String())
|
||||
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, resource); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.db.MarkAllInboxNotificationsAsRead(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) OIDCClaimFieldValues(ctx context.Context, args database.OIDCClaimFieldValuesParams) ([]string, error) {
|
||||
resource := rbac.ResourceIdpsyncSettings
|
||||
if args.OrganizationID != uuid.Nil {
|
||||
|
||||
@@ -4653,6 +4653,15 @@ func (s *MethodTestSuite) TestNotifications() {
|
||||
ReadAt: sql.NullTime{Time: readAt, Valid: true},
|
||||
}).Asserts(rbac.ResourceInboxNotification.WithID(notifID).WithOwner(u.ID.String()), policy.ActionUpdate)
|
||||
}))
|
||||
|
||||
s.Run("MarkAllInboxNotificationsAsRead", s.Subtest(func(db database.Store, check *expects) {
|
||||
u := dbgen.User(s.T(), db, database.User{})
|
||||
|
||||
check.Args(database.MarkAllInboxNotificationsAsReadParams{
|
||||
UserID: u.ID,
|
||||
ReadAt: sql.NullTime{Time: dbtestutil.NowInDefaultTimezone(), Valid: true},
|
||||
}).Asserts(rbac.ResourceInboxNotification.WithOwner(u.ID.String()), policy.ActionUpdate)
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *MethodTestSuite) TestOAuth2ProviderApps() {
|
||||
|
||||
@@ -9500,6 +9500,21 @@ func (q *FakeQuerier) ListWorkspaceAgentPortShares(_ context.Context, workspaceI
|
||||
return shares, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) MarkAllInboxNotificationsAsRead(_ context.Context, arg database.MarkAllInboxNotificationsAsReadParams) error {
|
||||
err := validateDatabaseType(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for idx, notif := range q.inboxNotifications {
|
||||
if notif.UserID == arg.UserID && !notif.ReadAt.Valid {
|
||||
q.inboxNotifications[idx].ReadAt = arg.ReadAt
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// nolint:forcetypeassert
|
||||
func (q *FakeQuerier) OIDCClaimFieldValues(_ context.Context, args database.OIDCClaimFieldValuesParams) ([]string, error) {
|
||||
orgMembers := q.getOrganizationMemberNoLock(args.OrganizationID)
|
||||
|
||||
@@ -2257,6 +2257,13 @@ func (m queryMetricsStore) ListWorkspaceAgentPortShares(ctx context.Context, wor
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) MarkAllInboxNotificationsAsRead(ctx context.Context, arg database.MarkAllInboxNotificationsAsReadParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.MarkAllInboxNotificationsAsRead(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("MarkAllInboxNotificationsAsRead").Observe(time.Since(start).Seconds())
|
||||
return r0
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) OIDCClaimFieldValues(ctx context.Context, organizationID database.OIDCClaimFieldValuesParams) ([]string, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.OIDCClaimFieldValues(ctx, organizationID)
|
||||
|
||||
@@ -4763,6 +4763,20 @@ func (mr *MockStoreMockRecorder) ListWorkspaceAgentPortShares(ctx, workspaceID a
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListWorkspaceAgentPortShares", reflect.TypeOf((*MockStore)(nil).ListWorkspaceAgentPortShares), ctx, workspaceID)
|
||||
}
|
||||
|
||||
// MarkAllInboxNotificationsAsRead mocks base method.
|
||||
func (m *MockStore) MarkAllInboxNotificationsAsRead(ctx context.Context, arg database.MarkAllInboxNotificationsAsReadParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "MarkAllInboxNotificationsAsRead", ctx, arg)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// MarkAllInboxNotificationsAsRead indicates an expected call of MarkAllInboxNotificationsAsRead.
|
||||
func (mr *MockStoreMockRecorder) MarkAllInboxNotificationsAsRead(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MarkAllInboxNotificationsAsRead", reflect.TypeOf((*MockStore)(nil).MarkAllInboxNotificationsAsRead), ctx, arg)
|
||||
}
|
||||
|
||||
// OIDCClaimFieldValues mocks base method.
|
||||
func (m *MockStore) OIDCClaimFieldValues(ctx context.Context, arg database.OIDCClaimFieldValuesParams) ([]string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
@@ -469,6 +469,7 @@ type sqlcQuerier interface {
|
||||
ListProvisionerKeysByOrganization(ctx context.Context, organizationID uuid.UUID) ([]ProvisionerKey, error)
|
||||
ListProvisionerKeysByOrganizationExcludeReserved(ctx context.Context, organizationID uuid.UUID) ([]ProvisionerKey, error)
|
||||
ListWorkspaceAgentPortShares(ctx context.Context, workspaceID uuid.UUID) ([]WorkspaceAgentPortShare, error)
|
||||
MarkAllInboxNotificationsAsRead(ctx context.Context, arg MarkAllInboxNotificationsAsReadParams) error
|
||||
OIDCClaimFieldValues(ctx context.Context, arg OIDCClaimFieldValuesParams) ([]string, error)
|
||||
// OIDCClaimFields returns a list of distinct keys in the the merged_claims fields.
|
||||
// This query is used to generate the list of available sync fields for idp sync settings.
|
||||
|
||||
@@ -4511,6 +4511,25 @@ func (q *sqlQuerier) InsertInboxNotification(ctx context.Context, arg InsertInbo
|
||||
return i, err
|
||||
}
|
||||
|
||||
const markAllInboxNotificationsAsRead = `-- name: MarkAllInboxNotificationsAsRead :exec
|
||||
UPDATE
|
||||
inbox_notifications
|
||||
SET
|
||||
read_at = $1
|
||||
WHERE
|
||||
user_id = $2 and read_at IS NULL
|
||||
`
|
||||
|
||||
type MarkAllInboxNotificationsAsReadParams struct {
|
||||
ReadAt sql.NullTime `db:"read_at" json:"read_at"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) MarkAllInboxNotificationsAsRead(ctx context.Context, arg MarkAllInboxNotificationsAsReadParams) error {
|
||||
_, err := q.db.ExecContext(ctx, markAllInboxNotificationsAsRead, arg.ReadAt, arg.UserID)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateInboxNotificationReadStatus = `-- name: UpdateInboxNotificationReadStatus :exec
|
||||
UPDATE
|
||||
inbox_notifications
|
||||
|
||||
@@ -57,3 +57,11 @@ SET
|
||||
read_at = $1
|
||||
WHERE
|
||||
id = $2;
|
||||
|
||||
-- name: MarkAllInboxNotificationsAsRead :exec
|
||||
UPDATE
|
||||
inbox_notifications
|
||||
SET
|
||||
read_at = $1
|
||||
WHERE
|
||||
user_id = $2 and read_at IS NULL;
|
||||
|
||||
Reference in New Issue
Block a user