Skip to content

Commit b05ce44

Browse files
committed
Merge branch 'OUT-4000-filter-iu-email-by-preference' of https://github.com/assemblycom/tasks-app into staging
2 parents f1833f9 + f5d34a9 commit b05ce44

4 files changed

Lines changed: 2 additions & 35 deletions

File tree

src/app/api/notification/iuEmailPreference.test.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { InternalUserNotificationSettings } from '@/types/common'
2-
import { disabledEmailSettingIds, isIuEmailGloballyOff } from './iuEmailPreference'
2+
import { disabledEmailSettingIds } from './iuEmailPreference'
33

44
const settings = (overrides: Partial<InternalUserNotificationSettings> = {}): InternalUserNotificationSettings => ({
55
emailSettings: 'active',
@@ -44,18 +44,3 @@ describe('disabledEmailSettingIds', () => {
4444
).toEqual(new Set())
4545
})
4646
})
47-
48-
describe('isIuEmailGloballyOff', () => {
49-
it('is false only when emailSettings is explicitly active (case-insensitive)', () => {
50-
expect(isIuEmailGloballyOff(settings({ emailSettings: 'active' }))).toBe(false)
51-
expect(isIuEmailGloballyOff(settings({ emailSettings: 'Active' }))).toBe(false)
52-
expect(isIuEmailGloballyOff(settings({ emailSettings: ' ACTIVE ' }))).toBe(false)
53-
})
54-
55-
it('fails closed for any non-active value so a global opt-out is never bypassed', () => {
56-
expect(isIuEmailGloballyOff(settings({ emailSettings: 'not_active' }))).toBe(true)
57-
expect(isIuEmailGloballyOff(settings({ emailSettings: 'disabled' }))).toBe(true)
58-
expect(isIuEmailGloballyOff(settings({ emailSettings: undefined }))).toBe(true)
59-
expect(isIuEmailGloballyOff(settings({ emailSettings: '' }))).toBe(true)
60-
})
61-
})

src/app/api/notification/iuEmailPreference.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,3 @@ export const disabledEmailSettingIds = (settings: InternalUserNotificationSettin
88
.map((entry) => entry.notificationSettingId as string)
99
return new Set(ids)
1010
}
11-
12-
// Global email gate, fail-closed: email is delivered only when the IU has explicitly activated
13-
// email notifications. Any other value — a different disabled string, unexpected casing, or a
14-
// missing field — is treated as not activated, so a global opt-out is never bypassed.
15-
export const isIuEmailGloballyOff = (settings: InternalUserNotificationSettings): boolean =>
16-
(settings.emailSettings ?? '').trim().toLowerCase() !== 'active'

src/jobs/notifications/flush-grouped-email.test.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,6 @@ describe('flushGroupedEmailRun', () => {
202202
expect(result).toMatchObject({ recipients: 1, sent: 0, sentGrouped: 0, sentIndividual: 0 })
203203
})
204204

205-
it('sends nothing to an IU whose email is globally not active', async () => {
206-
mockGetIuNotificationSettings.mockResolvedValue({ emailSettings: 'not_active', notifyAbout: {} })
207-
mockQueryRaw.mockResolvedValue([iuRow('setting_assigned'), iuRow('setting_comment')])
208-
209-
const result = await flushGroupedEmailRun(payload)
210-
211-
expect(mockSendGroupedEmail).not.toHaveBeenCalled()
212-
expect(mockCreateNotification).not.toHaveBeenCalled()
213-
expect(result).toMatchObject({ sent: 0 })
214-
})
215-
216205
it('sends ungated when the IU preference read fails (fail-open)', async () => {
217206
mockGetIuNotificationSettings.mockRejectedValue(new Error('copilot 5xx'))
218207
mockQueryRaw.mockResolvedValue([iuRow('setting_comment'), iuRow('setting_comment')])

src/jobs/notifications/flush-grouped-email.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import 'server-only'
33
import { randomUUID } from 'crypto'
44

55
import { composeGroupedEmail, GroupedEmailEventInput } from '@/app/api/notification/groupedEmail.composer'
6-
import { disabledEmailSettingIds, isIuEmailGloballyOff } from '@/app/api/notification/iuEmailPreference'
6+
import { disabledEmailSettingIds } from '@/app/api/notification/iuEmailPreference'
77
import { copilotAPIKey } from '@/config'
88
import { Sentry } from '@/jobs/sentry'
99
import DBClient from '@/lib/db'
@@ -99,7 +99,6 @@ const filterEventsForIuPreferences = async (
9999
): Promise<WindowEvent[]> => {
100100
try {
101101
const settings = await copilot.getInternalUserNotificationSettings(recipientIuId)
102-
if (isIuEmailGloballyOff(settings)) return []
103102
const disabled = disabledEmailSettingIds(settings)
104103
return events.filter((e) => {
105104
const id = e.individualEmail?.notificationSettingId

0 commit comments

Comments
 (0)