first commit
This commit is contained in:
102
calcom/apps/web/server/lib/auth/login/getServerSideProps.tsx
Normal file
102
calcom/apps/web/server/lib/auth/login/getServerSideProps.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import { jwtVerify } from "jose";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { getCsrfToken } from "next-auth/react";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { isSAMLLoginEnabled, samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
|
||||
import { WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { IS_GOOGLE_LOGIN_ENABLED } from "@server/lib/constants";
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const { req, res, query } = context;
|
||||
|
||||
const session = await getServerSession({ req, res });
|
||||
const ssr = await ssrInit(context);
|
||||
|
||||
const verifyJwt = (jwt: string) => {
|
||||
const secret = new TextEncoder().encode(process.env.CALENDSO_ENCRYPTION_KEY);
|
||||
|
||||
return jwtVerify(jwt, secret, {
|
||||
issuer: WEBSITE_URL,
|
||||
audience: `${WEBSITE_URL}/auth/login`,
|
||||
algorithms: ["HS256"],
|
||||
});
|
||||
};
|
||||
|
||||
let totpEmail = null;
|
||||
if (context.query.totp) {
|
||||
try {
|
||||
const decryptedJwt = await verifyJwt(context.query.totp as string);
|
||||
if (decryptedJwt.payload) {
|
||||
totpEmail = decryptedJwt.payload.email as string;
|
||||
} else {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/error?error=JWT%20Invalid%20Payload",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/error?error=Invalid%20JWT%3A%20Please%20try%20again",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (session) {
|
||||
const { callbackUrl } = query;
|
||||
|
||||
if (callbackUrl) {
|
||||
try {
|
||||
const destination = getSafeRedirectUrl(callbackUrl as string);
|
||||
if (destination) {
|
||||
return {
|
||||
redirect: {
|
||||
destination,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const userCount = await prisma.user.count();
|
||||
if (userCount === 0) {
|
||||
// Proceed to new onboarding to create first admin user
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/setup",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
csrfToken: await getCsrfToken(context),
|
||||
trpcState: ssr.dehydrate(),
|
||||
isGoogleLoginEnabled: IS_GOOGLE_LOGIN_ENABLED,
|
||||
isSAMLLoginEnabled,
|
||||
samlTenantID,
|
||||
samlProductID,
|
||||
totpEmail,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const ssr = await ssrInit(context);
|
||||
// Deleting old cookie manually, remove this code after all existing cookies have expired
|
||||
context.res?.setHeader(
|
||||
"Set-Cookie",
|
||||
"next-auth.session-token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"
|
||||
);
|
||||
|
||||
return {
|
||||
props: {
|
||||
trpcState: ssr.dehydrate(),
|
||||
query: context.query,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { getProviders, getCsrfToken } from "next-auth/react";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const { req } = context;
|
||||
|
||||
const session = await getServerSession({ req });
|
||||
const csrfToken = await getCsrfToken(context);
|
||||
const providers = await getProviders();
|
||||
if (session) {
|
||||
return {
|
||||
redirect: { destination: "/" },
|
||||
};
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
csrfToken,
|
||||
providers,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils";
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import { hostedCal, isSAMLLoginEnabled, samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
|
||||
import { ssoTenantProduct } from "@calcom/features/ee/sso/lib/sso";
|
||||
import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants";
|
||||
import { checkUsername } from "@calcom/lib/server/checkUsername";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { asStringOrNull } from "@lib/asStringOrNull";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
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);
|
||||
const usernameParam = asStringOrNull(context.query.username);
|
||||
const successDestination = `/getting-started${usernameParam ? `?username=${usernameParam}` : ""}`;
|
||||
if (!providerParam) {
|
||||
throw new Error(`File is not named sso/[provider]`);
|
||||
}
|
||||
|
||||
const { req } = context;
|
||||
|
||||
const session = await getServerSession({ req });
|
||||
const ssr = await ssrInit(context);
|
||||
const { currentOrgDomain } = orgDomainConfig(context.req);
|
||||
|
||||
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 checkUsername(usernameParam, currentOrgDomain);
|
||||
if (availability.available && availability.premium && IS_PREMIUM_USERNAME_ENABLED) {
|
||||
const stripePremiumUrl = await getStripePremiumUsernameUrl({
|
||||
userEmail: session.user.email,
|
||||
username: usernameParam,
|
||||
successDestination,
|
||||
});
|
||||
if (stripePremiumUrl) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: stripePremiumUrl,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
redirect: {
|
||||
destination: successDestination,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let error: string | null = null;
|
||||
|
||||
let tenant = samlTenantID;
|
||||
let product = samlProductID;
|
||||
|
||||
if (providerParam === "saml" && hostedCal) {
|
||||
if (!emailParam) {
|
||||
error = "Email not provided";
|
||||
} else {
|
||||
try {
|
||||
const ret = await ssoTenantProduct(prisma, emailParam);
|
||||
tenant = ret.tenant;
|
||||
product = ret.product;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
error = e.message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: `/auth/error?error=${error}`,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
trpcState: ssr.dehydrate(),
|
||||
provider: providerParam,
|
||||
isSAMLLoginEnabled,
|
||||
hostedCal,
|
||||
tenant,
|
||||
product,
|
||||
error,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
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: getPremiumMonthlyPlanPriceId(),
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
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",
|
||||
allow_promotion_codes: true,
|
||||
});
|
||||
|
||||
return checkoutSession.url;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
|
||||
|
||||
export async function getServerSideProps() {
|
||||
return {
|
||||
props: {
|
||||
samlTenantID,
|
||||
samlProductID,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
export const getServerSideProps = async (_context: GetServerSidePropsContext) => {
|
||||
const EMAIL_FROM = process.env.EMAIL_FROM;
|
||||
|
||||
return {
|
||||
props: {
|
||||
EMAIL_FROM,
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user