Skip to content

Commit

Permalink
fixup, conditional login
Browse files Browse the repository at this point in the history
  • Loading branch information
motatoes committed Oct 15, 2024
1 parent 21e4b57 commit c2df234
Show file tree
Hide file tree
Showing 6 changed files with 350 additions and 302 deletions.
31 changes: 31 additions & 0 deletions src/app/(dynamic-pages)/(login-pages)/auth/sso-verify/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

'use client'

import { supabaseAnonClient } from '@/supabase-clients/anon/supabaseAnonClient';
import { AuthChangeEvent, Session } from "@supabase/supabase-js";
import { useEffect, useState } from "react";


export default function Default() {
const supabase = supabaseAnonClient;

const [authState, setAuthState] = useState<AuthChangeEvent | "">("");
const [session, setSession] = useState<Session | null>(null);

useEffect(() => {
supabase.auth.onAuthStateChange((event, sessionValue) => {
console.log('state change', event, sessionValue)
if (event === "INITIAL_SESSION") {
window.location.href = `/auth/callback-tokens?access_token=${sessionValue?.access_token}&refresh_token=${sessionValue?.refresh_token}`
} else {
setAuthState(event);
}
});
}, []);

return (
<>
<p>Verifying login ...</p>
</>
);
}
249 changes: 5 additions & 244 deletions src/app/(dynamic-pages)/(login-pages)/login/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,6 @@
'use client';
import { Email } from '@/components/Auth/Email';
import { EmailAndPassword } from '@/components/Auth/EmailAndPassword';
import { EmailConfirmationPendingCard } from '@/components/Auth/EmailConfirmationPendingCard';
import { RedirectingPleaseWaitCard } from '@/components/Auth/RedirectingPleaseWaitCard';
import { RenderProviders } from '@/components/Auth/RenderProviders';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import {
signInWithMagicLink,
signInWithPassword,
signInWithProvider,
} from '@/data/auth/auth';
import { getMaybeInitialOrganizationToRedirectTo } from '@/data/user/organizations';
import { useSAToastMutation } from '@/hooks/useSAToastMutation';
import { supabaseAnonClient } from '@/supabase-clients/anon/supabaseAnonClient';
import type { AuthProvider } from '@/types';
import { PrefetchKind } from 'next/dist/client/components/router-reducer/router-reducer-types';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useDidMount } from 'rooks';
import DefaultLoginTabs from '@/components/Auth/DefaultLoginTabs';
import SSOLoginTabs from '@/components/Auth/SSOLoginTabs';

