ваше сообщение коммита

This commit is contained in:
2025-04-14 13:23:40 +03:00
parent 67230efec2
commit 4edb33b278
4 changed files with 160 additions and 127 deletions

View File

@@ -256,7 +256,7 @@ router.post('/telegram/verify', async (req, res) => {
logger.error('[telegram/verify] Error regenerating session:', err); logger.error('[telegram/verify] Error regenerating session:', err);
return res.status(500).json({ return res.status(500).json({
success: false, success: false,
error: 'Session regeneration failed' error: 'Session error'
}); });
} }
@@ -285,8 +285,8 @@ router.post('/telegram/verify', async (req, res) => {
}); });
}); });
// Связываем гостевые сообщения только если это новый пользователь // Связываем гостевые сообщения только один раз - исправлено дублирование
if (verificationResult.isNewUser && guestId) { if (guestId) {
// Создаем объект сессии для совместимости с другими методами аутентификации // Создаем объект сессии для совместимости с другими методами аутентификации
const session = { const session = {
guestId: guestId, guestId: guestId,
@@ -298,12 +298,7 @@ router.post('/telegram/verify', async (req, res) => {
} }
}; };
const linkResults = await linkGuestMessagesAfterAuth(session, verificationResult.userId); const linkResults = await linkGuestMessagesAfterAuth(session, verificationResult.userId);
logger.info(`[telegram/verify] Guest messages linking results for new user:`, linkResults); logger.info(`[telegram/verify] Guest messages linking results:`, linkResults);
}
// Если пользователь не новый, но есть гостевой ID, все равно связываем сообщения
else if (!verificationResult.isNewUser && guestId) {
const linkResults = await linkGuestMessagesAfterAuth(req.session, verificationResult.userId);
logger.info(`[telegram/verify] Guest messages linking results for existing user:`, linkResults);
} }
return res.json({ return res.json({
@@ -1168,88 +1163,94 @@ router.get('/email/auth-status/:token', async (req, res) => {
// Маршрут для проверки кода email // Маршрут для проверки кода email
router.post('/email/verify-code', async (req, res) => { router.post('/email/verify-code', async (req, res) => {
try { try {
const { code } = req.body; const { email, code } = req.body;
const pendingEmail = req.session.pendingEmail;
logger.info(`[email/verify-code] Verifying code for email: ${pendingEmail}`); if (!email || !code) {
logger.info(`[email/verify-code] Guest context: guestId=${req.session.guestId}, previousGuestId=${req.session.previousGuestId}`);
if (!pendingEmail) {
logger.warn('[email/verify-code] No pending email found in session');
return res.status(400).json({ return res.status(400).json({
success: false, success: false,
error: 'Нет ожидающей верификации электронной почты' error: 'Email и код подтверждения обязательны'
}); });
} }
if (!code) { logger.info(`[email/verify-code] Verifying code for email: ${email}`);
logger.warn('[email/verify-code] No verification code provided');
return res.status(400).json({ // Сохраняем гостевой ID до проверки
success: false, const guestId = req.session.guestId;
error: 'Код подтверждения не указан' const previousGuestId = req.session.previousGuestId;
});
logger.info(`[email/verify-code] Guest context: guestId=${guestId}, previousGuestId=${previousGuestId}`);
// Проверяем существование пользователя с таким email
const userResult = await db.query(
`SELECT u.id FROM users u
JOIN user_identities ui ON u.id = ui.user_id
WHERE ui.provider = $1 AND ui.provider_id = $2`,
['email', email.toLowerCase()]
);
let userId;
let isNewUser = false;
if (userResult.rows.length > 0) {
// Пользователь уже существует
userId = userResult.rows[0].id;
logger.info(`[email/verify-code] Found existing user with ID ${userId}`);
} else if (req.session.tempUserId) {
// Используем временный ID пользователя
userId = req.session.tempUserId;
logger.info(`[email/verify-code] Using tempUserId ${userId}`);
} else {
// Создаем нового пользователя
const newUserResult = await db.query(
'INSERT INTO users (created_at, role) VALUES (NOW(), $1) RETURNING id',
['user']
);
userId = newUserResult.rows[0].id;
isNewUser = true;
logger.info(`[email/verify-code] Created new user with ID ${userId} for email ${email}`);
} }
// Проверяем код верификации // Проверяем код верификации
const verificationResult = await verifyEmailCode(code, pendingEmail); const verification = await verificationService.verifyCode(
code.toUpperCase(),
'email',
email.toLowerCase()
);
if (!verificationResult.success) { if (!verification.success) {
logger.warn(`[email/verify-code] Invalid verification code for email ${pendingEmail}`); logger.warn(`[email/verify-code] Invalid verification code for ${email}: ${verification.error}`);
return res.status(400).json({ return res.status(400).json({
success: false, success: false,
error: verificationResult.error || 'Неверный код подтверждения' error: verification.error
}); });
} }
// Используем существующего пользователя, если он уже аутентифицирован logger.info(`[email/verify-code] Verification successful for email ${email}, user ${userId}`);
let userId;
if (req.session.authenticated && req.session.userId) { // Сохраняем email как identity
userId = req.session.userId; await saveUserIdentity(userId, 'email', email.toLowerCase(), true);
logger.info(`[email/verify-code] Using existing authenticated user ID ${userId}`); logger.info(`[email/verify-code] Saved email identity ${email} for user ${userId}`);
} else {
// Проверяем, существует ли пользователь с таким email // Если есть гостевой ID, сохраняем его
const existingUser = await db.query( if (guestId) {
`SELECT u.id FROM users u await saveUserIdentity(userId, 'guest', guestId, true);
JOIN user_identities ui ON u.id = ui.user_id logger.info(`[email/verify-code] Saved guest ID ${guestId} for user ${userId}`);
WHERE ui.provider = 'email' AND ui.provider_id = $1`,
[pendingEmail]
);
if (existingUser.rows.length > 0) {
userId = existingUser.rows[0].id;
logger.info(`[email/verify-code] Found existing user with ID ${userId} for email ${pendingEmail}`);
} else {
// Создаем нового пользователя только если нет существующей аутентификации
const newUser = await db.query(
'INSERT INTO users (created_at) VALUES (NOW()) RETURNING id'
);
userId = newUser.rows[0].id;
logger.info(`[email/verify-code] Created new user with ID ${userId} for email ${pendingEmail}`);
}
} }
// Сохраняем email как идентификатор пользователя if (previousGuestId && previousGuestId !== guestId) {
await saveUserIdentity(userId, 'email', pendingEmail, true); await saveUserIdentity(userId, 'guest', previousGuestId, true);
logger.info(`[email/verify-code] Saved email identity ${pendingEmail} for user ${userId}`); logger.info(`[email/verify-code] Saved previous guest ID ${previousGuestId} for user ${userId}`);
// Если есть гостевые ID, сохраняем их
if (req.session.guestId) {
await saveUserIdentity(userId, 'guest', req.session.guestId, true);
logger.info(`[email/verify-code] Saved guest ID ${req.session.guestId} for user ${userId}`);
} }
if (req.session.previousGuestId && req.session.previousGuestId !== req.session.guestId) { // Устанавливаем данные сессии
await saveUserIdentity(userId, 'guest', req.session.previousGuestId, true);
logger.info(`[email/verify-code] Saved previous guest ID ${req.session.previousGuestId} for user ${userId}`);
}
// Обновляем сессию
req.session.authenticated = true; req.session.authenticated = true;
req.session.userId = userId; req.session.userId = userId;
req.session.email = pendingEmail;
req.session.authType = 'email'; req.session.authType = 'email';
delete req.session.pendingEmail; req.session.email = email.toLowerCase();
// Удаляем временный ID
delete req.session.tempUserId; delete req.session.tempUserId;
delete req.session.pendingEmail;
// Сохраняем сессию перед связыванием сообщений // Сохраняем сессию перед связыванием сообщений
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
@@ -1264,14 +1265,19 @@ router.post('/email/verify-code', async (req, res) => {
}); });
}); });
// Сначала сохраняем сессию с актуальным гостевым ID
if (guestId) {
req.session.guestId = guestId;
}
// Связываем гостевые сообщения с пользователем // Связываем гостевые сообщения с пользователем
const linkResults = await linkGuestMessagesAfterAuth(req.session, userId); const linkResults = await linkGuestMessagesAfterAuth(req.session, userId);
logger.info(`[email/verify-code] Guest messages linking results:`, linkResults); logger.info(`[email/verify-code] Guest messages linking results:`, linkResults);
return res.json({ return res.json({
success: true, success: true,
userId, userId,
email: pendingEmail, email: email.toLowerCase(),
authenticated: true authenticated: true
}); });

View File

@@ -41,38 +41,16 @@ async function processGuestMessages(userId, guestId) {
const conversation = newConversationResult.rows[0]; const conversation = newConversationResult.rows[0];
console.log('Created new conversation for guest messages:', conversation); console.log('Created new conversation for guest messages:', conversation);
// Отслеживаем успешные сохранения сообщений
const savedMessageIds = [];
// Обрабатываем каждое гостевое сообщение // Обрабатываем каждое гостевое сообщение
for (const guestMessage of guestMessages) { for (const guestMessage of guestMessages) {
console.log(`Processing guest message ID ${guestMessage.id}: ${guestMessage.content}`); console.log(`Processing guest message ID ${guestMessage.id}: ${guestMessage.content}`);
// Сохраняем сообщение пользователя try {
const userMessageResult = await db.query( // Сохраняем сообщение пользователя
`INSERT INTO messages const userMessageResult = await db.query(
(conversation_id, content, sender_type, role, channel, created_at)
VALUES
($1, $2, $3, $4, $5, $6)
RETURNING *`,
[
conversation.id,
guestMessage.content,
'user',
'user',
'web',
guestMessage.created_at
]
);
console.log(`Saved user message with ID ${userMessageResult.rows[0].id}`);
// Получаем ответ от ИИ только для сообщений пользователя (не AI)
if (!guestMessage.is_ai) {
console.log('Getting AI response for:', guestMessage.content);
const language = guestMessage.language || 'auto';
const aiResponse = await aiAssistant.getResponse(guestMessage.content, language);
console.log('AI response received:', aiResponse);
// Сохраняем ответ от ИИ
const aiMessageResult = await db.query(
`INSERT INTO messages `INSERT INTO messages
(conversation_id, content, sender_type, role, channel, created_at) (conversation_id, content, sender_type, role, channel, created_at)
VALUES VALUES
@@ -80,25 +58,60 @@ async function processGuestMessages(userId, guestId) {
RETURNING *`, RETURNING *`,
[ [
conversation.id, conversation.id,
aiResponse, guestMessage.content,
'assistant', 'user',
'assistant', 'user',
'web', 'web',
new Date() guestMessage.created_at
] ]
); );
console.log(`Saved AI response with ID ${aiMessageResult.rows[0].id}`); console.log(`Saved user message with ID ${userMessageResult.rows[0].id}`);
savedMessageIds.push(guestMessage.id);
// Получаем ответ от ИИ только для сообщений пользователя (не AI)
if (!guestMessage.is_ai) {
console.log('Getting AI response for:', guestMessage.content);
const language = guestMessage.language || 'auto';
const aiResponse = await aiAssistant.getResponse(guestMessage.content, language);
console.log('AI response received:', aiResponse);
// Сохраняем ответ от ИИ
const aiMessageResult = await db.query(
`INSERT INTO messages
(conversation_id, content, sender_type, role, channel, created_at)
VALUES
($1, $2, $3, $4, $5, $6)
RETURNING *`,
[
conversation.id,
aiResponse,
'assistant',
'assistant',
'web',
new Date()
]
);
console.log(`Saved AI response with ID ${aiMessageResult.rows[0].id}`);
}
} catch (error) {
console.error(`Error processing guest message ${guestMessage.id}:`, error);
// Продолжаем с другими сообщениями в случае ошибки
} }
} }
// Удаляем обработанные гостевые сообщения // Удаляем только успешно обработанные гостевые сообщения
await db.query('DELETE FROM guest_messages WHERE guest_id = $1', [guestId]); if (savedMessageIds.length > 0) {
console.log(`Deleted processed guest messages for guest ID ${guestId}`); await db.query('DELETE FROM guest_messages WHERE id = ANY($1)', [savedMessageIds]);
console.log(`Deleted ${savedMessageIds.length} processed guest messages for guest ID ${guestId}`);
} else {
console.log('No guest messages were successfully processed, skipping deletion');
}
return { return {
success: true, success: true,
message: `Processed ${guestMessages.length} guest messages`, message: `Processed ${savedMessageIds.length} of ${guestMessages.length} guest messages`,
conversationId: conversation.id conversationId: conversation.id
}; };
} catch (error) { } catch (error) {

View File

@@ -77,9 +77,6 @@ export async function connectWithWallet() {
localStorage.setItem('userId', verificationResponse.data.userId); localStorage.setItem('userId', verificationResponse.data.userId);
localStorage.setItem('address', verificationResponse.data.address); localStorage.setItem('address', verificationResponse.data.address);
localStorage.setItem('isAdmin', verificationResponse.data.isAdmin); localStorage.setItem('isAdmin', verificationResponse.data.isAdmin);
// Перезагружаем страницу для обновления состояния
window.location.reload();
} }
return verificationResponse.data; return verificationResponse.data;

View File

@@ -529,11 +529,8 @@ const formatIdentityProvider = (provider) => {
// ===================================================================== // =====================================================================
/** /**
* Загружает историю сообщений * Загружает сообщения пользователя из истории
* @param {Object} options - Параметры загрузки * @param {Object} options - Опции загрузки
* @param {boolean} options.silent - Не показывать индикатор загрузки
* @param {boolean} options.initial - Первоначальная загрузка
* @param {string} options.authType - Тип аутентификации
*/ */
const loadMessages = async (options = {}) => { const loadMessages = async (options = {}) => {
const { silent = false, initial = false, authType = null } = options; const { silent = false, initial = false, authType = null } = options;
@@ -547,16 +544,32 @@ const loadMessages = async (options = {}) => {
console.log(`Загрузка истории сообщений${authType ? ` после ${authType} аутентификации` : ''}...`); console.log(`Загрузка истории сообщений${authType ? ` после ${authType} аутентификации` : ''}...`);
// Если это загрузка после аутентификации, ждем завершения привязки гостевых сообщений // Если это загрузка после аутентификации, немного ждем для завершения привязки сообщений
if (authType && messageLoading.value.isLinkingGuest) { if (authType) {
await new Promise(resolve => { console.log(`Ожидание завершения привязки гостевых сообщений после ${authType} аутентификации...`);
const checkInterval = setInterval(() => {
if (!messageLoading.value.isLinkingGuest) { // Задержка для гарантии, что сервер успеет обработать сессию
await new Promise(resolve => setTimeout(resolve, 1000));
// Дополнительно проверяем, что процесс связывания сообщений завершился
if (messageLoading.value.isLinkingGuest) {
await new Promise(resolve => {
const checkInterval = setInterval(() => {
if (!messageLoading.value.isLinkingGuest) {
clearInterval(checkInterval);
resolve();
}
}, 100);
// Таймаут на всякий случай
setTimeout(() => {
clearInterval(checkInterval); clearInterval(checkInterval);
resolve(); resolve();
} }, 5000);
}, 100); });
}); }
console.log('Привязка сообщений завершена, загружаем историю...');
} }
// Проверяем сессию перед загрузкой // Проверяем сессию перед загрузкой
@@ -568,10 +581,14 @@ const loadMessages = async (options = {}) => {
messageLoading.value.isLoadingMore = false; messageLoading.value.isLoadingMore = false;
messageLoading.value.isInProgress = false; messageLoading.value.isInProgress = false;
isLoading.value = false; isLoading.value = false;
return; return;
} }
} catch (error) { } catch (error) {
console.warn('Ошибка проверки сессии, продолжаем загрузку:', error); console.error('Ошибка при проверке сессии:', error);
messageLoading.value.isLoadingMore = false;
messageLoading.value.isInProgress = false;
isLoading.value = false;
return;
} }
} }