Set Google Auth

This commit is contained in:
MartinBraquet
2025-07-27 20:44:25 +02:00
parent f512b3b06c
commit f67ffa2701
14 changed files with 164 additions and 105 deletions

View File

@@ -61,6 +61,7 @@ Run the following commands to set up your database and Prisma schema:
```bash
npx prisma migrate dev --name init
```

View File

@@ -6,6 +6,8 @@ import {useSession, signOut} from "next-auth/react";
export default function Header() {
const {data: session} = useSession();
console.log(session);
return (
<header className="w-full bg-white shadow-md py-4 px-8">
<nav className="flex justify-between items-center">

View File

@@ -1,7 +1,6 @@
// import { prisma } from "@/lib/prisma";
import bcrypt from "bcryptjs";
import { NextResponse } from "next/server";
import prisma from "@/lib/prisma";
import { prisma }from "@/lib/prisma";
export async function POST(req: Request) {
try {

View File

@@ -1,4 +1,4 @@
import prisma from "@/lib/prisma";
import { prisma }from "@/lib/prisma";
import { NextResponse } from "next/server";
export async function GET(request: Request) {

View File

@@ -1,6 +1,6 @@
export const dynamic = "force-dynamic"; // This disables SSG and ISR
import prisma from "@/lib/prisma";
import { prisma }from "@/lib/prisma";
import { notFound, redirect } from "next/navigation";
export default async function Post({ params }: { params: Promise<{ id: string }> }) {

View File

@@ -1,6 +1,6 @@
import {redirect} from "next/navigation";
import Link from "next/link";
import prisma from "@/lib/prisma";
import { prisma }from "@/lib/prisma";
import {checkPostTableExists} from "@/lib/db-utils";

View File

@@ -1,57 +0,0 @@
export const dynamic = "force-dynamic"; // This disables SSG and ISR
import prisma from "@/lib/prisma";
import { redirect } from "next/navigation";
import Form from "next/form";
export default function NewUser() {
async function createUser(formData: FormData) {
"use server";
const name = formData.get("name") as string;
const email = formData.get("email") as string;
await prisma.user.create({
data: { name, email, password: "" }, // password will be added by NextAuth
});
redirect("/");
}
return (
<div className="max-w-2xl mx-auto p-6 bg-white rounded-lg shadow-md mt-12">
<h1 className="text-3xl font-bold mb-6">Create New User</h1>
<Form action={createUser} className="space-y-6">
<div>
<label htmlFor="name" className="block text-lg font-medium mb-2">Name</label>
<input
type="text"
id="name"
name="name"
placeholder="Enter user name ..."
className="w-full px-4 py-2 border rounded-lg"
/>
</div>
<div>
<label htmlFor="email" className="flex text-lg font-medium mb-2 items-center">
Email
<span className="ml-2 px-2 py-1 text-xs font-semibold text-white bg-gray-500 rounded-lg">
Required
</span>
</label>
<input
type="email"
id="email"
name="email"
required
placeholder="Enter user email ..."
className="w-full px-4 py-2 border rounded-lg"
/>
</div>
<button type="submit" className="w-full bg-blue-500 text-white py-3 rounded-lg hover:bg-blue-600">
Create User
</button>
</Form>
</div>
);
}

32
auth.ts
View File

@@ -1,8 +1,9 @@
import CredentialsProvider from "next-auth/providers/credentials";
import GoogleProvider from "next-auth/providers/google";
import { type NextAuthOptions } from "next-auth";
import prisma from "@/lib/prisma";
import {type NextAuthOptions} from "next-auth";
import bcrypt from "bcryptjs";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import {prisma} from "@/lib/prisma"
export const authOptions = {
providers: [
@@ -13,9 +14,9 @@ export const authOptions = {
CredentialsProvider({
name: "credentials",
credentials: {
email: { label: "Email", type: "email" },
name: { label: "Name", type: "name" },
password: { label: "Password", type: "password" },
email: {label: "Email", type: "email"},
name: {label: "Name", type: "name"},
password: {label: "Password", type: "password"},
},
async authorize(credentials) {
if (!credentials?.email || !credentials?.password) {
@@ -23,7 +24,7 @@ export const authOptions = {
}
const user = await prisma.user.findUnique({
where: { email: credentials.email },
where: {email: credentials.email},
});
if (!user || !user.password) {
@@ -46,12 +47,15 @@ export const authOptions = {
pages: {
signIn: "/login",
},
callbacks: {
async jwt({ token, user }) {
return { ...token, id: token.id ?? user?.id };
},
async session({ session, token }) {
return { ...session, user: { ...session.user, id: token.id } };
},
},
adapter: PrismaAdapter(prisma),
debug: process.env.NODE_ENV === "development",
secret: process.env.NEXTAUTH_SECRET,
// callbacks: {
// async jwt({ token, user }) {
// return { ...token, id: token.id ?? user?.id };
// },
// async session({ session, token }) {
// return { ...session, user: { ...session.user, id: token.id } };
// },
// },
} satisfies NextAuthOptions;

View File

@@ -1,6 +1,6 @@
"use server";
import prisma from "@/lib/prisma";
import { prisma }from "@/lib/prisma";
/**
* Checks if the Post table exists in the database

View File

@@ -1,10 +1,11 @@
import { PrismaClient } from '@prisma/client'
import { withAccelerate } from '@prisma/extension-accelerate'
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient().$extends(withAccelerate())
const globalForPrisma = global as unknown as { prisma: PrismaClient };
const globalForPrisma = global as unknown as { prisma: typeof prisma }
export const prisma =
globalForPrisma.prisma ||
new PrismaClient({
log: ["query"],
});
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

85
package-lock.json generated
View File

@@ -9,12 +9,14 @@
"version": "0.1.0",
"hasInstallScript": true,
"dependencies": {
"@auth/prisma-adapter": "^2.10.0",
"@next-auth/prisma-adapter": "^1.0.7",
"@prisma/client": "^6.12.0",
"@prisma/extension-accelerate": "^2.0.2",
"bcryptjs": "^3.0.2",
"lucide-react": "^0.503.0",
"next": "^15.4.4",
"next-auth": "^4.24.11",
"next-auth": "^4.24.7",
"react": "^19.1.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0"
@@ -46,6 +48,78 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@auth/prisma-adapter": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/@auth/prisma-adapter/-/prisma-adapter-2.10.0.tgz",
"integrity": "sha512-EliOQoTjGK87jWWqnJvlQjbR4PjQZQqtwRwPAe108WwT9ubuuJJIrL68aNnQr4hFESz6P7SEX2bZy+y2yL37Gw==",
"dependencies": {
"@auth/core": "0.40.0"
},
"peerDependencies": {
"@prisma/client": ">=2.26.0 || >=3 || >=4 || >=5 || >=6"
}
},
"node_modules/@auth/prisma-adapter/node_modules/@auth/core": {
"version": "0.40.0",
"resolved": "https://registry.npmjs.org/@auth/core/-/core-0.40.0.tgz",
"integrity": "sha512-n53uJE0RH5SqZ7N1xZoMKekbHfQgjd0sAEyUbE+IYJnmuQkbvuZnXItCU7d+i7Fj8VGOgqvNO7Mw4YfBTlZeQw==",
"dependencies": {
"@panva/hkdf": "^1.2.1",
"jose": "^6.0.6",
"oauth4webapi": "^3.3.0",
"preact": "10.24.3",
"preact-render-to-string": "6.5.11"
},
"peerDependencies": {
"@simplewebauthn/browser": "^9.0.1",
"@simplewebauthn/server": "^9.0.2",
"nodemailer": "^6.8.0"
},
"peerDependenciesMeta": {
"@simplewebauthn/browser": {
"optional": true
},
"@simplewebauthn/server": {
"optional": true
},
"nodemailer": {
"optional": true
}
}
},
"node_modules/@auth/prisma-adapter/node_modules/jose": {
"version": "6.0.12",
"resolved": "https://registry.npmjs.org/jose/-/jose-6.0.12.tgz",
"integrity": "sha512-T8xypXs8CpmiIi78k0E+Lk7T2zlK4zDyg+o1CZ4AkOHgDg98ogdP2BeZ61lTFKFyoEwJ9RgAgN+SdM3iPgNonQ==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/@auth/prisma-adapter/node_modules/oauth4webapi": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.6.0.tgz",
"integrity": "sha512-OwXPTXjKPOldTpAa19oksrX9TYHA0rt+VcUFTkJ7QKwgmevPpNm9Cn5vFZUtIo96FiU6AfPuUUGzoXqgOzibWg==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/@auth/prisma-adapter/node_modules/preact": {
"version": "10.24.3",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz",
"integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/@auth/prisma-adapter/node_modules/preact-render-to-string": {
"version": "6.5.11",
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.11.tgz",
"integrity": "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==",
"peerDependencies": {
"preact": ">=10"
}
},
"node_modules/@babel/runtime": {
"version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz",
@@ -1152,6 +1226,15 @@
"@tybys/wasm-util": "^0.10.0"
}
},
"node_modules/@next-auth/prisma-adapter": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@next-auth/prisma-adapter/-/prisma-adapter-1.0.7.tgz",
"integrity": "sha512-Cdko4KfcmKjsyHFrWwZ//lfLUbcLqlyFqjd/nYE2m3aZ7tjMNUjpks47iw7NTCnXf+5UWz5Ypyt1dSs1EP5QJw==",
"peerDependencies": {
"@prisma/client": ">=2.26.0 || >=3",
"next-auth": "^4"
}
},
"node_modules/@next/env": {
"version": "15.4.4",
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.4.4.tgz",

View File

@@ -10,12 +10,14 @@
"postinstall": "npx prisma generate --no-engine"
},
"dependencies": {
"@auth/prisma-adapter": "^2.10.0",
"@next-auth/prisma-adapter": "^1.0.7",
"@prisma/client": "^6.12.0",
"@prisma/extension-accelerate": "^2.0.2",
"bcryptjs": "^3.0.2",
"lucide-react": "^0.503.0",
"next": "^15.4.4",
"next-auth": "^4.24.11",
"next-auth": "^4.24.7",
"react": "^19.1.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0"

View File

@@ -1,30 +1,26 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id String @id @default(cuid())
name String?
email String @unique
password String
id String @id @default(cuid())
name String?
email String? @unique
password String? // <-- Add this for email/password auth
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Optional for WebAuthn support
Authenticator Authenticator[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Account {
@@ -41,6 +37,9 @@ model Account {
id_token String?
session_state String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@ -51,6 +50,32 @@ model Session {
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model VerificationToken {
identifier String
token String
expires DateTime
@@unique([identifier, token])
}
// Optional for WebAuthn support
model Authenticator {
credentialID String @unique
userId String
providerAccountId String
credentialPublicKey String
counter Int
credentialDeviceType String
credentialBackedUp Boolean
transports String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
@@id([userId, credentialID])
}

View File

@@ -4,7 +4,6 @@ import bcrypt from 'bcryptjs';
const prisma = new PrismaClient();
async function main() {
// Create 5 users with hashed passwords
const users = await Promise.all([
prisma.user.create({
data: {