parent
4a74a5284b
commit
0ff8984a94
2 changed files with 46 additions and 10 deletions
|
|
@ -181,13 +181,13 @@ export const updateSubscription = instrument(
|
|||
}
|
||||
)
|
||||
|
||||
const getMostRecentTombstonedSubscription = async (pubkey: string) =>
|
||||
const getMostRecentTombstonedSubscription = async (pubkey: string, email: string) =>
|
||||
parseSubscription(
|
||||
await get(
|
||||
`SELECT * FROM subscriptions
|
||||
WHERE pubkey = ? AND unsubscribed_at IS NOT NULL
|
||||
ORDER BY created_at DESC, id DESC LIMIT 1`,
|
||||
[pubkey]
|
||||
WHERE pubkey = ? AND email = ? AND unsubscribed_at IS NOT NULL
|
||||
ORDER BY rowid DESC LIMIT 1`,
|
||||
[pubkey, email]
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -209,13 +209,13 @@ export const insertSubscription = instrument(
|
|||
return assertResult(await updateSubscription(existing, email, frequency, hour, minute, dayOfWeek, timezone))
|
||||
}
|
||||
|
||||
// No active row. If this account previously subscribed to the same email
|
||||
// and was unsubscribed, reactivate that row instead of inserting a fresh
|
||||
// one. Otherwise every turn-on → turn-off → turn-on cycle would create a
|
||||
// new row, abandoning the confirmed state (and the already-known key).
|
||||
const tombstoned = await getMostRecentTombstonedSubscription(pubkey)
|
||||
// No active row. If this account previously subscribed to this email and
|
||||
// was unsubscribed, reactivate the most recent such row instead of inserting
|
||||
// a fresh one. Otherwise every turn-on → turn-off → turn-on cycle would
|
||||
// create a new row, abandoning the confirmed state (and the already-known key).
|
||||
const tombstoned = await getMostRecentTombstonedSubscription(pubkey, email)
|
||||
|
||||
if (tombstoned?.email === email) {
|
||||
if (tombstoned) {
|
||||
try {
|
||||
return assertResult(await reactivateSubscription(tombstoned, frequency))
|
||||
} catch (err: any) {
|
||||
|
|
|
|||
|
|
@ -149,4 +149,40 @@ describe('Re-subscribe with a changed frequency reactivates and updates cadence'
|
|||
const rows = await db.getAllSubscriptionsByPubkey(pubkey)
|
||||
expect(rows).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Re-subscribe with mixed emails for one pubkey picks the right row', () => {
|
||||
const pubkey = unique('resub-mixed')
|
||||
const emailA = `${unique('resub-mixed-a')}@example.com`
|
||||
const emailB = `${unique('resub-mixed-b')}@example.com`
|
||||
|
||||
beforeAll(async () => {
|
||||
await db.migrate()
|
||||
})
|
||||
|
||||
it('creates and tombstones two different emails, then re-subscribes email B', async () => {
|
||||
// Email A cycle
|
||||
const subA = await db.insertSubscription(pubkey, emailA, 'daily')
|
||||
await db.unsubscribeSubscription(subA.key)
|
||||
|
||||
// Email B cycle
|
||||
const subB = await db.insertSubscription(pubkey, emailB, 'daily')
|
||||
const bId = subB!.id
|
||||
await db.unsubscribeSubscription(subB.key)
|
||||
|
||||
// Re-subscribe with email B — must reactivate B's own row, not A's,
|
||||
// and must not resurrect the wrong email.
|
||||
const resigned = await db.insertSubscription(pubkey, emailB, 'daily')
|
||||
const active = await db.getSubscriptionByPubkey(pubkey)
|
||||
|
||||
expect(active!.id).toBe(bId)
|
||||
expect(active!.id).not.toBe(subA!.id)
|
||||
expect(active!.email).toBe(emailB)
|
||||
expect(active!.unsubscribed_at).toBeFalsy()
|
||||
|
||||
const rows = await db.getAllSubscriptionsByPubkey(pubkey)
|
||||
expect(rows).toHaveLength(2)
|
||||
expect(rows.filter(r => r.email === emailA)).toHaveLength(1)
|
||||
expect(rows.filter(r => r.email === emailB)).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue