This commit is contained in:
Balázs Orbán
2023-10-24 10:46:23 -07:00
parent 5d936f92bb
commit a8b795b227
5 changed files with 19 additions and 65 deletions

View File

@@ -21,7 +21,7 @@ export default function SideNav() {
<form
action={async () => {
'use server';
await signOut({ redirectTo: '/' });
await signOut();
}}
>
<button className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3">

View File

@@ -17,10 +17,7 @@ export default async function LoginForm() {
<form
action={async (formData) => {
'use server';
await signIn('credentials', {
...Object.fromEntries(formData),
redirectTo: '/dashboard',
});
await signIn('credentials', Object.fromEntries(formData));
}}
className="space-y-3"
>

View File

@@ -1,59 +0,0 @@
import NextAuth from 'next-auth';
import Credentials from 'next-auth/providers/credentials';
import bcrypt from 'bcryptjs';
import { sql } from '@vercel/postgres';
import type { User } from '@/app/lib/definitions';
async function getUser(email: string) {
try {
const user = await sql<User>`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 {
handlers: { GET, POST },
auth,
signIn,
signOut,
} = NextAuth({
providers: [
Credentials({
name: 'Sign-In with Credentials',
credentials: {
password: { label: 'Password', type: 'password' },
email: { label: 'Email', type: 'email' },
},
async authorize(credentials) {
const { email, password } = credentials ?? {};
// @ts-expect-error TODO: Validate email type with zod
const user = await getUser(email);
if (!user || !password) {
console.log('Missing credentials');
return null;
}
// @ts-expect-error TODO: Validate password type with zod
const passwordsMatch = await bcrypt.compare(password, user.password);
if (!passwordsMatch) {
console.log('Invalid credentials');
return null;
}
return { ...user, id: user.id.toString() };
},
}),
],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
return !nextUrl.pathname.startsWith('/dashboard') || !!auth?.user;
},
},
pages: {
signIn: '/login',
},
});

View File

@@ -3,6 +3,7 @@ import Credentials from 'next-auth/providers/credentials';
import bcrypt from 'bcryptjs';
import { sql } from '@vercel/postgres';
import type { User } from '@/app/lib/definitions';
import { NextResponse } from 'next/server';
async function getUser(email: string) {
try {
@@ -50,7 +51,18 @@ export const {
],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
return !nextUrl.pathname.startsWith('/dashboard') || !!auth?.user;
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith('/dashboard');
if (isOnDashboard) {
nextUrl.pathname = '/login';
if (!isLoggedIn) return NextResponse.redirect(nextUrl);
return true;
} else if (isLoggedIn) {
nextUrl.pathname = '/dashboard';
return NextResponse.redirect(nextUrl);
}
return true;
},
},
pages: {

View File

@@ -1 +1,5 @@
export { auth as middleware } from './auth';
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};