- Adiciona página /recuperar para solicitar redefinição de senha - Adiciona página /redefinir-senha para definir nova senha com token - Cria APIs /api/auth/forgot-password e /api/auth/reset-password - Adiciona notificação por e-mail quando ticket é criado - Repagina página de configurações removendo informações técnicas - Adiciona script de teste para todos os tipos de e-mail - Corrige acentuações em templates de e-mail 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
97 lines
2.8 KiB
TypeScript
97 lines
2.8 KiB
TypeScript
import { NextResponse } from "next/server"
|
|
import { hashPassword } from "better-auth/crypto"
|
|
|
|
import { prisma } from "@/lib/prisma"
|
|
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const body = await request.json()
|
|
const { token, password } = body
|
|
|
|
if (!token || typeof token !== "string") {
|
|
return NextResponse.json({ error: "Token inválido" }, { status: 400 })
|
|
}
|
|
|
|
if (!password || typeof password !== "string" || password.length < 6) {
|
|
return NextResponse.json({ error: "A senha deve ter pelo menos 6 caracteres" }, { status: 400 })
|
|
}
|
|
|
|
// Busca o token de verificação
|
|
const verification = await prisma.authVerification.findFirst({
|
|
where: {
|
|
value: token,
|
|
identifier: { startsWith: "password-reset:" },
|
|
expiresAt: { gt: new Date() },
|
|
},
|
|
})
|
|
|
|
if (!verification) {
|
|
return NextResponse.json({ error: "Token inválido ou expirado" }, { status: 400 })
|
|
}
|
|
|
|
// Extrai o userId do identifier
|
|
const userId = verification.identifier.replace("password-reset:", "")
|
|
|
|
// Busca o usuário
|
|
const user = await prisma.authUser.findUnique({
|
|
where: { id: userId },
|
|
})
|
|
|
|
if (!user) {
|
|
return NextResponse.json({ error: "Usuário não encontrado" }, { status: 400 })
|
|
}
|
|
|
|
// Hash da nova senha
|
|
const hashedPassword = await hashPassword(password)
|
|
|
|
// Atualiza a conta do usuário com a nova senha
|
|
await prisma.authAccount.updateMany({
|
|
where: {
|
|
userId: user.id,
|
|
providerId: "credential",
|
|
},
|
|
data: {
|
|
password: hashedPassword,
|
|
},
|
|
})
|
|
|
|
// Remove o token usado
|
|
await prisma.authVerification.delete({
|
|
where: { id: verification.id },
|
|
})
|
|
|
|
return NextResponse.json({ success: true })
|
|
} catch (error) {
|
|
console.error("[RESET_PASSWORD] Erro:", error)
|
|
return NextResponse.json({ error: "Erro ao redefinir senha" }, { status: 500 })
|
|
}
|
|
}
|
|
|
|
// GET para validar se o token é válido (usado pela página)
|
|
export async function GET(request: Request) {
|
|
try {
|
|
const { searchParams } = new URL(request.url)
|
|
const token = searchParams.get("token")
|
|
|
|
if (!token) {
|
|
return NextResponse.json({ valid: false, error: "Token não fornecido" })
|
|
}
|
|
|
|
const verification = await prisma.authVerification.findFirst({
|
|
where: {
|
|
value: token,
|
|
identifier: { startsWith: "password-reset:" },
|
|
expiresAt: { gt: new Date() },
|
|
},
|
|
})
|
|
|
|
if (!verification) {
|
|
return NextResponse.json({ valid: false, error: "Token inválido ou expirado" })
|
|
}
|
|
|
|
return NextResponse.json({ valid: true })
|
|
} catch (error) {
|
|
console.error("[RESET_PASSWORD] Erro ao validar token:", error)
|
|
return NextResponse.json({ valid: false, error: "Erro ao validar token" })
|
|
}
|
|
}
|