76 lines
3.3 KiB
TypeScript
76 lines
3.3 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { prisma } from '@/lib/db'
|
|
import { sendEmail } from '@/lib/email'
|
|
import { randomBytes } from 'crypto'
|
|
import { resendVerificationLimiter, getClientIp, rateLimitResponse } from '@/lib/rate-limit'
|
|
|
|
export async function POST(req: NextRequest) {
|
|
try {
|
|
const ip = getClientIp(req)
|
|
const rl = resendVerificationLimiter.check(ip)
|
|
if (!rl.success) return rateLimitResponse(rl.resetAt)
|
|
|
|
const { email } = await req.json()
|
|
|
|
if (!email) {
|
|
return NextResponse.json({ error: 'E-Mail-Adresse erforderlich.' }, { status: 400 })
|
|
}
|
|
|
|
const user = await (prisma as any).user.findUnique({
|
|
where: { email },
|
|
include: { memberships: { include: { tenant: true } } },
|
|
})
|
|
|
|
if (!user) {
|
|
// Don't reveal whether user exists
|
|
return NextResponse.json({ success: true, message: 'Falls ein Konto mit dieser E-Mail existiert, wurde eine neue Bestätigungsmail gesendet.' })
|
|
}
|
|
|
|
if (user.emailVerified) {
|
|
return NextResponse.json({ success: true, message: 'Ihre E-Mail-Adresse ist bereits bestätigt. Sie können sich anmelden.' })
|
|
}
|
|
|
|
// Generate new verification token
|
|
const verificationToken = randomBytes(32).toString('hex')
|
|
await (prisma as any).user.update({
|
|
where: { id: user.id },
|
|
data: { emailVerificationToken: verificationToken },
|
|
})
|
|
|
|
// Build verification URL
|
|
let baseUrl = process.env.NEXTAUTH_URL || req.headers.get('origin') || `${req.headers.get('x-forwarded-proto') || 'https'}://${req.headers.get('host')}` || 'http://localhost:3000'
|
|
if (baseUrl && !baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {
|
|
baseUrl = `https://${baseUrl}`
|
|
}
|
|
const verifyUrl = `${baseUrl}/api/auth/verify-email?token=${verificationToken}`
|
|
|
|
const orgName = user.memberships?.[0]?.tenant?.name || 'Lageplan'
|
|
|
|
await sendEmail(
|
|
user.email,
|
|
'E-Mail-Adresse bestätigen — Lageplan',
|
|
`<div style="font-family:sans-serif;max-width:600px;margin:0 auto;">
|
|
<div style="background:#dc2626;color:white;padding:20px 24px;border-radius:12px 12px 0 0;">
|
|
<h1 style="margin:0;font-size:22px;">E-Mail bestätigen</h1>
|
|
</div>
|
|
<div style="border:1px solid #e5e7eb;border-top:none;padding:24px;border-radius:0 0 12px 12px;">
|
|
<p>Hallo <strong>${user.name}</strong>,</p>
|
|
<p>Bitte bestätigen Sie Ihre E-Mail-Adresse, um Ihr Konto für <strong>${orgName}</strong> zu aktivieren.</p>
|
|
<div style="text-align:center;margin:24px 0;">
|
|
<a href="${verifyUrl}" style="background:#dc2626;color:white;padding:12px 32px;text-decoration:none;border-radius:8px;font-weight:600;display:inline-block;">
|
|
E-Mail bestätigen
|
|
</a>
|
|
</div>
|
|
<p style="color:#666;font-size:13px;">Falls der Button nicht funktioniert, kopieren Sie diesen Link:<br/>
|
|
<a href="${verifyUrl}" style="word-break:break-all;">${verifyUrl}</a></p>
|
|
</div>
|
|
</div>`
|
|
)
|
|
|
|
return NextResponse.json({ success: true, message: 'Bestätigungsmail wurde erneut gesendet. Bitte prüfen Sie Ihren Posteingang.' })
|
|
} catch (error) {
|
|
console.error('Resend verification error:', error)
|
|
return NextResponse.json({ error: 'Fehler beim Senden der Bestätigungsmail.' }, { status: 500 })
|
|
}
|
|
}
|