feat: add notifications inbox db (#16599)

This PR is linked [to the following
issue](https://github.com/coder/internal/issues/334).

The objective is to create the DB layer and migration for the new `Coder
Inbox`.
This commit is contained in:
Vincent Vielle
2025-03-03 10:12:48 +01:00
committed by GitHub
parent d0e2060692
commit c074f77a4f
27 changed files with 966 additions and 0 deletions
+130
View File
@@ -67,6 +67,7 @@ func New() database.Store {
gitSSHKey: make([]database.GitSSHKey, 0),
notificationMessages: make([]database.NotificationMessage, 0),
notificationPreferences: make([]database.NotificationPreference, 0),
InboxNotification: make([]database.InboxNotification, 0),
parameterSchemas: make([]database.ParameterSchema, 0),
provisionerDaemons: make([]database.ProvisionerDaemon, 0),
provisionerKeys: make([]database.ProvisionerKey, 0),
@@ -206,6 +207,7 @@ type data struct {
notificationMessages []database.NotificationMessage
notificationPreferences []database.NotificationPreference
notificationReportGeneratorLogs []database.NotificationReportGeneratorLog
InboxNotification []database.InboxNotification
oauth2ProviderApps []database.OAuth2ProviderApp
oauth2ProviderAppSecrets []database.OAuth2ProviderAppSecret
oauth2ProviderAppCodes []database.OAuth2ProviderAppCode
@@ -1606,6 +1608,26 @@ func (*FakeQuerier) CleanTailnetTunnels(context.Context) error {
return ErrUnimplemented
}
func (q *FakeQuerier) CountUnreadInboxNotificationsByUserID(_ context.Context, userID uuid.UUID) (int64, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
var count int64
for _, notification := range q.InboxNotification {
if notification.UserID != userID {
continue
}
if notification.ReadAt.Valid {
continue
}
count++
}
return count, nil
}
func (q *FakeQuerier) CustomRoles(_ context.Context, arg database.CustomRolesParams) ([]database.CustomRole, error) {
q.mutex.Lock()
defer q.mutex.Unlock()
@@ -3130,6 +3152,45 @@ func (q *FakeQuerier) GetFileTemplates(_ context.Context, id uuid.UUID) ([]datab
return rows, nil
}
func (q *FakeQuerier) GetFilteredInboxNotificationsByUserID(_ context.Context, arg database.GetFilteredInboxNotificationsByUserIDParams) ([]database.InboxNotification, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
notifications := make([]database.InboxNotification, 0)
for _, notification := range q.InboxNotification {
if notification.UserID == arg.UserID {
for _, template := range arg.Templates {
templateFound := false
if notification.TemplateID == template {
templateFound = true
}
if !templateFound {
continue
}
}
for _, target := range arg.Targets {
isFound := false
for _, insertedTarget := range notification.Targets {
if insertedTarget == target {
isFound = true
break
}
}
if !isFound {
continue
}
notifications = append(notifications, notification)
}
}
}
return notifications, nil
}
func (q *FakeQuerier) GetGitSSHKey(_ context.Context, userID uuid.UUID) (database.GitSSHKey, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
@@ -3328,6 +3389,33 @@ func (q *FakeQuerier) GetHungProvisionerJobs(_ context.Context, hungSince time.T
return hungJobs, nil
}
func (q *FakeQuerier) GetInboxNotificationByID(_ context.Context, id uuid.UUID) (database.InboxNotification, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
for _, notification := range q.InboxNotification {
if notification.ID == id {
return notification, nil
}
}
return database.InboxNotification{}, sql.ErrNoRows
}
func (q *FakeQuerier) GetInboxNotificationsByUserID(_ context.Context, params database.GetInboxNotificationsByUserIDParams) ([]database.InboxNotification, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
notifications := make([]database.InboxNotification, 0)
for _, notification := range q.InboxNotification {
if notification.UserID == params.UserID {
notifications = append(notifications, notification)
}
}
return notifications, nil
}
func (q *FakeQuerier) GetJFrogXrayScanByWorkspaceAndAgentID(_ context.Context, arg database.GetJFrogXrayScanByWorkspaceAndAgentIDParams) (database.JfrogXrayScan, error) {
err := validateDatabaseType(arg)
if err != nil {
@@ -7965,6 +8053,30 @@ func (q *FakeQuerier) InsertGroupMember(_ context.Context, arg database.InsertGr
return nil
}
func (q *FakeQuerier) InsertInboxNotification(_ context.Context, arg database.InsertInboxNotificationParams) (database.InboxNotification, error) {
if err := validateDatabaseType(arg); err != nil {
return database.InboxNotification{}, err
}
q.mutex.Lock()
defer q.mutex.Unlock()
notification := database.InboxNotification{
ID: arg.ID,
UserID: arg.UserID,
TemplateID: arg.TemplateID,
Targets: arg.Targets,
Title: arg.Title,
Content: arg.Content,
Icon: arg.Icon,
Actions: arg.Actions,
CreatedAt: time.Now(),
}
q.InboxNotification = append(q.InboxNotification, notification)
return notification, nil
}
func (q *FakeQuerier) InsertLicense(
_ context.Context, arg database.InsertLicenseParams,
) (database.License, error) {
@@ -9679,6 +9791,24 @@ func (q *FakeQuerier) UpdateInactiveUsersToDormant(_ context.Context, params dat
return updated, nil
}
func (q *FakeQuerier) UpdateInboxNotificationReadStatus(_ context.Context, arg database.UpdateInboxNotificationReadStatusParams) error {
err := validateDatabaseType(arg)
if err != nil {
return err
}
q.mutex.Lock()
defer q.mutex.Unlock()
for i := range q.InboxNotification {
if q.InboxNotification[i].ID == arg.ID {
q.InboxNotification[i].ReadAt = arg.ReadAt
}
}
return nil
}
func (q *FakeQuerier) UpdateMemberRoles(_ context.Context, arg database.UpdateMemberRolesParams) (database.OrganizationMember, error) {
if err := validateDatabaseType(arg); err != nil {
return database.OrganizationMember{}, err