tier-vercel-openai
tier-vercel-openai copied to clipboard
moved tier free user subscription to createUser event from session to…
… ensure only one subscription per user
Description 📣
i was having this problem where new users would be subscribed 2-3x on Stripe upon logging in and couldn’t figure out why.
The reason why is this block of code on line 23 from auth.ts
in authOptions
of the Metered Billing example:
async session({ token, session }) {
if (token) {
session.user.id = token.id;
session.user.name = token.name;
session.user.email = token.email;
session.user.image = token.picture;
// Check if org/user already exists in Stripe, else create and subscribe to free tier
try {
const c = await tier.lookupOrg(`org:${session?.user?.id}`);
console.log("Checking if user/org already exists in Tier");
console.log(c);
} catch (error) {
// Auto subscribe user to the free plan if they do not have any subscription already.
// Add OrgInfo to create/update the customer profile while subscribing
await tier.subscribe(`org:${session?.user?.id}`, TIER_FREE_PLAN_ID, {
info: {
name: session?.user?.name as string,
email: session?.user?.email as string,
} as OrgInfo,
});
} finally {
return session;
}
}
return session;
},
The duplicate subscriptions would cause some weird bugs, primarily tier.report()
reporting to the wrong subscription and tier.limit()
not displaying the correct usage, etc.
the correct place for this try/catch block in authOptions
is the createUser
trigger in events:
events: {
createUser: async ({ user }) => {
console.log(`User ${user.id} was created in the database....`)
// Check if org/user already exists in Stripe, else create and subscribe to free tier
try {
const c = await tier.lookupOrg(`org:${user.id!}`);
console.log(`Customer ${JSON.stringify(c)} already exists in Stripe.`);
} catch (e) {
// Auto subscribe user to the free plan if they do not have any subscription already.
// Add OrgInfo to create/update the customer profile while subscribing
console.log(
`User ${user.id!} is a new user, subscribing to free plan....`,
);
await tier.subscribe(`org:${user.id!}`, TIER_FREE_PLAN_ID, {
info: {
name: user.name! as string,
email: user.email! as string,
} as OrgInfo,
});
console.log(
`User ${user.id!} has been subscribed to free plan....`,
);
}
},
},
This way, it only fires on the first time the org is not found, and not every time getSession
runs.
Type ✨
- [✅] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation
Tests 🛠️
Before the code change, 3 subscriptions were created, presumably because getSession
was fired 3 times in the auth process before the response from prisma.user.create()
returns, triggering a creation for each session call. Also, tier.report()
would not increment on the client side because the wrong subscription was tied to the user.
after clearing Stripe test data and db, subscription is created only once in Stripe and tier.can()
/tier.report()
works as expected.
- [✅] I have agreed and acknowledged the code of conduct. 📝