diff --git a/app/components/alerts.tsx b/app/components/alerts.tsx index 97af11b..567269b 100644 --- a/app/components/alerts.tsx +++ b/app/components/alerts.tsx @@ -1,4 +1,4 @@ -import { CheckCircleIcon } from '@heroicons/react/solid' +import { CheckCircleIcon, XCircleIcon } from '@heroicons/react/solid' import { ReactNode } from 'react' export function Alert({ children }: { children: ReactNode }) { @@ -18,3 +18,18 @@ export function Alert({ children }: { children: ReactNode }) { ) } + +export function ErrorAlert({ children }: { children: ReactNode }) { + return ( +
+
+
+
+
+

{children}

+
+
+
+ ) +} diff --git a/app/routes/login.tsx b/app/routes/login.tsx index ed09689..f49d003 100644 --- a/app/routes/login.tsx +++ b/app/routes/login.tsx @@ -1,10 +1,10 @@ import type { ActionFunction, LoaderFunction } from '@remix-run/node' import { json } from '@remix-run/node' import { Form, useLoaderData, useNavigation } from '@remix-run/react' -import { Alert } from '~/components/alerts' +import { Alert, ErrorAlert } from '~/components/alerts' import { Button } from '~/components/form-elements' import { auth } from '~/services/auth.server' -import { getUserSession } from '~/services/session.server' +import { commitSession, getUserSession } from '~/services/session.server' export const loader: LoaderFunction = async ({ request }) => { await auth.isAuthenticated(request, { successRedirect: '/dashboard' }) @@ -12,10 +12,21 @@ export const loader: LoaderFunction = async ({ request }) => { // This session key `auth:magiclink` is the default one used by the EmailLinkStrategy // you can customize it passing a `sessionMagicLinkKey` when creating an // instance. - return json({ - user: session.get('user'), - magicLinkSent: session.has('zain:magiclink'), - }) + const error = session.get(auth.sessionErrorKey) as + | { message: string } + | undefined + return json( + { + user: session.get('user'), + magicLinkSent: session.has('zain:magiclink'), + error: error?.message, + }, + { + headers: { + 'Set-Cookie': await commitSession(session), + }, + } + ) } export const action: ActionFunction = async ({ request }) => { @@ -31,7 +42,10 @@ export const action: ActionFunction = async ({ request }) => { } export default function Login() { - const { magicLinkSent } = useLoaderData<{ magicLinkSent: boolean }>() + const { magicLinkSent, error } = useLoaderData<{ + magicLinkSent: boolean + error?: string + }>() const { state } = useNavigation() return ( @@ -79,6 +93,7 @@ export default function Login() { + {error ? {error} : null} {magicLinkSent ? (
diff --git a/app/services/session.server.ts b/app/services/session.server.ts index a8be96e..7780c69 100644 --- a/app/services/session.server.ts +++ b/app/services/session.server.ts @@ -7,7 +7,7 @@ export const sessionStorage = createCookieSessionStorage({ sameSite: 'lax', path: '/', httpOnly: true, - expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days + maxAge: 7 * 24 * 60 * 60, // 7 days in seconds secrets: [getRequiredServerEnvVar('SESSION_SECRET')], // normally you want this to be `secure: true` // but that doesn't work on localhost for Safari