mirror of
https://github.com/vercel/next-learn.git
synced 2026-06-15 11:51:39 +00:00
add users to data seed and add pw auth
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import NextAuth from 'next-auth/next';
|
||||
import CredentialsProvider from 'next-auth/providers/credentials';
|
||||
// import bcrypt from 'bcryptjs';
|
||||
import bcrypt from 'bcrypt';
|
||||
import { fetchUser } from '../../../lib/data';
|
||||
|
||||
export const authOptions = {
|
||||
@@ -14,16 +14,17 @@ export const authOptions = {
|
||||
|
||||
try {
|
||||
const user = await fetchUser(email);
|
||||
|
||||
console.log('user: ', user);
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// const passwordsMatch = await bcrypt.compare(password, user.password);
|
||||
const passwordsMatch = await bcrypt.compare(password, user.password);
|
||||
|
||||
// if (!passwordsMatch) {
|
||||
// return null;
|
||||
// }
|
||||
if (!passwordsMatch) {
|
||||
console.log('Passwords do not match');
|
||||
return null;
|
||||
}
|
||||
|
||||
return user;
|
||||
} catch (error) {
|
||||
|
||||
@@ -4,7 +4,9 @@ import { Revenue, LatestInvoice, User } from './definitions';
|
||||
|
||||
export async function fetchUser(email: string) {
|
||||
try {
|
||||
return await sql`SELECT * from USERS where email=${email}`;
|
||||
const user = await sql`SELECT * from USERS where email=${email}`;
|
||||
|
||||
return user.rows[0] as User;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch user:', error);
|
||||
throw new Error('Failed to fetch user.');
|
||||
|
||||
15
dashboard/15-final/app/ui/dashboard/log-out-button.tsx
Normal file
15
dashboard/15-final/app/ui/dashboard/log-out-button.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
'use client';
|
||||
import { PowerIcon } from '@heroicons/react/24/outline';
|
||||
import { signOut } from 'next-auth/react';
|
||||
|
||||
export default function LogOutButton() {
|
||||
return (
|
||||
<button
|
||||
onClick={() => signOut()}
|
||||
className="flex gap-2 rounded p-2 font-semibold hover:text-blue-600"
|
||||
>
|
||||
<PowerIcon className="w-6" />
|
||||
<div className="hidden md:block">Sign Out</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { PowerIcon } from '@heroicons/react/24/outline';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import NavLinks from '@/app/ui/dashboard/nav-links';
|
||||
import LogOutButton from './log-out-button';
|
||||
|
||||
export default function SideNav() {
|
||||
return (
|
||||
@@ -18,13 +18,7 @@ export default function SideNav() {
|
||||
</Link>
|
||||
<NavLinks />
|
||||
</div>
|
||||
<Link
|
||||
href="/login"
|
||||
className="flex gap-2 rounded p-2 font-semibold hover:text-blue-600"
|
||||
>
|
||||
<PowerIcon className="w-6" />
|
||||
<div className="hidden md:block">Sign Out</div>
|
||||
</Link>
|
||||
<LogOutButton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function LoginForm() {
|
||||
password,
|
||||
redirect: false,
|
||||
});
|
||||
|
||||
console.log(res);
|
||||
if (res.error) {
|
||||
setError('Invalid Credentials');
|
||||
return;
|
||||
|
||||
845
dashboard/15-final/package-lock.json
generated
845
dashboard/15-final/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
"@types/react-dom": "18.2.7",
|
||||
"@vercel/postgres": "^0.4.1",
|
||||
"autoprefixer": "10.4.15",
|
||||
"bcrypt": "^5.1.1",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"clsx": "^2.0.0",
|
||||
"next": "13.4.19",
|
||||
@@ -27,6 +28,7 @@
|
||||
"typescript": "5.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
"dotenv": "^16.3.1"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,5 +1,49 @@
|
||||
const { sql } = require('@vercel/postgres');
|
||||
const { invoices, customers, revenue } = require('../app/lib/dummy-data.js');
|
||||
const {
|
||||
invoices,
|
||||
customers,
|
||||
revenue,
|
||||
users,
|
||||
} = require('../app/lib/dummy-data.js');
|
||||
const bcrypt = require('bcrypt');
|
||||
|
||||
async function seedUsers() {
|
||||
try {
|
||||
// Create the "invoices" table if it doesn't exist
|
||||
const createTable = await sql`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
console.log(`Created "users" table`);
|
||||
|
||||
// Insert data into the "users" table
|
||||
const insertedUsers = await Promise.all(
|
||||
users.map(async (user) => {
|
||||
const hashedPassword = await bcrypt.hash(user.password, 10);
|
||||
return sql`
|
||||
INSERT INTO users (id, name, email, password)
|
||||
VALUES (${user.id}, ${user.name}, ${user.email}, ${hashedPassword})
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
`;
|
||||
}),
|
||||
);
|
||||
|
||||
console.log(`Seeded ${insertedUsers.length} users`);
|
||||
|
||||
return {
|
||||
createTable,
|
||||
users: insertedUsers,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error seeding users:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function seedInvoices() {
|
||||
try {
|
||||
@@ -112,6 +156,7 @@ async function seedRevenue() {
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await seedUsers();
|
||||
await seedCustomers();
|
||||
await seedInvoices();
|
||||
await seedRevenue();
|
||||
|
||||
Reference in New Issue
Block a user