diff --git a/packages/server/modules/notifications/domain/operations.ts b/packages/server/modules/notifications/domain/operations.ts new file mode 100644 index 000000000..1c659dc96 --- /dev/null +++ b/packages/server/modules/notifications/domain/operations.ts @@ -0,0 +1,5 @@ +import { NotificationPreferences } from '@/modules/notifications/helpers/types' + +export type GetSavedUserNotificationPreferences = ( + userId: string +) => Promise diff --git a/packages/server/modules/notifications/graph/resolvers/userNotificationPreferences.ts b/packages/server/modules/notifications/graph/resolvers/userNotificationPreferences.ts index c489ee9a6..debe9c522 100644 --- a/packages/server/modules/notifications/graph/resolvers/userNotificationPreferences.ts +++ b/packages/server/modules/notifications/graph/resolvers/userNotificationPreferences.ts @@ -1,10 +1,18 @@ +import { db } from '@/db/knex' import { Resolvers } from '@/modules/core/graph/generated/graphql' +import { getSavedUserNotificationPreferencesFactory } from '@/modules/notifications/repositories' import { updateNotificationPreferences, - getUserNotificationPreferences + getUserNotificationPreferencesFactory } from '@/modules/notifications/services/notificationPreferences' -module.exports = { +const getUserNotificationPreferences = getUserNotificationPreferencesFactory({ + getSavedUserNotificationPreferences: getSavedUserNotificationPreferencesFactory({ + db + }) +}) + +export = { User: { async notificationPreferences(parent) { const preferences = await getUserNotificationPreferences(parent.id) @@ -12,12 +20,8 @@ module.exports = { } }, Mutation: { - async userNotificationPreferencesUpdate( - _parent, - args, - context: { userId: string } - ) { - await updateNotificationPreferences(context.userId, args.preferences) + async userNotificationPreferencesUpdate(_parent, args, context) { + await updateNotificationPreferences(context.userId!, args.preferences) return true } } diff --git a/packages/server/modules/notifications/repositories.ts b/packages/server/modules/notifications/repositories.ts index 296feac24..4a2569302 100644 --- a/packages/server/modules/notifications/repositories.ts +++ b/packages/server/modules/notifications/repositories.ts @@ -1,19 +1,26 @@ import { UserNotificationPreferences } from '@/modules/core/dbSchema' +import { GetSavedUserNotificationPreferences } from '@/modules/notifications/domain/operations' import { NotificationPreferences, UserNotificationPreferencesRecord } from '@/modules/notifications/helpers/types' +import { Knex } from 'knex' -export async function getUserNotificationPreferences( - userId: string -): Promise { - const userPreferences = - await UserNotificationPreferences.knex() +const tables = { + userNotificationPreferences: (db: Knex) => + db(UserNotificationPreferences.name) +} + +export const getSavedUserNotificationPreferencesFactory = + (deps: { db: Knex }): GetSavedUserNotificationPreferences => + async (userId: string): Promise => { + const userPreferences = await tables + .userNotificationPreferences(deps.db) .where({ userId }) .first() - return userPreferences?.preferences ?? {} -} + return userPreferences?.preferences ?? {} + } export async function saveUserNotificationPreferences( userId: string, diff --git a/packages/server/modules/notifications/services/handlers/activityDigest.ts b/packages/server/modules/notifications/services/handlers/activityDigest.ts index dba7a5ed2..cdb650da1 100644 --- a/packages/server/modules/notifications/services/handlers/activityDigest.ts +++ b/packages/server/modules/notifications/services/handlers/activityDigest.ts @@ -10,7 +10,6 @@ import { } from '@/modules/activitystream/helpers/types' import { getServerInfo } from '@/modules/core/services/generic' import { ServerInfo, UserRecord } from '@/modules/core/helpers/types' -import { getUserNotificationPreferences } from '@/modules/notifications/services/notificationPreferences' import { sendEmail, SendEmailParams } from '@/modules/emails/services/sending' import { groupBy } from 'lodash' import { packageRoot } from '@/bootstrap' @@ -26,6 +25,9 @@ import { EmailInput, renderEmail } from '@/modules/emails/services/emailRendering' +import { getUserNotificationPreferencesFactory } from '@/modules/notifications/services/notificationPreferences' +import { getSavedUserNotificationPreferencesFactory } from '@/modules/notifications/repositories' +import { db } from '@/db/knex' const handler: NotificationHandler = async (msg) => { const { @@ -44,6 +46,12 @@ const digestNotificationEmailHandler = async ( end: Date, emailSender: (params: SendEmailParams) => Promise ): Promise => { + const getUserNotificationPreferences = getUserNotificationPreferencesFactory({ + getSavedUserNotificationPreferences: getSavedUserNotificationPreferencesFactory({ + db + }) + }) + const wantDigests = (await (await getUserNotificationPreferences(userId)).activityDigest?.email) !== false diff --git a/packages/server/modules/notifications/services/notificationPreferences.ts b/packages/server/modules/notifications/services/notificationPreferences.ts index 07b8dc28f..3134091ac 100644 --- a/packages/server/modules/notifications/services/notificationPreferences.ts +++ b/packages/server/modules/notifications/services/notificationPreferences.ts @@ -5,15 +5,18 @@ import { NotificationPreferences } from '@/modules/notifications/helpers/types' import { InvalidArgumentError } from '@/modules/shared/errors' +import { GetSavedUserNotificationPreferences } from '@/modules/notifications/domain/operations' -export async function getUserNotificationPreferences( - userId: string -): Promise { - const savedPreferences = await repo.getUserNotificationPreferences(userId) - return addDefaultPreferenceValues(savedPreferences) -} +export const getUserNotificationPreferencesFactory = + (deps: { + getSavedUserNotificationPreferences: GetSavedUserNotificationPreferences + }) => + async (userId: string): Promise => { + const savedPreferences = await deps.getSavedUserNotificationPreferences(userId) + return addDefaultPreferenceValues(savedPreferences) + } -export function addDefaultPreferenceValues( +function addDefaultPreferenceValues( preferences: NotificationPreferences ): NotificationPreferences { const savedPreferences = { ...preferences } diff --git a/packages/server/modules/notifications/tests/notificationsPreferences.spec.ts b/packages/server/modules/notifications/tests/notificationsPreferences.spec.ts index 913d39544..372d9a16f 100644 --- a/packages/server/modules/notifications/tests/notificationsPreferences.spec.ts +++ b/packages/server/modules/notifications/tests/notificationsPreferences.spec.ts @@ -1,7 +1,6 @@ import { truncateTables } from '@/test/hooks' import { UserNotificationPreferences, Users } from '@/modules/core/dbSchema' import { BasicTestUser, createTestUsers } from '@/test/authHelper' -import * as repo from '@/modules/notifications/repositories' import * as services from '@/modules/notifications/services/notificationPreferences' import { expect } from 'chai' import { @@ -9,6 +8,16 @@ import { NotificationChannel } from '@/modules/notifications/helpers/types' import { BaseError } from '@/modules/shared/errors' +import { getUserNotificationPreferencesFactory } from '@/modules/notifications/services/notificationPreferences' +import { getSavedUserNotificationPreferencesFactory } from '@/modules/notifications/repositories' +import { db } from '@/db/knex' + +const getSavedUserNotificationPreferences = getSavedUserNotificationPreferencesFactory({ + db +}) +const getUserNotificationPreferences = getUserNotificationPreferencesFactory({ + getSavedUserNotificationPreferences +}) const cleanup = async () => { await truncateTables([Users.name, UserNotificationPreferences.name]) @@ -28,10 +37,10 @@ describe('User notification preferences @notifications', () => { describe('services', () => { it('gets default preferences if none saved', async () => { - const savedPreferences = await repo.getUserNotificationPreferences(userA.id) + const savedPreferences = await getSavedUserNotificationPreferences(userA.id) expect(savedPreferences).to.deep.equal({}) expect(savedPreferences).to.be.empty - const preferences = await services.getUserNotificationPreferences(userA.id) + const preferences = await getUserNotificationPreferences(userA.id) expect(preferences).to.not.be.empty for (const val of Object.values(preferences)) { for (const setting of Object.values(val)) { @@ -43,13 +52,13 @@ describe('User notification preferences @notifications', () => { await services.updateNotificationPreferences(userA.id, { activityDigest: { email: false } }) - let preferences = await services.getUserNotificationPreferences(userA.id) + let preferences = await getUserNotificationPreferences(userA.id) expect(preferences).to.not.be.empty expect(preferences.activityDigest?.email).to.be.false await services.updateNotificationPreferences(userA.id, { activityDigest: { email: true } }) - preferences = await services.getUserNotificationPreferences(userA.id) + preferences = await getUserNotificationPreferences(userA.id) expect(preferences.activityDigest?.email).to.be.true }) it("doesn't store invalid preference keys", async () => {