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>
This commit is contained in:
parent
06cec35522
commit
fdc99b346a
3 changed files with 64 additions and 34 deletions
|
@ -3,6 +3,10 @@ import { signIn } from "next-auth/react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect } from "react";
|
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 { asStringOrNull } from "@lib/asStringOrNull";
|
||||||
import { getSession } from "@lib/auth";
|
import { getSession } from "@lib/auth";
|
||||||
import prisma from "@lib/prisma";
|
import prisma from "@lib/prisma";
|
||||||
|
@ -44,7 +48,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||||
const providerParam = asStringOrNull(context.query.provider);
|
const providerParam = asStringOrNull(context.query.provider);
|
||||||
const emailParam = asStringOrNull(context.query.email);
|
const emailParam = asStringOrNull(context.query.email);
|
||||||
const usernameParam = asStringOrNull(context.query.username);
|
const usernameParam = asStringOrNull(context.query.username);
|
||||||
|
const successDestination = "/getting-started" + (usernameParam ? `?username=${usernameParam}` : "");
|
||||||
if (!providerParam) {
|
if (!providerParam) {
|
||||||
throw new Error(`File is not named sso/[provider]`);
|
throw new Error(`File is not named sso/[provider]`);
|
||||||
}
|
}
|
||||||
|
@ -55,9 +59,29 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||||
const ssr = await ssrInit(context);
|
const ssr = await ssrInit(context);
|
||||||
|
|
||||||
if (session) {
|
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 {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
destination: "/getting-started" + (usernameParam ? `?username=${usernameParam}` : ""),
|
destination: successDestination,
|
||||||
permanent: false,
|
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;
|
||||||
|
};
|
||||||
|
|
|
@ -352,25 +352,6 @@ export default function Onboarding(props: inferSSRProps<typeof getServerSideProp
|
||||||
</div>
|
</div>
|
||||||
<form className="sm:mx-auto sm:w-full">
|
<form className="sm:mx-auto sm:w-full">
|
||||||
<section className="space-y-8">
|
<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>
|
<fieldset>
|
||||||
<label htmlFor="name" className="block text-sm font-medium text-gray-700">
|
<label htmlFor="name" className="block text-sm font-medium text-gray-700">
|
||||||
{t("full_name")}
|
{t("full_name")}
|
||||||
|
|
|
@ -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
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue