Skip to content

Commit 90823ed

Browse files
committed
fix: handle email edge cases. Only send email to users with verified emails, rely on email from firebase-auth since that is source of truth for user email data, skip users with no notificationFrequency synced to users (they will get their first digest on the next pass)
1 parent bc200d9 commit 90823ed

File tree

2 files changed

+33
-13
lines changed

2 files changed

+33
-13
lines changed

functions/src/notifications/deliverNotifications.ts

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from "../email/types"
1515
import { prepareHandlebars } from "../email/handlebarsHelpers"
1616
import { getAuth } from "firebase-admin/auth"
17+
import { Frequency } from "../auth/types"
1718

1819
const NUM_BILLS_TO_DISPLAY = 4
1920
const NUM_USERS_TO_DISPLAY = 4
@@ -25,9 +26,13 @@ const db = admin.firestore()
2526
const auth = getAuth()
2627
const path = require("path")
2728

28-
const isEmailVerified = async (uid: string) => {
29+
const getVerifiedUserEmail = async (uid: string) => {
2930
const userRecord = await auth.getUser(uid)
30-
return userRecord && userRecord.emailVerified
31+
if (userRecord && userRecord.email && userRecord.emailVerified) {
32+
return userRecord.email
33+
} else {
34+
return null
35+
}
3136
}
3237

3338
// TODO: Batching (at both user + email level)?
@@ -39,21 +44,32 @@ const deliverEmailNotifications = async () => {
3944
prepareHandlebars()
4045
console.log("Handlebars helpers and partials prepared")
4146

47+
// TODO: Add index
4248
const usersSnapshot = await db
4349
.collection("users")
4450
.where("nextDigestAt", "<=", now)
4551
.get()
4652

4753
const emailPromises = usersSnapshot.docs.map(async userDoc => {
4854
const user = userDoc.data() as User
55+
if (!user || !user.notificationFrequency) {
56+
console.log(`User ${userDoc.id} has no notificationFrequency - skipping`)
57+
return
58+
}
4959

50-
const emailVerified = await isEmailVerified(userDoc.id)
51-
if (!emailVerified) {
52-
console.log(`Skipping user ${userDoc.id} because email is not verified`)
60+
const verifiedEmail = await getVerifiedUserEmail(userDoc.id)
61+
if (!verifiedEmail) {
62+
console.log(
63+
`Skipping user ${userDoc.id} because they have no verified email address`
64+
)
5365
return
5466
}
5567

56-
const digestData = await buildDigestData(user, userDoc.id, now)
68+
const digestData = await buildDigestData(
69+
userDoc.id,
70+
now,
71+
user.notificationFrequency
72+
)
5773

5874
// If there are no new notifications, don't send an email
5975
if (
@@ -66,7 +82,7 @@ const deliverEmailNotifications = async () => {
6682

6783
// Create an email document in /emails to queue up the send
6884
await db.collection("emails").add({
69-
to: [user.email],
85+
to: [verifiedEmail],
7086
message: {
7187
subject: "Your Notifications Digest",
7288
text: "", // blank because we're sending HTML
@@ -89,8 +105,12 @@ const deliverEmailNotifications = async () => {
89105
}
90106

91107
// TODO: Unit tests
92-
const buildDigestData = async (user: User, userId: string, now: Timestamp) => {
93-
const startDate = getNotificationStartDate(user.notificationFrequency, now)
108+
const buildDigestData = async (
109+
userId: string,
110+
now: Timestamp,
111+
notificationFrequency: Frequency
112+
) => {
113+
const startDate = getNotificationStartDate(notificationFrequency, now)
94114

95115
const notificationsSnapshot = await db
96116
.collection(`users/${userId}/userNotificationFeed`)
@@ -176,7 +196,7 @@ const buildDigestData = async (user: User, userId: string, now: Timestamp) => {
176196
.sort((a, b) => b.newTestimonyCount - a.newTestimonyCount)
177197

178198
const digestData = {
179-
notificationFrequency: user.notificationFrequency,
199+
notificationFrequency,
180200
startDate: startDate.toDate(),
181201
endDate: now.toDate(),
182202
bills: bills.slice(0, NUM_BILLS_TO_DISPLAY),

functions/src/notifications/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { Timestamp } from "../firebase"
44

55
// This should probably live somewhere else once other code starts caring about this
66
export interface User {
7-
email: string
8-
notificationFrequency: Frequency
9-
nextDigestAt: Timestamp
7+
email?: string
8+
notificationFrequency?: Frequency
9+
nextDigestAt?: Timestamp
1010
}
1111

1212
export interface Notification {

0 commit comments

Comments
 (0)