| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | import { GetServerSidePropsContext } from "next"; | 
					
						
							|  |  |  | import { signIn } from "next-auth/react"; | 
					
						
							|  |  |  | import { useRouter } from "next/router"; | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  | import { useEffect } from "react"; | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-16 19:33:20 +00:00
										 |  |  | import { checkPremiumUsername } from "@calcom/ee/lib/core/checkPremiumUsername"; | 
					
						
							|  |  |  | import stripe from "@calcom/stripe/server"; | 
					
						
							|  |  |  | import { getPremiumPlanPrice } from "@calcom/stripe/utils"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | import { asStringOrNull } from "@lib/asStringOrNull"; | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  | import { getSession } from "@lib/auth"; | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | import prisma from "@lib/prisma"; | 
					
						
							|  |  |  | import { isSAMLLoginEnabled, hostedCal, samlTenantID, samlProductID, samlTenantProduct } from "@lib/saml"; | 
					
						
							|  |  |  | import { inferSSRProps } from "@lib/types/inferSSRProps"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  | import { ssrInit } from "@server/lib/ssr"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | export type SSOProviderPageProps = inferSSRProps<typeof getServerSideProps>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  | export default function Provider(props: SSOProviderPageProps) { | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |   const router = useRouter(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     if (props.provider === "saml") { | 
					
						
							|  |  |  |       const email = typeof router.query?.email === "string" ? router.query?.email : null; | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |       if (!email) { | 
					
						
							|  |  |  |         router.push("/auth/error?error=" + "Email not provided"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |       if (!props.isSAMLLoginEnabled) { | 
					
						
							|  |  |  |         router.push("/auth/error?error=" + "SAML login not enabled"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |       signIn("saml", {}, { tenant: props.tenant, product: props.product }); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       signIn(props.provider); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }, []); | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |   return null; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export const getServerSideProps = async (context: GetServerSidePropsContext) => { | 
					
						
							|  |  |  |   // get query params and typecast them to string
 | 
					
						
							|  |  |  |   // (would be even better to assert them instead of typecasting)
 | 
					
						
							|  |  |  |   const providerParam = asStringOrNull(context.query.provider); | 
					
						
							|  |  |  |   const emailParam = asStringOrNull(context.query.email); | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |   const usernameParam = asStringOrNull(context.query.username); | 
					
						
							| 
									
										
										
										
											2022-03-16 19:33:20 +00:00
										 |  |  |   const successDestination = "/getting-started" + (usernameParam ? `?username=${usernameParam}` : ""); | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |   if (!providerParam) { | 
					
						
							|  |  |  |     throw new Error(`File is not named sso/[provider]`); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |   const { req } = context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const session = await getSession({ req }); | 
					
						
							|  |  |  |   const ssr = await ssrInit(context); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (session) { | 
					
						
							| 
									
										
										
										
											2022-03-16 19:33:20 +00:00
										 |  |  |     // 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, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |     return { | 
					
						
							|  |  |  |       redirect: { | 
					
						
							| 
									
										
										
										
											2022-03-16 19:33:20 +00:00
										 |  |  |         destination: successDestination, | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |         permanent: false, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |   let error: string | null = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let tenant = samlTenantID; | 
					
						
							|  |  |  |   let product = samlProductID; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |   if (providerParam === "saml" && hostedCal) { | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |     if (!emailParam) { | 
					
						
							|  |  |  |       error = "Email not provided"; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       try { | 
					
						
							|  |  |  |         const ret = await samlTenantProduct(prisma, emailParam); | 
					
						
							|  |  |  |         tenant = ret.tenant; | 
					
						
							|  |  |  |         product = ret.product; | 
					
						
							|  |  |  |       } catch (e: any) { | 
					
						
							|  |  |  |         error = e.message; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (error) { | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       redirect: { | 
					
						
							|  |  |  |         destination: "/auth/error?error=" + error, | 
					
						
							|  |  |  |         permanent: false, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     props: { | 
					
						
							| 
									
										
										
										
											2022-02-02 18:33:27 +00:00
										 |  |  |       trpcState: ssr.dehydrate(), | 
					
						
							| 
									
										
										
										
											2022-01-13 20:05:23 +00:00
										 |  |  |       provider: providerParam, | 
					
						
							|  |  |  |       isSAMLLoginEnabled, | 
					
						
							|  |  |  |       hostedCal, | 
					
						
							|  |  |  |       tenant, | 
					
						
							|  |  |  |       product, | 
					
						
							|  |  |  |       error, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2022-03-16 19:33:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ], | 
					
						
							| 
									
										
										
										
											2022-03-26 00:39:38 +00:00
										 |  |  |     success_url: `${process.env.NEXT_PUBLIC_WEBAPP_URL}${successDestination}&session_id={CHECKOUT_SESSION_ID}`, | 
					
						
							|  |  |  |     cancel_url: process.env.NEXT_PUBLIC_WEBAPP_URL || "https://app.cal.com", | 
					
						
							| 
									
										
										
										
											2022-03-16 19:33:20 +00:00
										 |  |  |     allow_promotion_codes: true, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return checkoutSession.url; | 
					
						
							|  |  |  | }; |