Новые изменения в компоненты

This commit is contained in:
Web-serfer 2026-05-05 21:12:46 +05:00
parent da261fcf9f
commit f14125d198
2 changed files with 123 additions and 21 deletions

View file

@ -1,11 +1,55 @@
import type { APIRoute } from 'astro';
const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://localhost:8090';
const PB_ADMIN_EMAIL = import.meta.env.PB_ADMIN_EMAIL;
const PB_ADMIN_PASSWORD = import.meta.env.PB_ADMIN_PASSWORD;
const PASSWORD_MIN_LENGTH = 8;
const PASSWORD_MAX_LENGTH = 12;
const PASSWORD_REGEX = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d_!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]+$/;
async function getAdminToken(): Promise<string> {
const response = await fetch(`${PB_POCKETBASE_URL}/api/admins/auth-with-password`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
identity: PB_ADMIN_EMAIL,
password: PB_ADMIN_PASSWORD
})
});
if (!response.ok) {
throw new Error('Не удалось авторизоваться как админ');
}
const data = await response.json();
return data.token;
}
async function getUserIdByResetToken(token: string): Promise<string | null> {
try {
const adminToken = await getAdminToken();
const response = await fetch(`${PB_POCKETBASE_URL}/api/collections/users/records?filter=reset_token="${token}"&limit=1`, {
headers: {
'Authorization': `Bearer ${adminToken}`
}
});
if (!response.ok) return null;
const data = await response.json();
if (data.items && data.items.length > 0) {
return data.items[0].id;
}
return null;
} catch (e) {
console.error('[CONFIRM_RESET] Error getting user by token:', e);
return null;
}
}
function validatePassword(password: string): { valid: boolean; error?: string } {
if (!password || password.length < PASSWORD_MIN_LENGTH) {
return { valid: false, error: 'Пароль должен быть не менее 8 символов' };
@ -62,39 +106,48 @@ export const POST: APIRoute = async ({ request }) => {
);
}
const confirmUrl = `${PB_POCKETBASE_URL}/api/collections/users/confirm-password-reset`;
const response = await fetch(confirmUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token, password, passwordConfirm }),
});
if (response.status === 204) {
// Ищем пользователя по токену через Admin API
const userId = await getUserIdByResetToken(token);
if (!userId) {
return new Response(
JSON.stringify({
success: true,
message: 'Пароль успешно изменён'
}),
{ status: 200, headers: { 'Content-Type': 'application/json' } }
JSON.stringify({ error: 'Неверный или истёкший токен сброса пароля' }),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
let data;
try {
data = await response.json();
} catch {
// Обновляем пароль через Admin API (обходит валидацию PB)
const adminToken = await getAdminToken();
const updateResponse = await fetch(`${PB_POCKETBASE_URL}/api/collections/users/records/${userId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${adminToken}`
},
body: JSON.stringify({
password: password,
passwordConfirm: passwordConfirm,
reset_token: '', // Очищаем токен
reset_token_expires: ''
})
});
if (!updateResponse.ok) {
const updateData = await updateResponse.json();
console.log('[CONFIRM_RESET] Update error:', updateData);
return new Response(
JSON.stringify({ error: 'Ошибка обработки ответа' }),
JSON.stringify({ error: 'Не удалось обновить пароль' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
return new Response(
JSON.stringify({
error: data.message || 'Неверный или истёкший токен сброса пароля'
success: true,
message: 'Пароль успешно изменён'
}),
{ status: response.status, headers: { 'Content-Type': 'application/json' } }
{ status: 200, headers: { 'Content-Type': 'application/json' } }
);
} catch (error) {