fix/handle-premium-on-google-signup (#2160)

* checking if username is premium on google sign up

* Removed test validating query input value, but it's no longer required

* undo code that was moved to a function for reuse

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
pull/2081/head^2
alannnc 2022-03-16 12:33:20 -07:00 committed by GitHub
parent 06cec35522
commit fdc99b346a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 34 deletions

View File

@ -3,6 +3,10 @@ import { signIn } from "next-auth/react";
import { useRouter } from "next/router";
import { useEffect } from "react";
import { checkPremiumUsername } from "@calcom/ee/lib/core/checkPremiumUsername";
import stripe from "@calcom/stripe/server";
import { getPremiumPlanPrice } from "@calcom/stripe/utils";
import { asStringOrNull } from "@lib/asStringOrNull";
import { getSession } from "@lib/auth";
import prisma from "@lib/prisma";
@ -44,7 +48,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
const providerParam = asStringOrNull(context.query.provider);
const emailParam = asStringOrNull(context.query.email);
const usernameParam = asStringOrNull(context.query.username);
const successDestination = "/getting-started" + (usernameParam ? `?username=${usernameParam}` : "");
if (!providerParam) {
throw new Error(`File is not named sso/[provider]`);
}
@ -55,9 +59,29 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
const ssr = await ssrInit(context);
if (session) {
// Validating if username is Premium, while this is true an email its required for stripe user confirmation
if (usernameParam && session.user.email) {
const availability = await checkPremiumUsername(usernameParam);
if (availability.available && availability.premium) {
const stripePremiumUrl = await getStripePremiumUsernameUrl({
userEmail: session.user.email,
username: usernameParam,
successDestination,
});
if (stripePremiumUrl) {
return {
redirect: {
destination: stripePremiumUrl,
permanent: false,
},
};
}
}
}
return {
redirect: {
destination: "/getting-started" + (usernameParam ? `?username=${usernameParam}` : ""),
destination: successDestination,
permanent: false,
},
};
@ -103,3 +127,41 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
},
};
};
type GetStripePremiumUsernameUrl = {
userEmail: string;
username: string;
successDestination: string;
};
const getStripePremiumUsernameUrl = async ({
userEmail,
username,
successDestination,
}: GetStripePremiumUsernameUrl): Promise<string | null> => {
// @TODO: probably want to check if stripe user email already exists? or not
const customer = await stripe.customers.create({
email: userEmail,
metadata: {
email: userEmail,
username,
},
});
const checkoutSession = await stripe.checkout.sessions.create({
mode: "subscription",
payment_method_types: ["card"],
customer: customer.id,
line_items: [
{
price: getPremiumPlanPrice(),
quantity: 1,
},
],
success_url: `${process.env.NEXT_PUBLIC_APP_BASE_URL}${successDestination}&session_id={CHECKOUT_SESSION_ID}`,
cancel_url: process.env.NEXT_PUBLIC_APP_BASE_URL || "https://app.cal.com",
allow_promotion_codes: true,
});
return checkoutSession.url;
};

View File

@ -352,25 +352,6 @@ export default function Onboarding(props: inferSSRProps<typeof getServerSideProp
</div>
<form className="sm:mx-auto sm:w-full">
<section className="space-y-8">
{(props.usernameParam || props.user?.identityProvider !== IdentityProvider.CAL) && (
<fieldset>
<label htmlFor="name" className="block text-sm font-medium text-gray-700">
{t("username")}
</label>
<input
ref={usernameRef}
type="text"
name="username"
id="username"
data-testid="username"
placeholder={t("username")}
defaultValue={props.usernameParam ? props.usernameParam : props.user?.username ?? ""}
required
className="mt-1 block w-full rounded-sm border border-gray-300 px-3 py-2 shadow-sm focus:border-neutral-500 focus:outline-none focus:ring-neutral-500 sm:text-sm"
/>
</fieldset>
)}
<fieldset>
<label htmlFor="name" className="block text-sm font-medium text-gray-700">
{t("full_name")}

View File

@ -11,17 +11,4 @@ test.describe("Onboarding", () => {
},
});
});
const username = "calendso";
test(`/getting-started?username=${username} shows the first step of onboarding with username field populated`, async ({
page,
}) => {
await page.goto("/getting-started?username=" + username);
await page.waitForSelector("[data-testid=username]");
await expect(await page.$eval("[data-testid=username]", (el: HTMLInputElement) => el.value)).toEqual(
username
);
});
});