import { verifySession } from "@app/lib/auth/verifySession"; import Link from "next/link"; import { redirect } from "next/navigation"; import OrgSignInLink from "@app/components/OrgSignInLink"; import { cache } from "react"; import SmartLoginForm from "@app/components/SmartLoginForm"; import DashboardLoginForm from "@app/components/DashboardLoginForm"; import { Mail } from "lucide-react"; import { pullEnv } from "@app/lib/pullEnv"; import { cleanRedirect } from "@app/lib/cleanRedirect"; import { getTranslations } from "next-intl/server"; import { build } from "@server/build"; import { LoadLoginPageResponse } from "@server/routers/loginPage/types"; import { Card, CardContent } from "@app/components/ui/card"; import LoginCardHeader from "@app/components/LoginCardHeader"; import { priv } from "@app/lib/api"; import { AxiosResponse } from "axios"; import { LoginFormIDP } from "@app/components/LoginForm"; import { ListIdpsResponse, type GetIdpResponse } from "@server/routers/idp"; import type { Metadata } from "next"; import { cookies } from "next/headers"; import { LAST_USED_IDP_COOKIE_NAME } from "@app/lib/consts"; import z from "zod"; export const metadata: Metadata = { title: "Log In" }; export const dynamic = "force-dynamic"; export default async function Page(props: { searchParams: Promise<{ [key: string]: string | string[] | undefined }>; }) { const searchParams = await props.searchParams; const user = await verifySession({ skipCheckVerifyEmail: true }); const lastUsedIdpCookie = (await cookies()).get(LAST_USED_IDP_COOKIE_NAME); const isInvite = searchParams?.redirect?.includes("/invite"); const forceLoginParam = searchParams?.forceLogin; const forceLogin = forceLoginParam === "true"; const env = pullEnv(); const signUpDisabled = env.flags.disableSignupWithoutInvite; if (user && !forceLogin) { redirect("/"); } // Check for orgId and redirect to org-specific login page if found const orgId = searchParams.orgId as string | undefined; let loginPageDomain: string | undefined; if (orgId) { try { const res = await priv.get>( `/login-page?orgId=${orgId}` ); if (res && res.status === 200 && res.data.data.fullDomain) { loginPageDomain = res.data.data.fullDomain; } } catch (e) { console.debug("No custom login page found for org", orgId); } } if (loginPageDomain) { const redirectUrl = searchParams.redirect as string | undefined; let url = `https://${loginPageDomain}/auth/org`; if (redirectUrl) { url += `?redirect=${redirectUrl}`; } redirect(url); } let redirectUrl: string | undefined = undefined; if (searchParams.redirect) { redirectUrl = cleanRedirect(searchParams.redirect as string); searchParams.redirect = redirectUrl; } const defaultUser = searchParams.user as string | undefined; // Only use SmartLoginForm if NOT (OSS build OR org-only IdP enabled) const useSmartLogin = build === "saas" || (build === "enterprise" && env.app.identityProviderMode === "org"); let loginIdps: LoginFormIDP[] = []; let lastUsedIdpForSmartLogin: (LoginFormIDP & { orgId?: string }) | null = null; if (!useSmartLogin) { // Load IdPs for DashboardLoginForm (OSS or org-only IdP mode) if (build === "oss" || env.app.identityProviderMode !== "org") { const idpsRes = await priv.get>("/idp"); loginIdps = idpsRes.data.data.idps.map((idp) => ({ idpId: idp.idpId, name: idp.name, variant: idp.type })) as LoginFormIDP[]; } } else { if (lastUsedIdpCookie) { const lastUsedIdpSchema = z.object({ orgId: z.string().optional(), idpId: z.number() }); try { const persistedData = lastUsedIdpSchema.parse( JSON.parse(lastUsedIdpCookie.value) ); const idpRes = await priv.get>( `/idp/${persistedData.idpId}` ); const idp = idpRes.data.data.idp; lastUsedIdpForSmartLogin = { idpId: idp.idpId, name: idp.name, variant: idp.type, orgId: persistedData.orgId, lastUsed: true }; } catch (error) { // the idp might not exist or the data is malformatted, skip this } } } const t = await getTranslations(); return ( <> {build === "saas" && (

{t.rich("loginLegalDisclaimer", { termsOfService: (chunks) => ( {chunks} ), privacyPolicy: (chunks) => ( {chunks} ) })}

)} {isInvite && (

{t("inviteAlready")}

{t("inviteAlreadyDescription")}

)} {useSmartLogin ? ( <> ) : ( )} {(!signUpDisabled || isInvite) && (

{t("authNoAccount")}{" "} {t("signup")}

)} {!useSmartLogin && !isInvite && (build === "saas" || env.app.identityProviderMode === "org") ? ( ) : null} ); } function buildQueryString(searchParams: { [key: string]: string | string[] | undefined; }): string { const params = new URLSearchParams(); const redirect = searchParams.redirect; const forceLogin = searchParams.forceLogin; if (redirect && typeof redirect === "string") { params.set("redirect", redirect); } if (forceLogin && typeof forceLogin === "string") { params.set("forceLogin", forceLogin); } const queryString = params.toString(); return queryString ? `?${queryString}` : ""; }