Skip to content

Commit 6c64da6

Browse files
committed
fix(billing): count any earlier account as the Gmail inbox holder, verified or not
1 parent 47e8605 commit 6c64da6

2 files changed

Lines changed: 18 additions & 10 deletions

File tree

‎apps/sim/lib/users/gmail-alias.integration.ts‎

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,20 @@ describe('Gmail inboxes and the free allowance', () => {
9393
expect(await statsOf(returning)).toEqual({ freeTierEligible: false, limit: 0 })
9494
})
9595

96-
it('grants it when the earlier account never verified the inbox', async () => {
96+
it('withholds it from aliases registered before any of them verified the inbox', async () => {
9797
const local = uniqueLocalPart()
98-
await signUp(`${local}@gmail.com`, { emailVerified: false })
99-
100-
const owner = await signUp(`${local.slice(0, 5)}.${local.slice(5)}@gmail.com`)
101-
102-
expect(await statsOf(owner)).toEqual({ freeTierEligible: true, limit: getFreeTierLimit() })
98+
const first = await signUp(`${local}@gmail.com`, { emailVerified: false })
99+
const second = await signUp(`${local}+two@gmail.com`, { emailVerified: false })
100+
await db
101+
.update(user)
102+
.set({ emailVerified: true })
103+
.where(inArray(user.id, [first, second]))
104+
105+
const third = await signUp(`${local.slice(0, 5)}.${local.slice(5)}@gmail.com`)
106+
107+
expect(await statsOf(first)).toEqual({ freeTierEligible: true, limit: getFreeTierLimit() })
108+
expect(await statsOf(second)).toEqual({ freeTierEligible: false, limit: 0 })
109+
expect(await statsOf(third)).toEqual({ freeTierEligible: false, limit: 0 })
103110
})
104111

105112
it('grants it to a different Gmail inbox and never folds addresses outside Gmail', async () => {

‎apps/sim/lib/users/gmail-alias.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ const logger = createLogger('GmailAlias')
2121
* Whether an earlier account, banned or not, already holds the Gmail inbox this
2222
* user's address delivers to. Only an account created before this one counts
2323
* (the id breaks a creation-time tie), so the inbox's first account keeps the
24-
* allowance however late its own stats row is created. It must have verified
25-
* the address, so an account that merely claimed someone else's inbox never
26-
* withholds that person's allowance. Pass the caller's transaction as
24+
* allowance however late its own stats row is created. The earlier account
25+
* counts whether or not it verified the address: the allowance is granted at
26+
* signup, before verification, and where verification is off a password
27+
* account never verifies, so a verified-only rule would let every alias
28+
* registered unverified keep its allowance. Pass the caller's transaction as
2729
* `executor` to read on it; the read then runs in a savepoint, so a failed
2830
* lookup never aborts that transaction. Fails open: a lookup error returns
2931
* `false` and is logged, because refusing a legitimate person's allowance is
@@ -47,7 +49,6 @@ export async function userHasGmailAliasAccount(
4749
.where(
4850
and(
4951
sql`${gmailMailbox(user.email)} = ${self.mailbox}`,
50-
eq(user.emailVerified, true),
5152
or(
5253
lt(user.createdAt, self.createdAt),
5354
and(eq(user.createdAt, self.createdAt), lt(user.id, userId))

0 commit comments

Comments
 (0)