diff --git a/userapi/storage/interface.go b/userapi/storage/interface.go index 89d767f6b..50595cd74 100644 --- a/userapi/storage/interface.go +++ b/userapi/storage/interface.go @@ -116,26 +116,29 @@ type ThreePID interface { GetThreePIDsForLocalpart(ctx context.Context, localpart string) (threepids []authtypes.ThreePID, err error) } -type Database interface { - Account - AccountData - Device - KeyBackup - LoginToken - OpenID - Profile - Pusher - ThreePID - +type Notification interface { InsertNotification(ctx context.Context, localpart, eventID string, pos int64, tweaks map[string]interface{}, n *api.Notification) error DeleteNotificationsUpTo(ctx context.Context, localpart, roomID string, pos int64) (affected bool, err error) - SetNotificationsRead(ctx context.Context, localpart, roomID string, pos int64, b bool) (affected bool, err error) + SetNotificationsRead(ctx context.Context, localpart, roomID string, pos int64, read bool) (affected bool, err error) GetNotifications(ctx context.Context, localpart string, fromID int64, limit int, filter tables.NotificationFilter) ([]*api.Notification, int64, error) GetNotificationCount(ctx context.Context, localpart string, filter tables.NotificationFilter) (int64, error) GetRoomNotificationCounts(ctx context.Context, localpart, roomID string) (total int64, highlight int64, _ error) DeleteOldNotifications(ctx context.Context) error } +type Database interface { + Account + AccountData + Device + KeyBackup + LoginToken + Notification + OpenID + Profile + Pusher + ThreePID +} + // Err3PIDInUse is the error returned when trying to save an association involving // a third-party identifier which is already associated to a local user. var Err3PIDInUse = errors.New("this third-party identifier is already in use") diff --git a/userapi/storage/storage_test.go b/userapi/storage/storage_test.go index 5a70d99ce..4ba45fa89 100644 --- a/userapi/storage/storage_test.go +++ b/userapi/storage/storage_test.go @@ -9,10 +9,12 @@ import ( "time" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" + "github.com/matrix-org/dendrite/internal/pushrules" "github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/test" "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/dendrite/userapi/storage" + "github.com/matrix-org/dendrite/userapi/storage/tables" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" "github.com/stretchr/testify/assert" @@ -431,3 +433,76 @@ func Test_ThreePID(t *testing.T) { assert.Equal(t, 0, len(threepids)) }) } + +func Test_Notification(t *testing.T) { + ctx := context.Background() + alice := test.NewUser() + aliceLocalpart, _, err := gomatrixserverlib.SplitID('@', alice.ID) + assert.NoError(t, err) + room := test.NewRoom(t, alice) + room2 := test.NewRoom(t, alice) + test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) { + db, close := mustCreateDatabase(t, dbType) + defer close() + // generate some dummy notifications + for i := 0; i < 10; i++ { + eventID := util.RandomString(16) + roomID := room.ID + ts := time.Now() + if i > 5 { + roomID = room2.ID + // create some old notifications to test DeleteOldNotifications + ts = ts.AddDate(0, -2, 0) + } + notification := &api.Notification{ + Actions: []*pushrules.Action{ + {}, + }, + Event: gomatrixserverlib.ClientEvent{ + Content: gomatrixserverlib.RawJSON("{}"), + }, + Read: false, + RoomID: roomID, + TS: gomatrixserverlib.AsTimestamp(ts), + } + err = db.InsertNotification(ctx, aliceLocalpart, eventID, int64(i+1), nil, notification) + assert.NoError(t, err, "unable to insert notification") + } + + // get notifications + count, err := db.GetNotificationCount(ctx, aliceLocalpart, tables.AllNotifications) + assert.NoError(t, err, "unable to get notification count") + assert.Equal(t, int64(10), count) + notifs, count, err := db.GetNotifications(ctx, aliceLocalpart, 0, 15, tables.AllNotifications) + assert.NoError(t, err, "unable to get notifications") + assert.Equal(t, int64(10), count) + assert.Equal(t, 10, len(notifs)) + // ... for a specific room + total, _, err := db.GetRoomNotificationCounts(ctx, aliceLocalpart, room2.ID) + assert.NoError(t, err, "unable to get notifications for room") + assert.Equal(t, int64(4), total) + + // mark notification as read + affected, err := db.SetNotificationsRead(ctx, aliceLocalpart, room2.ID, 7, true) + assert.NoError(t, err, "unable to set notifications read") + assert.True(t, affected) + + // this should delete 2 notifications + affected, err = db.DeleteNotificationsUpTo(ctx, aliceLocalpart, room2.ID, 8) + assert.NoError(t, err, "unable to set notifications read") + assert.True(t, affected) + + total, _, err = db.GetRoomNotificationCounts(ctx, aliceLocalpart, room2.ID) + assert.NoError(t, err, "unable to get notifications for room") + assert.Equal(t, int64(2), total) + + // delete old notifications + err = db.DeleteOldNotifications(ctx) + assert.NoError(t, err) + + // this should now return 0 notifications + total, _, err = db.GetRoomNotificationCounts(ctx, aliceLocalpart, room2.ID) + assert.NoError(t, err, "unable to get notifications for room") + assert.Equal(t, int64(0), total) + }) +}