jefflix-website/app/api/request-access/route.ts

104 lines
3.5 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import nodemailer from 'nodemailer'
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const { name, email, reason } = body
// Validate required fields
if (!name || !email) {
return NextResponse.json(
{ error: 'Name and email are required' },
{ status: 400 }
)
}
// Email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!emailRegex.test(email)) {
return NextResponse.json(
{ error: 'Invalid email format' },
{ status: 400 }
)
}
const smtpHost = process.env.SMTP_HOST
const smtpUser = process.env.SMTP_USER
const smtpPass = process.env.SMTP_PASS
if (!smtpHost || !smtpUser || !smtpPass) {
console.error('SMTP credentials not configured')
return NextResponse.json(
{ error: 'Email service not configured' },
{ status: 500 }
)
}
const adminEmail = process.env.ADMIN_EMAIL || 'jeff@jeffemmett.com'
const transporter = nodemailer.createTransport({
host: smtpHost,
port: Number(process.env.SMTP_PORT) || 587,
secure: false,
auth: { user: smtpUser, pass: smtpPass },
tls: { rejectUnauthorized: false },
})
await transporter.sendMail({
from: `Jefflix <${smtpUser}>`,
to: adminEmail,
subject: `[Jefflix] New Access Request from ${name}`,
html: `
<h2>New Jefflix Access Request</h2>
<p>Someone has requested access to Jefflix:</p>
<table style="border-collapse: collapse; margin: 20px 0;">
<tr>
<td style="padding: 8px; font-weight: bold; border: 1px solid #ddd;">Name:</td>
<td style="padding: 8px; border: 1px solid #ddd;">${escapeHtml(name)}</td>
</tr>
<tr>
<td style="padding: 8px; font-weight: bold; border: 1px solid #ddd;">Email:</td>
<td style="padding: 8px; border: 1px solid #ddd;"><a href="mailto:${escapeHtml(email)}">${escapeHtml(email)}</a></td>
</tr>
<tr>
<td style="padding: 8px; font-weight: bold; border: 1px solid #ddd;">Reason:</td>
<td style="padding: 8px; border: 1px solid #ddd;">${escapeHtml(reason || 'Not provided')}</td>
</tr>
<tr>
<td style="padding: 8px; font-weight: bold; border: 1px solid #ddd;">Requested:</td>
<td style="padding: 8px; border: 1px solid #ddd;">${new Date().toLocaleString()}</td>
</tr>
</table>
<p>To approve this request:</p>
<ol>
<li>Go to <a href="https://movies.jefflix.lol">Jellyfin Dashboard</a></li>
<li>Navigate to Dashboard → Users → Add User</li>
<li>Create an account for ${escapeHtml(name)} (${escapeHtml(email)})</li>
<li>Reply to this email to let them know their account is ready</li>
</ol>
<hr style="margin: 20px 0; border: none; border-top: 1px solid #ddd;" />
<p style="color: #666; font-size: 12px;">This is an automated message from Jefflix.</p>
`,
})
return NextResponse.json({ success: true })
} catch (error) {
console.error('Request access error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}
function escapeHtml(text: string): string {
const map: Record<string, string> = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#039;',
}
return text.replace(/[&<>"']/g, (char) => map[char])
}