astro_avtourist/frontend/src/pages/api/auth/forgot-password.ts

123 lines
No EOL
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { APIRoute } from 'astro';
import PocketBase from 'pocketbase';
import { sendEmail, getSiteUrl } from '../../../lib/email';
function generateResetPasswordHtml(firstName: string, resetLink: string): string {
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Сброс пароля</title>
</head>
<body style="margin: 0; padding: 0; background-color: #f5f7fa; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f5f7fa; padding: 40px 20px;">
<tr>
<td align="center">
<table width="100%" cellpadding="0" cellspacing="0" style="max-width: 600px; background-color: #ffffff; border-radius: 16px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.08);">
<tr>
<td style="background: linear-gradient(135deg, #1e3050 0%, #2d4a6f 100%); padding: 30px 40px; text-align: center;">
<h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: 700;">Автоюрист Сургут</h1>
<p style="color: rgba(255,255,255,0.8); margin: 10px 0 0 0; font-size: 16px;">Юридические услуги для автовладельцев</p>
</td>
</tr>
<tr>
<td style="padding: 40px;">
<h2 style="color: #1e3050; margin: 0 0 20px 0; font-size: 24px; font-weight: 700;">Сброс пароля</h2>
<p style="color: #64748b; font-size: 16px; line-height: 1.6; margin: 0 0 20px 0;">
Здравствуйте, ${firstName}!
</p>
<p style="color: #64748b; font-size: 16px; line-height: 1.6; margin: 0 0 30px 0;">
Вы запросили сброс пароля. Нажмите кнопку ниже для создания нового пароля:
</p>
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<a href="${resetLink}" style="display: inline-block; background: linear-gradient(135deg, #eac26e 0%, #ce9f40 100%); color: #ffffff; text-decoration: none; padding: 16px 32px; border-radius: 8px; font-size: 16px; font-weight: 700;">
Сбросить пароль
</a>
</td>
</tr>
</table>
<p style="color: #94a3b8; font-size: 14px; margin: 30px 0 0 0;">
Ссылка действительна 1 час. Если вы не запрашивали сброс пароля, просто проигнорируйте это письмо.
</p>
</td>
</tr>
<tr>
<td style="background-color: #1e3050; padding: 24px 40px; text-align: center;">
<p style="color: rgba(255,255,255,0.6); font-size: 14px; margin: 0;">
© 2026 Автоюрист Сургут. Все права защищены.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>`;
}
export const POST: APIRoute = async ({ request }) => {
try {
const pb = new PocketBase(import.meta.env.POCKETBASE_URL);
const data = await request.json();
const { email } = data;
console.log('Password reset request:', email);
if (!email) {
return new Response(JSON.stringify({
success: false,
error: 'Email обязателен'
}), { status: 400 });
}
// Проверяем существует ли пользователь
let user = null;
try {
user = await pb.collection('users').getFirstListItem(`email="${email}"`);
} catch (e) {
console.log('User not found, still return success');
}
if (!user) {
return new Response(JSON.stringify({
success: true,
message: 'Ссылка для сброса пароля отправлена'
}), { status: 200 });
}
// Создаём свой токен сброса (как для верификации)
const resetToken = Buffer.from(`${user.id}:${Date.now()}`).toString('base64').replace(/=/g, '');
const resetLink = `${getSiteUrl()}/auth/reset-password?token=${resetToken}&userId=${user.id}`;
// Отправляем письмо
const firstName = user.firstName || 'Пользователь';
const html = generateResetPasswordHtml(firstName, resetLink);
const emailSent = await sendEmail({
to: email,
subject: 'Сброс пароля — Автоюрист Сургут',
html
});
console.log('Reset email sent:', emailSent);
return new Response(JSON.stringify({
success: true,
message: 'Ссылка для сброса пароля отправлена'
}), { status: 200 });
} catch (error: any) {
console.error('Forgot password error:', error);
return new Response(JSON.stringify({
success: true,
message: 'Ссылка для сброса пароля отправлена'
}), { status: 200 });
}
};