Skip to content

Commit

Permalink
replaced auth with new auth and updated packages
Browse files Browse the repository at this point in the history
  • Loading branch information
claudfuen committed Mar 27, 2024
1 parent 16c5ffb commit 9232d73
Show file tree
Hide file tree
Showing 13 changed files with 353 additions and 191 deletions.
2 changes: 0 additions & 2 deletions app/astria/train-webhook/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { LeapWebhookImage } from "@/types/leap";
import { Database } from "@/types/supabase";
import { Leap } from "@leap-ai/sdk";
import { createClient } from "@supabase/supabase-js";
import { NextResponse } from "next/server";
import { Resend } from "resend";
Expand Down
69 changes: 54 additions & 15 deletions app/auth/callback/route.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,60 @@
import { Database } from '@/types/supabase'
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
import { Database } from "@/types/supabase";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { isAuthApiError } from "@supabase/supabase-js";
import { cookies } from "next/headers";
import { NextRequest, NextResponse } from "next/server";

import type { NextRequest } from 'next/server'
export async function GET(req: NextRequest) {
const requestUrl = new URL(req.url);
const code = requestUrl.searchParams.get("code");
const error = requestUrl.searchParams.get("error");
const next = requestUrl.searchParams.get("next") || "/";
const error_description = requestUrl.searchParams.get("error_description");

export const dynamic = 'force-dynamic'

export async function GET(request: NextRequest) {
const requestUrl = new URL(request.url)
const code = requestUrl.searchParams.get('code')
if (error) {
console.log("error: ", {
error,
error_description,
code,
});
}

if (code) {
const supabase = createRouteHandlerClient<Database>({ cookies })
await supabase.auth.exchangeCodeForSession(code)
const supabase = createRouteHandlerClient<Database>({ cookies });

try {
await supabase.auth.exchangeCodeForSession(code);

// ater exchanging the code, we should check if the user has a feature-flag row and a credits now, if not, we should create one

const { data: user, error: userError } = await supabase.auth.getUser();

if (userError || !user) {
console.error(
"[login] [session] [500] Error getting user: ",
userError
);
return NextResponse.redirect(
`${requestUrl.origin}/login/failed?err=500`
);
}
} catch (error) {
if (isAuthApiError(error)) {
console.error(
"[login] [session] [500] Error exchanging code for session: ",
error
);
return NextResponse.redirect(
`${requestUrl.origin}/login/failed?err=AuthApiError`
);
} else {
console.error("[login] [session] [500] Something wrong: ", error);
return NextResponse.redirect(
`${requestUrl.origin}/login/failed?err=500`
);
}
}
}

// URL to redirect to after sign in process completes
return NextResponse.redirect(requestUrl.origin)
}
return NextResponse.redirect(new URL(next, req.url));
}
22 changes: 0 additions & 22 deletions app/auth/confirm/route.ts

This file was deleted.

34 changes: 0 additions & 34 deletions app/auth/sign-in/route.ts

This file was deleted.

39 changes: 0 additions & 39 deletions app/auth/sign-up/route.ts

This file was deleted.