export function Login({
next,
Expand All @@ -33,224 +9,9 @@ export function Login({
next?: string;
nextActionType?: string;
}) {
const [emailSentSuccessMessage, setEmailSentSuccessMessage] = useState<string | null>(null);
const [redirectInProgress, setRedirectInProgress] = useState(false);

const router = useRouter();

useDidMount(() => {
console.log('prefetching dashboard')
router.prefetch('/org/123', {
kind: PrefetchKind.AUTO
})
})


async function ssoLogin() {
const SSO_DOMAIN = process.env.NEXT_PUBLIC_SSO_DOMAIN || ''
const { data, error } = await supabaseAnonClient.auth.signInWithSSO({
domain: SSO_DOMAIN,
});
if (error) {
alert(error.message);
return;
}
if (data?.url) {
// redirect the user to the identity provider's authentication flow
window.location.href = data.url;
return;
} else {
alert("Unable to open SSO login page.");
}
}

const initialOrgRedirectMutation = useSAToastMutation(getMaybeInitialOrganizationToRedirectTo, {
loadingMessage: 'Loading your dashboard...',
errorMessage: 'Failed to load dashboard',
successMessage: 'Redirecting to your dashboard...',
onSuccess: (successPayload) => {
if (successPayload.data) {
router.push(`/org/${successPayload.data}`);
} else {
router.push('/dashboard');
}
},
onError: (errorPayload) => {
console.error(errorPayload);
},
dismissOnSuccess: true,
});


function redirectToDashboard() {
if (next) {
router.push(`/auth/callback?next=${next}`);
} else {
initialOrgRedirectMutation.mutate();
}
}
const magicLinkMutation = useSAToastMutation(
async (email: string) => {
return await signInWithMagicLink(email, next);
},
{
loadingMessage: 'Sending magic link...',
errorMessage(error) {
try {
if (error instanceof Error) {
return String(error.message);
}
return `Send magic link failed ${String(error)}`;
} catch (_err) {
console.warn(_err);
return 'Send magic link failed ';
}
},
successMessage: 'A magic link has been sent to your email!',
dismissOnSuccess: true,
onSuccess: () => {
setEmailSentSuccessMessage('A magic link has been sent to your email!');
},
},
);
const passwordMutation = useSAToastMutation(
async ({ email, password }: { email: string; password: string }) => {
return await signInWithPassword(email, password);
},
{
onSuccess: () => {
redirectToDashboard();
setRedirectInProgress(true);
},
loadingMessage: 'Logging in...',
errorMessage(error) {
try {
if (error instanceof Error) {
return String(error.message);
}
return `Sign in account failed ${String(error)}`;
} catch (_err) {
console.warn(_err);
return 'Sign in account failed';
}
},
successMessage: 'Logged in!',
dismissOnSuccess: true,
},
);
const providerMutation = useSAToastMutation(
async (provider: AuthProvider) => {
return signInWithProvider(provider, next);
},
{
loadingMessage: 'Requesting login...',
successMessage: 'Redirecting...',
errorMessage: 'Failed to login',
onSuccess: (payload) => {
window.location.href = payload.data.url;
},
dismissOnSuccess: true,
},
);
return (
<div
data-success={emailSentSuccessMessage}
className="container data-[success]:flex items-center data-[success]:justify-center text-left max-w-lg mx-auto overflow-auto data-[success]:h-full min-h-[470px]"
>
{emailSentSuccessMessage ? (
<EmailConfirmationPendingCard
type={'login'}
heading={"Confirmation Link Sent"}
message={emailSentSuccessMessage}
resetSuccessMessage={setEmailSentSuccessMessage}
/>
) : redirectInProgress ? (
<RedirectingPleaseWaitCard
message="Please wait while we redirect you to your dashboard."
heading="Redirecting to Dashboard"
/>
) : (
<div className="space-y-8 bg-background p-6 rounded-lg shadow dark:border">
<Tabs defaultValue="password" className="md:min-w-[400px]">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="password">Password</TabsTrigger>
<TabsTrigger value="magic-link">Magic Link</TabsTrigger>
<TabsTrigger value="social-login">Social Login</TabsTrigger>
<TabsTrigger value="sso-login">SSO Login</TabsTrigger>
</TabsList>
<TabsContent value="password">
<Card className="border-none shadow-none">
<CardHeader className="py-6 px-0">
<CardTitle>Login to Digger</CardTitle>
<CardDescription>
Login with the account you used to signup.
</CardDescription>
</CardHeader>
<CardContent className="space-y-2 p-0">
<EmailAndPassword
isLoading={passwordMutation.isLoading}
onSubmit={(data) => {
passwordMutation.mutate(data);
}}
view="sign-in"
/>
</CardContent>
</Card>
</TabsContent>

<TabsContent value="magic-link">
<Card className="border-none shadow-none">
<CardHeader className="py-6 px-0">
<CardTitle>Login to Digger</CardTitle>
<CardDescription>
Login with magic link we will send to your email.
</CardDescription>
</CardHeader>
<CardContent className="space-y-2 p-0">
<Email
onSubmit={(email) => magicLinkMutation.mutate(email)}
isLoading={magicLinkMutation.isLoading}
view="sign-in"
/>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="social-login">
<Card className="border-none shadow-none">
<CardHeader className="py-6 px-0">
<CardTitle>Login to Digger</CardTitle>
<CardDescription>
Login with your social account.
</CardDescription>
</CardHeader>
<CardContent className="space-y-2 p-0">
<RenderProviders
providers={['github']}
isLoading={providerMutation.isLoading}
onProviderLoginRequested={providerMutation.mutate}
/>
</CardContent>
</Card>
</TabsContent>

<TabsContent value="sso-login">
<Card className="border-none shadow-none">
<CardHeader className="py-6 px-0">
<CardTitle>Login to Digger</CardTitle>
<CardDescription>
Login with via SSO
</CardDescription>
</CardHeader>
<CardContent className="space-y-2 p-0">
<button onClick={() => ssoLogin()}>SSO Login</button>
</CardContent>
</Card>
</TabsContent>


</Tabs>
</div>
)}
</div>
<>
{process.env.NEXT_PUBLIC_SSO_DOMAIN ? <SSOLoginTabs></SSOLoginTabs> : <DefaultLoginTabs></DefaultLoginTabs>}
</>
);
}
58 changes: 0 additions & 58 deletions src/app/page.tsx

This file was deleted.

39 changes: 39 additions & 0 deletions src/app/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { createSupabaseUserRouteHandlerClient } from '@/supabase-clients/user/createSupabaseUserRouteHandlerClient';
import { NextResponse } from 'next/server';

export const dynamic = 'force-dynamic';

export async function GET() {
if (process.env.NEXT_PUBLIC_SSO_DOMAIN !== undefined) {
return NextResponse.redirect(
new URL('/auth/sso-verify', process.env.NEXT_PUBLIC_SITE_URL),
);
}

const supabase = createSupabaseUserRouteHandlerClient();

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

if (error) {
console.error('Error checking user authentication:', error);
// In case of an error, redirect to login as a fallback
return NextResponse.redirect(
new URL('/login', process.env.NEXT_PUBLIC_SITE_URL),
);
}

if (user) {
// User is logged in, redirect to dashboard
return NextResponse.redirect(
new URL('/dashboard', process.env.NEXT_PUBLIC_SITE_URL),
);
} else {
// User is not logged in, redirect to login
return NextResponse.redirect(
new URL('/login', process.env.NEXT_PUBLIC_SITE_URL),
);
}
}
Loading

0 comments on commit c2df234

Please sign in to comment.