import { OnboardingLayout } from "@/components/layouts/onboarding-layout"; import { AlertBlock } from "@/components/shared/alert-block"; import { Logo } from "@/components/shared/logo"; import { Button } from "@/components/ui/button"; import { CardContent, CardDescription } from "@/components/ui/card"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { InputOTP, InputOTPGroup, InputOTPSlot, } from "@/components/ui/input-otp"; import { Label } from "@/components/ui/label"; import { authClient } from "@/lib/auth-client"; import { IS_CLOUD, isAdminPresent } from "@dokploy/server"; import { validateRequest } from "@dokploy/server/lib/auth"; import { zodResolver } from "@hookform/resolvers/zod"; import { REGEXP_ONLY_DIGITS } from "input-otp"; import type { GetServerSidePropsContext } from "next"; import Link from "next/link"; import { useRouter } from "next/router"; import { type ReactElement, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; const LoginSchema = z.object({ email: z.string().email(), password: z.string().min(8), }); const _TwoFactorSchema = z.object({ code: z.string().min(6), }); type LoginForm = z.infer; interface Props { IS_CLOUD: boolean; } export default function Home({ IS_CLOUD }: Props) { const router = useRouter(); const [isLoginLoading, setIsLoginLoading] = useState(false); const [isTwoFactorLoading, setIsTwoFactorLoading] = useState(false); const [isBackupCodeLoading, setIsBackupCodeLoading] = useState(false); const [isTwoFactor, setIsTwoFactor] = useState(false); const [error, setError] = useState(null); const [twoFactorCode, setTwoFactorCode] = useState(""); const [isBackupCodeModalOpen, setIsBackupCodeModalOpen] = useState(false); const [backupCode, setBackupCode] = useState(""); const [isGithubLoading, setIsGithubLoading] = useState(false); const [isGoogleLoading, setIsGoogleLoading] = useState(false); const loginForm = useForm({ resolver: zodResolver(LoginSchema), defaultValues: { email: "", password: "", }, }); const onSubmit = async (values: LoginForm) => { setIsLoginLoading(true); try { const { data, error } = await authClient.signIn.email({ email: values.email, password: values.password, }); if (error) { toast.error(error.message); setError(error.message || "An error occurred while logging in"); return; } // @ts-ignore if (data?.twoFactorRedirect as boolean) { setTwoFactorCode(""); setIsTwoFactor(true); toast.info("Please enter your 2FA code"); return; } toast.success("Logged in successfully"); router.push("/dashboard/projects"); } catch { toast.error("An error occurred while logging in"); } finally { setIsLoginLoading(false); } }; const onTwoFactorSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (twoFactorCode.length !== 6) { toast.error("Please enter a valid 6-digit code"); return; } setIsTwoFactorLoading(true); try { const { error } = await authClient.twoFactor.verifyTotp({ code: twoFactorCode.replace(/\s/g, ""), }); if (error) { toast.error(error.message); setError(error.message || "An error occurred while verifying 2FA code"); return; } toast.success("Logged in successfully"); router.push("/dashboard/projects"); } catch { toast.error("An error occurred while verifying 2FA code"); } finally { setIsTwoFactorLoading(false); } }; const onBackupCodeSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (backupCode.length < 8) { toast.error("Please enter a valid backup code"); return; } setIsBackupCodeLoading(true); try { const { error } = await authClient.twoFactor.verifyBackupCode({ code: backupCode.trim(), }); if (error) { toast.error(error.message); setError( error.message || "An error occurred while verifying backup code", ); return; } toast.success("Logged in successfully"); router.push("/dashboard/projects"); } catch { toast.error("An error occurred while verifying backup code"); } finally { setIsBackupCodeLoading(false); } }; const handleGithubSignIn = async () => { setIsGithubLoading(true); try { const { error } = await authClient.signIn.social({ provider: "github", }); if (error) { toast.error(error.message); return; } } catch (error) { toast.error("An error occurred while signing in with GitHub", { description: error instanceof Error ? error.message : "Unknown error", }); } finally { setIsGithubLoading(false); } }; const handleGoogleSignIn = async () => { setIsGoogleLoading(true); try { const { error } = await authClient.signIn.social({ provider: "google", }); if (error) { toast.error(error.message); return; } } catch (error) { toast.error("An error occurred while signing in with Google", { description: error instanceof Error ? error.message : "Unknown error", }); } finally { setIsGoogleLoading(false); } }; return ( <>

Sign in

Enter your email and password to sign in

{error && ( {error} )} {!isTwoFactor ? ( <> {IS_CLOUD && ( )} {IS_CLOUD && ( )}
( Email )} /> ( Password )} /> ) : ( <>
Enter the 6-digit code from your authenticator app
Enter Backup Code Enter one of your backup codes to access your account
setBackupCode(e.target.value)} placeholder="Enter your backup code" className="font-mono" /> Enter one of the backup codes you received when setting up 2FA
)}
{IS_CLOUD && ( Create an account )}
{IS_CLOUD ? ( Lost your password? ) : ( Lost your password? )}
); } Home.getLayout = (page: ReactElement) => { return {page}; }; export async function getServerSideProps(context: GetServerSidePropsContext) { if (IS_CLOUD) { try { const { user } = await validateRequest(context.req); if (user) { return { redirect: { permanent: true, destination: "/dashboard/projects", }, }; } } catch {} return { props: { IS_CLOUD: IS_CLOUD, }, }; } const hasAdmin = await isAdminPresent(); if (!hasAdmin) { return { redirect: { permanent: true, destination: "/register", }, }; } const { user } = await validateRequest(context.req); if (user) { return { redirect: { permanent: true, destination: "/dashboard/projects", }, }; } return { props: { hasAdmin, }, }; }