feat: replace custom login/signup with NextAuth credentials provider, add signup page using Prisma, update NextAuth config to JWT strategy

This commit is contained in:
Carlos
2026-07-10 21:59:06 +02:00
parent 583170efd1
commit 71da57088f
2 changed files with 46 additions and 43 deletions
+28 -23
View File
@@ -1,52 +1,57 @@
import NextAuth from "next-auth" import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials" import CredentialsProvider from "next-auth/providers/credentials"
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { PrismaClient } from "@prisma/client" import { PrismaClient } from "@prisma/client"
import bcrypt from "bcryptjs" import bcrypt from "bcryptjs"
const prisma = new PrismaClient() const prisma = new PrismaClient()
export default NextAuth({ export default NextAuth({
adapter: PrismaAdapter(prisma),
trustHost: true,
providers: [ providers: [
CredentialsProvider({ CredentialsProvider({
name: "Credentials", name: "Credentials",
credentials: { credentials: {
username: { label: "Username", type: "text", placeholder: "seu_usuario" }, username: { label: "Username", type: "text" },
password: { label: "Password", type: "password" } password: { label: "Password", type: "password" }
}, },
async authorize(credentials) { async authorize(credentials) {
if (!credentials?.username || !credentials?.password) return null if (!credentials?.username || !credentials?.password) return null
const user = await prisma.user.findUnique({ const user = await prisma.user.findUnique({
where: { username: credentials.username } where: { username: credentials.username }
}) })
if (!user) return null
if (user && user.password) { const isValid = await bcrypt.compare(credentials.password, user.password)
const isValid = await bcrypt.compare(credentials.password, user.password) if (!isValid) return null
if (isValid) { return {
return { id: user.id,
id: user.id, username: user.username,
email: user.email, email: user.email,
name: user.name || user.username, name: user.name,
username: user.username // optional: role, image, etc.
}
}
} }
return null
} }
}) })
], ],
secret: process.env.NEXTAUTH_SECRET, secret: process.env.NEXTAUTH_SECRET,
session: { strategy: "jwt" }, session: {
pages: { strategy: "jwt",
signIn: "/signin", maxAge: 30 * 24 * 60 * 60 // 30 days
}, },
callbacks: { callbacks: {
async session({ session, token, user }) { async jwt({ token, user }) {
if (session.user) { if (user) {
session.user.id = token.sub token.id = user.id
token.username = user.username
token.email = user.email
token.name = user.name
}
return token
},
async session({ session, token }) {
if (token) {
session.user.id = token.id
session.user.username = token.username
session.user.email = token.email
session.user.name = token.name
} }
return session return session
} }
+15 -17
View File
@@ -12,21 +12,19 @@ export default function SignUp() {
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault() e.preventDefault()
setError("") setError("")
if (password !== confirmPassword) {
setError("Senhas não coincidem")
return
}
if (password.length < 6) {
setError("Senha deve ter pelo menos 6 caracteres")
return
}
setLoading(true) setLoading(true)
try { try {
const res = await fetch("/api/auth/signup", { if (password !== confirmPassword) {
setError("Senhas não coincidem")
return
}
if (password.length < 6) {
setError("Senha deve ter pelo menos 6 caracteres")
return
}
const res = await fetch("/api/auth/register", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }) body: JSON.stringify({ username, password })
@@ -52,7 +50,7 @@ export default function SignUp() {
<h2 className="text-2xl font-bold mb-6">Cadastrar - 1000Apps</h2> <h2 className="text-2xl font-bold mb-6">Cadastrar - 1000Apps</h2>
{error && ( {error && (
<div className="bg-red-100 text-red-700 p-3 rounded mb-4"> <div className="mb-4 bg-red-100 text-red-700 p-3 rounded">
{error} {error}
</div> </div>
)} )}
@@ -61,26 +59,26 @@ export default function SignUp() {
<input <input
type="text" type="text"
placeholder="Nome de usuário" placeholder="Nome de usuário"
className="w-full p-2 border rounded"
value={username} value={username}
onChange={(e) => setUsername(e.target.value)} onChange={(e) => setUsername(e.target.value)}
className="w-full p-2 border rounded"
required required
/> />
<input <input
type="password" type="password"
placeholder="Senha" placeholder="Senha"
className="w-full p-2 border rounded"
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
className="w-full p-2 border rounded"
required required
minLength={6} minLength={6}
/> />
<input <input
type="password" type="password"
placeholder="Confirmar senha" placeholder="Confirmar senha"
className="w-full p-2 border rounded"
value={confirmPassword} value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)} onChange={(e) => setConfirmPassword(e.target.value)}
className="w-full p-2 border rounded"
required required
/> />
<button <button