175 changes: 175 additions & 0 deletions app/login/components/Login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
"use client";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { useToast } from "@/components/ui/use-toast";
import { Database } from "@/types/supabase";
import { createClientComponentClient } from "@supabase/auth-helpers-nextjs";
import disposableDomains from "disposable-email-domains";
import { useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import { AiOutlineGoogle } from "react-icons/ai";
import { WaitingForMagicLink } from "./WaitingForMagicLink";

type Inputs = {
email: string;
};

export const Login = ({
host,
searchParams,
}: {
host: string | null;
searchParams?: { [key: string]: string | string[] | undefined };
}) => {
const supabase = createClientComponentClient<Database>();
const [isSubmitting, setIsSubmitting] = useState(false);
const [isMagicLinkSent, setIsMagicLinkSent] = useState(false);
const { toast } = useToast();

const {
register,
handleSubmit,
formState: { errors, isSubmitted },
} = useForm<Inputs>();

const onSubmit: SubmitHandler<Inputs> = async (data) => {
setIsSubmitting(true);
try {
await signInWithMagicLink(data.email);
setTimeout(() => {
setIsSubmitting(false);
toast({
title: "Email sent",
description: "Check your inbox for a magic link to sign in.",
duration: 5000,
});
setIsMagicLinkSent(true);
}, 1000);
} catch (error) {
setIsSubmitting(false);
toast({
title: "Something went wrong",
variant: "destructive",
description:
"Please try again, if the problem persists, contact us at hello@tryleap.ai",
duration: 5000,
});
}
};

let inviteToken = null;
if (searchParams && "inviteToken" in searchParams) {
inviteToken = searchParams["inviteToken"];
}

const protocol = host?.includes("localhost") ? "http" : "https";
const redirectUrl = `${protocol}://${host}/auth/callback`;

console.log({ redirectUrl });

const signInWithGoogle = async () => {
const { data, error } = await supabase.auth.signInWithOAuth({
provider: "google",
options: {
redirectTo: redirectUrl,
},
});

console.log(data, error);
};

const signInWithMagicLink = async (email: string) => {
const { error } = await supabase.auth.signInWithOtp({
email,
options: {
emailRedirectTo: redirectUrl,
},
});

if (error) {
console.log(`Error: ${error.message}`);
}
};

if (isMagicLinkSent) {
return (
<WaitingForMagicLink toggleState={() => setIsMagicLinkSent(false)} />
);
}

return (
<>
<div className="flex items-center justify-center p-8">
<div className="flex flex-col gap-4 bg-neutral-50 dark:bg-neutral-900 border border-neutral-200 p-4 rounded-xl max-w-sm w-full">
<h1 className="text-xl">Welcome</h1>
<p className="text-xs opacity-60">
Sign in or create an account to get started.
</p>
<Button
onClick={signInWithGoogle}
variant={"outline"}
className="font-semibold"
>
<AiOutlineGoogle size={20} />
Continue with Google
</Button>
<OR />

<form
onSubmit={handleSubmit(onSubmit)}
className="flex flex-col gap-2"
>
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-2">
<Input
type="email"
placeholder="Email"
{...register("email", {
required: true,
validate: {
emailIsValid: (value: string) =>
/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value) ||
"Please enter a valid email",
emailDoesntHavePlus: (value: string) =>
/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value) ||
"Email addresses with a '+' are not allowed",
emailIsntDisposable: (value: string) =>
!disposableDomains.includes(value.split("@")[1]) ||
"Please use a permanent email address",
},
})}
/>
{isSubmitted && errors.email && (
<span className={"text-xs text-red-400"}>
{errors.email?.message || "Email is required to sign in"}
</span>
)}
</div>
</div>

<Button
isLoading={isSubmitting}
disabled={isSubmitting}
variant="outline"
className="w-full"
type="submit"
>
Continue with Email
</Button>
</form>
</div>
</div>
</>
);
};

export const OR = () => {
return (
<div className="flex items-center my-1">
<div className="border-b flex-grow mr-2 opacity-50" />
<span className="text-sm opacity-50">OR</span>
<div className="border-b flex-grow ml-2 opacity-50" />
</div>
);
};
32 changes: 32 additions & 0 deletions app/login/components/WaitingForMagicLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Button } from "@/components/ui/button";
import { ArrowLeft } from "lucide-react";

export const WaitingForMagicLink = ({
toggleState,
}: {
toggleState: () => void;
}) => {
return (
<>
<div className="flex items-center justify-center p-8">
<div className="flex flex-col gap-4 bg-neutral-50 dark:bg-neutral-900 border border-neutral-200 p-4 rounded-xl max-w-sm w-full">
<h1 className="text-xl">Check your email to continue</h1>
<div className="flex flex-col gap-2">
<p className="text-sm">
We've emailed you a magic link to access your account.
</p>
<p className="text-xs opacity-60">
Hint: it might be in your spam folder.
</p>
</div>
<div>
<Button onClick={toggleState} variant="secondary" size="sm">
<ArrowLeft size={14} />
Go back
</Button>
</div>
</div>
</div>
</>
);
};
Loading

0 comments on commit 9232d73

Please sign in to comment.