Skip to content

Commit 47e8605

Browse files
committed
fix(billing): count only a verified earlier account as the Gmail inbox holder
1 parent aaca509 commit 47e8605

2 files changed

Lines changed: 23 additions & 8 deletions

File tree

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,26 @@ const userIds: string[] = []
2424

2525
async function insertUser(
2626
email: string,
27-
{ banned = false, createdAt = new Date() } = {}
27+
{ banned = false, emailVerified = true, createdAt = new Date() } = {}
2828
): Promise<string> {
2929
const id = generateId()
3030
userIds.push(id)
3131
await db.insert(user).values({
3232
id,
3333
name: 'Gmail alias fixture',
3434
email,
35-
emailVerified: true,
35+
emailVerified,
3636
banned,
3737
createdAt,
3838
updatedAt: createdAt,
3939
})
4040
return id
4141
}
4242

43-
async function signUp(email: string, options?: { banned?: boolean }): Promise<string> {
43+
async function signUp(
44+
email: string,
45+
options?: { banned?: boolean; emailVerified?: boolean }
46+
): Promise<string> {
4447
const id = await insertUser(email, options)
4548
await handleNewUser(id, {})
4649
return id
@@ -90,6 +93,15 @@ describe('Gmail inboxes and the free allowance', () => {
9093
expect(await statsOf(returning)).toEqual({ freeTierEligible: false, limit: 0 })
9194
})
9295

96+
it('grants it when the earlier account never verified the inbox', async () => {
97+
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() })
103+
})
104+
93105
it('grants it to a different Gmail inbox and never folds addresses outside Gmail', async () => {
94106
const local = uniqueLocalPart()
95107
await signUp(`${local}@gmail.com`)

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ 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. Pass the caller's
25-
* transaction as `executor` to read on it; the read then runs in a savepoint,
26-
* so a failed lookup never aborts that transaction. Fails open: a lookup error
27-
* returns `false` and is logged, because refusing a legitimate person's
28-
* allowance is worse than one missed match.
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
27+
* `executor` to read on it; the read then runs in a savepoint, so a failed
28+
* lookup never aborts that transaction. Fails open: a lookup error returns
29+
* `false` and is logged, because refusing a legitimate person's allowance is
30+
* worse than one missed match.
2931
*/
3032
export async function userHasGmailAliasAccount(
3133
userId: string,
@@ -45,6 +47,7 @@ export async function userHasGmailAliasAccount(
4547
.where(
4648
and(
4749
sql`${gmailMailbox(user.email)} = ${self.mailbox}`,
50+
eq(user.emailVerified, true),
4851
or(
4952
lt(user.createdAt, self.createdAt),
5053
and(eq(user.createdAt, self.createdAt), lt(user.id, userId))

0 commit comments

Comments
 (0)