diff --git a/dashboard/final-example/app/ui/login-form.tsx b/dashboard/final-example/app/ui/login-form.tsx index 5fa1374..1f68e2d 100644 --- a/dashboard/final-example/app/ui/login-form.tsx +++ b/dashboard/final-example/app/ui/login-form.tsx @@ -62,9 +62,7 @@ export default function LoginForm() { - +
{code === 'CredentialsSignin' && ( <> diff --git a/dashboard/final-example/package.json b/dashboard/final-example/package.json index 849afb4..3fdbaed 100644 --- a/dashboard/final-example/package.json +++ b/dashboard/final-example/package.json @@ -13,10 +13,8 @@ "@types/node": "20.5.7", "@vercel/postgres": "^0.5.0", "autoprefixer": "10.4.15", - "bcrypt": "^5.1.1", "clsx": "^2.0.0", "next": "13.5.7-canary.27", - "next-auth": "5.0.0-beta.2", "postcss": "8.4.31", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/dashboard/starter-example/app/dashboard/customers/page.tsx b/dashboard/starter-example/app/dashboard/customers/page.tsx index 601da16..dcd62af 100644 --- a/dashboard/starter-example/app/dashboard/customers/page.tsx +++ b/dashboard/starter-example/app/dashboard/customers/page.tsx @@ -1,6 +1,5 @@ import { fetchFilteredCustomers } from '@/app/lib/data'; import CustomersTable from '@/app/ui/customers/table'; -import { Metadata } from 'next'; export default async function Page({ searchParams, diff --git a/dashboard/starter-example/app/lib/actions.ts b/dashboard/starter-example/app/lib/actions.ts index 1a318db..08d14f4 100644 --- a/dashboard/starter-example/app/lib/actions.ts +++ b/dashboard/starter-example/app/lib/actions.ts @@ -4,7 +4,6 @@ import { z } from 'zod'; import { sql } from '@vercel/postgres'; import { revalidatePath } from 'next/cache'; import { redirect } from 'next/navigation'; -import { signIn } from '@/auth'; const FormSchema = z.object({ id: z.string(), @@ -120,17 +119,3 @@ export async function deleteInvoice(formData: FormData) { return { message: 'Database Error: Failed to Delete Invoice.' }; } } - -export async function authenticate( - prevState: string | undefined, - formData: FormData, -) { - try { - await signIn('credentials', Object.fromEntries(formData)); - } catch (error) { - if ((error as Error).message.includes('CredentialsSignin')) { - return 'CredentialsSignin'; - } - throw error; - } -} diff --git a/dashboard/starter-example/app/login/page.tsx b/dashboard/starter-example/app/login/page.tsx deleted file mode 100644 index 5c07299..0000000 --- a/dashboard/starter-example/app/login/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import AcmeLogo from '@/app/ui/acme-logo'; -import LoginForm from '@/app/ui/login-form'; - -export default function LoginPage() { - return ( -
-
-
-
- -
-
- -
-
- ); -} diff --git a/dashboard/starter-example/app/ui/login-form.tsx b/dashboard/starter-example/app/ui/login-form.tsx index 5fa1374..79283f4 100644 --- a/dashboard/starter-example/app/ui/login-form.tsx +++ b/dashboard/starter-example/app/ui/login-form.tsx @@ -1,6 +1,5 @@ 'use client'; -import { authenticate } from '@/app/lib/actions'; import { lusitana } from '@/app/ui/fonts'; import { AtSymbolIcon, @@ -9,14 +8,10 @@ import { } from '@heroicons/react/24/outline'; import { ArrowRightIcon } from '@heroicons/react/20/solid'; import { Button } from './button'; -import { useFormState, useFormStatus } from 'react-dom'; export default function LoginForm() { - const [code, action] = useFormState(authenticate, undefined); - const { pending } = useFormStatus(); - return ( -
+

Please log in to continue. @@ -62,18 +57,9 @@ export default function LoginForm() {

- +
- {code === 'CredentialsSignin' && ( - <> - -

- Invalid credentials -

- - )} + {/* Add form errors here */}
@@ -81,10 +67,8 @@ export default function LoginForm() { } function LoginButton() { - const { pending } = useFormStatus(); - return ( - ); diff --git a/dashboard/starter-example/auth.config.ts b/dashboard/starter-example/auth.config.ts deleted file mode 100644 index 4fa7a84..0000000 --- a/dashboard/starter-example/auth.config.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { NextAuthConfig } from 'next-auth'; - -export const authConfig = { - pages: { - signIn: '/login', - }, - providers: [ - // added later in auth.ts since it requires bcrypt which is only compatible with Node.js - // while this file is also used in non-Node.js environments - ], - callbacks: { - authorized({ auth, request: { nextUrl } }) { - const isLoggedIn = !!auth?.user; - const isOnDashboard = nextUrl.pathname.startsWith('/dashboard'); - if (isOnDashboard) { - if (isLoggedIn) return true; - return false; // Redirect unathenticated users to login page - } else if (isLoggedIn) { - return Response.redirect(new URL('/dashboard', nextUrl)); - } - return true; - }, - }, -} satisfies NextAuthConfig; diff --git a/dashboard/starter-example/auth.ts b/dashboard/starter-example/auth.ts deleted file mode 100644 index 30cd8fc..0000000 --- a/dashboard/starter-example/auth.ts +++ /dev/null @@ -1,43 +0,0 @@ -import NextAuth from 'next-auth'; -import Credentials from 'next-auth/providers/credentials'; -import bcrypt from 'bcrypt'; -import { sql } from '@vercel/postgres'; -import { z } from 'zod'; -import type { User } from '@/app/lib/definitions'; -import { authConfig } from './auth.config'; - -async function getUser(email: string): Promise { - try { - const user = await sql`SELECT * from USERS where email=${email}`; - return user.rows[0]; - } catch (error) { - console.error('Failed to fetch user:', error); - throw new Error('Failed to fetch user.'); - } -} - -export const { auth, signIn, signOut } = NextAuth({ - ...authConfig, - providers: [ - Credentials({ - async authorize(credentials) { - const parsedCredentials = z - .object({ email: z.string().email(), password: z.string().min(6) }) - .safeParse(credentials); - - if (parsedCredentials.success) { - const { email, password } = parsedCredentials.data; - - const user = await getUser(email); - if (!user) return null; - - const passwordsMatch = await bcrypt.compare(password, user.password); - if (passwordsMatch) return user; - } - - console.log('Invalid credentials'); - return null; - }, - }), - ], -}); diff --git a/dashboard/starter-example/middleware.ts b/dashboard/starter-example/middleware.ts deleted file mode 100644 index 187e1c6..0000000 --- a/dashboard/starter-example/middleware.ts +++ /dev/null @@ -1,9 +0,0 @@ -import NextAuth from 'next-auth'; -import { authConfig } from './auth.config'; - -export default NextAuth(authConfig).auth; - -export const config = { - // https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher - matcher: ['/((?!api|_next/static|_next/image|.png).*)'], -}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 511f1f6..66a401a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -212,6 +212,67 @@ importers: version: 4.9.5 dashboard/final-example: + dependencies: + '@heroicons/react': + specifier: ^2.0.18 + version: 2.0.18(react@18.2.0) + '@tailwindcss/forms': + specifier: ^0.5.6 + version: 0.5.6(tailwindcss@3.3.3) + '@types/node': + specifier: 20.5.7 + version: 20.5.7 + '@vercel/postgres': + specifier: ^0.5.0 + version: 0.5.0 + autoprefixer: + specifier: 10.4.15 + version: 10.4.15(postcss@8.4.31) + clsx: + specifier: ^2.0.0 + version: 2.0.0 + next: + specifier: 13.5.7-canary.27 + version: 13.5.7-canary.27(@babel/core@7.23.0)(react-dom@18.2.0)(react@18.2.0) + postcss: + specifier: 8.4.31 + version: 8.4.31 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + tailwindcss: + specifier: 3.3.3 + version: 3.3.3 + typescript: + specifier: 5.2.2 + version: 5.2.2 + use-debounce: + specifier: ^9.0.4 + version: 9.0.4(react@18.2.0) + zod: + specifier: ^3.22.2 + version: 3.22.2 + devDependencies: + '@types/bcrypt': + specifier: ^5.0.1 + version: 5.0.1 + '@types/react': + specifier: 18.2.21 + version: 18.2.21 + '@types/react-dom': + specifier: 18.2.14 + version: 18.2.14 + dotenv: + specifier: ^16.3.1 + version: 16.3.1 + prettier: + specifier: ^3.0.3 + version: 3.0.3 + + dashboard/starter-example: dependencies: '@heroicons/react': specifier: ^2.0.18