ваше сообщение коммита
This commit is contained in:
@@ -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) {
|
|
||||||
userId = req.session.userId;
|
|
||||||
logger.info(`[email/verify-code] Using existing authenticated user ID ${userId}`);
|
|
||||||
} else {
|
|
||||||
// Проверяем, существует ли пользователь с таким email
|
|
||||||
const existingUser = await db.query(
|
|
||||||
`SELECT u.id FROM users u
|
|
||||||
JOIN user_identities ui ON u.id = ui.user_id
|
|
||||||
WHERE ui.provider = 'email' AND ui.provider_id = $1`,
|
|
||||||
[pendingEmail]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingUser.rows.length > 0) {
|
// Сохраняем email как identity
|
||||||
userId = existingUser.rows[0].id;
|
await saveUserIdentity(userId, 'email', email.toLowerCase(), true);
|
||||||
logger.info(`[email/verify-code] Found existing user with ID ${userId} for email ${pendingEmail}`);
|
logger.info(`[email/verify-code] Saved email identity ${email} for user ${userId}`);
|
||||||
} else {
|
|
||||||
// Создаем нового пользователя только если нет существующей аутентификации
|
// Если есть гостевой ID, сохраняем его
|
||||||
const newUser = await db.query(
|
if (guestId) {
|
||||||
'INSERT INTO users (created_at) VALUES (NOW()) RETURNING id'
|
await saveUserIdentity(userId, 'guest', guestId, true);
|
||||||
);
|
logger.info(`[email/verify-code] Saved guest ID ${guestId} for user ${userId}`);
|
||||||
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,6 +1265,11 @@ 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);
|
||||||
@@ -1271,7 +1277,7 @@ router.post('/email/verify-code', async (req, res) => {
|
|||||||
return res.json({
|
return res.json({
|
||||||
success: true,
|
success: true,
|
||||||
userId,
|
userId,
|
||||||
email: pendingEmail,
|
email: email.toLowerCase(),
|
||||||
authenticated: true
|
authenticated: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user