fix: show live ticker across app and website and suppress review emails
Some checks failed
Code Analysis and Production Deploy / analyze (push) Failing after 5m18s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Has been skipped

This commit is contained in:
Torsten Schulz (local)
2026-10-29 21:49:51 +01:00
parent 10a37180de
commit 472bec4519
29 changed files with 280 additions and 70 deletions

View File

@@ -5,6 +5,7 @@ import crypto from 'crypto'
vi.mock('../server/utils/auth.js', () => {
return {
getTokenFromEvent: vi.fn(() => undefined),
readUsers: vi.fn(),
writeUsers: vi.fn(),
verifyPassword: vi.fn(),

View File

@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createEvent, mockSuccessReadBody } from './setup'
vi.mock('../server/utils/auth.js', () => ({
getTokenFromEvent: vi.fn(() => undefined),
getUserFromToken: vi.fn(),
readUsers: vi.fn(),
writeUsers: vi.fn(),

View File

@@ -0,0 +1,69 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createEvent } from './setup'
vi.mock('nodemailer', () => ({
default: { createTransport: vi.fn(() => ({ sendMail: vi.fn().mockResolvedValue({ messageId: 'real' }) })) }
}))
vi.mock('../server/utils/auth.js', () => ({
readUsers: vi.fn().mockResolvedValue([]),
getTokenFromEvent: vi.fn(),
getUserFromToken: vi.fn()
}))
import nodemailer from 'nodemailer'
import * as auth from '../server/utils/auth.js'
import { createMailTransport } from '../server/utils/mail-transport.js'
import { sendMembershipEmail, sendRegistrationNotification } from '../server/utils/email-service.js'
describe('Mail delivery gate', () => {
beforeEach(() => {
vi.clearAllMocks()
vi.stubEnv('MAIL_DELIVERY_DISABLED', '')
vi.stubEnv('PLAYSTORE_REVIEW_EMAIL', '')
auth.readUsers.mockResolvedValue([])
auth.getTokenFromEvent.mockReturnValue(undefined)
})
afterEach(() => vi.unstubAllEnvs())
it('does not create an SMTP transport when all delivery is disabled', async () => {
vi.stubEnv('MAIL_DELIVERY_DISABLED', 'TRUE')
expect(await createMailTransport(createEvent(), {}).sendMail({ to: 'board@example.com' }))
.toMatchObject({ suppressed: true, accepted: [] })
expect(nodemailer.createTransport).not.toHaveBeenCalled()
})
it('suppresses board mail for an authenticated review user with another form address', async () => {
auth.getTokenFromEvent.mockReturnValue('verified-by-auth')
auth.getUserFromToken.mockResolvedValue({ accountType: 'playstore_review' })
await createMailTransport(createEvent(), {}).sendMail({ to: 'board@example.com', replyTo: 'other@example.com' })
expect(auth.getUserFromToken).toHaveBeenCalledWith('verified-by-auth')
expect(nodemailer.createTransport).not.toHaveBeenCalled()
})
it('suppresses signed-out contact mail using the configured review reply address', async () => {
vi.stubEnv('PLAYSTORE_REVIEW_EMAIL', 'review@example.com')
await createMailTransport(undefined, {}).sendMail({ to: 'board@example.com', replyTo: 'Review <REVIEW@example.com>' })
expect(nodemailer.createTransport).not.toHaveBeenCalled()
})
it('checks stored review accounts in cc and bcc as well', async () => {
auth.readUsers.mockResolvedValue([{ email: 'review@example.com', accountType: 'playstore_review' }])
await createMailTransport(undefined, {}).sendMail({ to: 'member@example.com', bcc: [{ address: 'review@example.com' }] })
expect(nodemailer.createTransport).not.toHaveBeenCalled()
})
it('suppresses membership and registration notifications before SMTP/config loading', async () => {
vi.stubEnv('PLAYSTORE_REVIEW_EMAIL', 'review@example.com')
expect(await sendMembershipEmail({ email: 'review@example.com' }, '/unused.pdf')).toMatchObject({ success: true, suppressed: true })
expect(await sendRegistrationNotification({ email: 'review@example.com' })).toMatchObject({ success: true, suppressed: true })
expect(nodemailer.createTransport).not.toHaveBeenCalled()
})
it('delivers ordinary member mail and does not trust a client demo flag', async () => {
const event = createEvent({ body: { demo: true, accountType: 'playstore_review' } })
const mail = { to: 'member@example.com', text: 'Hello' }
expect(await createMailTransport(event, { host: 'smtp.example.com' }).sendMail(mail)).toEqual({ messageId: 'real' })
expect(nodemailer.createTransport).toHaveBeenCalledWith({ host: 'smtp.example.com' })
expect(nodemailer.createTransport.mock.results[0].value.sendMail).toHaveBeenCalledWith(mail)
})
})

View File

@@ -17,6 +17,7 @@ vi.mock('../server/utils/news.js', () => ({
}))
vi.mock('../server/utils/auth.js', () => ({
getTokenFromEvent: vi.fn(() => undefined),
readUsers: vi.fn(),
migrateUserRoles: vi.fn((user) => {
if (!user) return user