ваше сообщение коммита
This commit is contained in:
@@ -232,11 +232,17 @@ class AuthService {
|
||||
// Создание сессии с проверкой роли
|
||||
async createSession(session, { userId, authenticated, authType, guestId, address }) {
|
||||
try {
|
||||
// Если пользователь аутентифицирован, обрабатываем гостевые сообщения
|
||||
if (authenticated && guestId) {
|
||||
await this.processAndCleanupGuestData(userId, guestId, session);
|
||||
}
|
||||
|
||||
// Обновляем данные сессии
|
||||
session.userId = userId;
|
||||
session.authenticated = authenticated;
|
||||
session.authType = authType;
|
||||
session.guestId = guestId;
|
||||
|
||||
// Сохраняем адрес кошелька если есть
|
||||
if (address) {
|
||||
session.address = address;
|
||||
}
|
||||
@@ -250,7 +256,6 @@ class AuthService {
|
||||
userId,
|
||||
authenticated,
|
||||
authType,
|
||||
guestId,
|
||||
address,
|
||||
cookie: session.cookie
|
||||
}), session.id]
|
||||
@@ -263,6 +268,31 @@ class AuthService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка и очистка гостевых данных после авторизации
|
||||
* @param {number} userId - ID пользователя
|
||||
* @param {string} guestId - Гостевой ID
|
||||
* @param {Object} session - Объект сессии
|
||||
*/
|
||||
async processAndCleanupGuestData(userId, guestId, session) {
|
||||
try {
|
||||
// Обрабатываем гостевые сообщения
|
||||
const { processGuestMessages } = require('../routes/chat');
|
||||
await processGuestMessages(userId, guestId);
|
||||
|
||||
// Очищаем гостевой ID из сессии
|
||||
delete session.guestId;
|
||||
if (session.previousGuestId) {
|
||||
delete session.previousGuestId;
|
||||
}
|
||||
|
||||
logger.info(`Cleaned up guest data for user ${userId}, guest ID ${guestId}`);
|
||||
} catch (error) {
|
||||
logger.error('Error processing and cleaning up guest data:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getSession(sessionId) {
|
||||
try {
|
||||
const result = await db.query('SELECT * FROM session WHERE sid = $1', [sessionId]);
|
||||
|
||||
@@ -70,38 +70,57 @@ class EmailAuth {
|
||||
return { verified: false, message: result.error || 'Неверный код верификации' };
|
||||
}
|
||||
|
||||
const userId = result.userId || session.tempUserId;
|
||||
const email = session.pendingEmail;
|
||||
const email = session.pendingEmail.toLowerCase();
|
||||
let finalUserId;
|
||||
|
||||
// Проверяем, существует ли уже этот email в user_identities
|
||||
const existingUserQuery = await db.query(
|
||||
`SELECT user_id FROM user_identities
|
||||
WHERE provider = 'email' AND provider_id = $1`,
|
||||
[email.toLowerCase()]
|
||||
);
|
||||
// Ищем всех пользователей с похожими идентификаторами
|
||||
const identities = {
|
||||
email: email,
|
||||
guest: session.guestId
|
||||
};
|
||||
|
||||
let finalUserId = userId;
|
||||
|
||||
// Если email уже связан с другим пользователем
|
||||
if (existingUserQuery.rows.length > 0) {
|
||||
finalUserId = existingUserQuery.rows[0].user_id;
|
||||
logger.info(`Using existing user ID ${finalUserId} for email ${email}`);
|
||||
|
||||
// Обновляем идентификатор пользователя в сессии
|
||||
if (userId !== finalUserId) {
|
||||
logger.info(`Changing user ID from ${userId} to ${finalUserId} based on existing email identity`);
|
||||
const relatedUsers = await authService.identityService.findRelatedUsers(identities);
|
||||
logger.info(`[checkEmailVerification] Found ${relatedUsers.length} related users for identities:`, identities);
|
||||
|
||||
if (relatedUsers.length > 0) {
|
||||
// Берем первого найденного пользователя как основного
|
||||
finalUserId = relatedUsers[0];
|
||||
logger.info(`[checkEmailVerification] Using existing user ${finalUserId} as primary`);
|
||||
|
||||
// Мигрируем данные от остальных пользователей к основному
|
||||
for (const userId of relatedUsers.slice(1)) {
|
||||
await authService.identityService.migrateUserData(userId, finalUserId);
|
||||
logger.info(`[checkEmailVerification] Migrated data from user ${userId} to ${finalUserId}`);
|
||||
}
|
||||
|
||||
// Если у нас есть временный пользователь, мигрируем его данные тоже
|
||||
if (session.tempUserId && !relatedUsers.includes(session.tempUserId)) {
|
||||
await authService.identityService.migrateUserData(session.tempUserId, finalUserId);
|
||||
logger.info(`[checkEmailVerification] Migrated temporary user ${session.tempUserId} to ${finalUserId}`);
|
||||
}
|
||||
} else {
|
||||
// Добавляем email в базу данных для нового пользователя
|
||||
await db.query(
|
||||
`INSERT INTO user_identities
|
||||
(user_id, provider, provider_id)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (provider, provider_id)
|
||||
DO UPDATE SET user_id = $1`,
|
||||
[finalUserId, 'email', email.toLowerCase()]
|
||||
);
|
||||
logger.info(`Added new email identity ${email} for user ${finalUserId}`);
|
||||
// Если связанных пользователей нет, используем временного или создаем нового
|
||||
if (session.tempUserId) {
|
||||
finalUserId = session.tempUserId;
|
||||
logger.info(`[checkEmailVerification] Using temporary user ${finalUserId}`);
|
||||
} else {
|
||||
const newUserResult = await db.query(
|
||||
'INSERT INTO users (role) VALUES ($1) RETURNING id',
|
||||
['user']
|
||||
);
|
||||
finalUserId = newUserResult.rows[0].id;
|
||||
logger.info(`[checkEmailVerification] Created new user ${finalUserId}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Добавляем email в базу данных
|
||||
await authService.identityService.saveIdentity(finalUserId, 'email', email, true);
|
||||
logger.info(`[checkEmailVerification] Added email identity ${email} for user ${finalUserId}`);
|
||||
|
||||
// Если есть гостевой ID, добавляем его тоже
|
||||
if (session.guestId) {
|
||||
await authService.identityService.saveIdentity(finalUserId, 'guest', session.guestId, true);
|
||||
logger.info(`[checkEmailVerification] Added guest identity ${session.guestId} for user ${finalUserId}`);
|
||||
}
|
||||
|
||||
// Очищаем временные данные
|
||||
@@ -113,7 +132,7 @@ class EmailAuth {
|
||||
return {
|
||||
verified: true,
|
||||
userId: finalUserId,
|
||||
email: email.toLowerCase()
|
||||
email: email
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Error checking email verification:', error);
|
||||
|
||||
@@ -195,6 +195,110 @@ class IdentityService {
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Мигрирует все идентификаторы и сообщения от одного пользователя к другому
|
||||
* @param {number} fromUserId - ID исходного пользователя
|
||||
* @param {number} toUserId - ID целевого пользователя
|
||||
* @returns {Promise<object>} - Результат операции
|
||||
*/
|
||||
async migrateUserData(fromUserId, toUserId) {
|
||||
try {
|
||||
if (!fromUserId || !toUserId) {
|
||||
logger.warn(`[IdentityService] Missing parameters: fromUserId=${fromUserId}, toUserId=${toUserId}`);
|
||||
return { success: false, error: 'Missing required parameters' };
|
||||
}
|
||||
|
||||
// Начинаем транзакцию
|
||||
const client = await db.pool.connect();
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
|
||||
// Получаем все идентификаторы исходного пользователя
|
||||
const identitiesResult = await client.query(
|
||||
`SELECT provider, provider_id FROM user_identities WHERE user_id = $1`,
|
||||
[fromUserId]
|
||||
);
|
||||
|
||||
// Переносим каждый идентификатор
|
||||
for (const identity of identitiesResult.rows) {
|
||||
await client.query(
|
||||
`UPDATE user_identities
|
||||
SET user_id = $1
|
||||
WHERE user_id = $2 AND provider = $3 AND provider_id = $4`,
|
||||
[toUserId, fromUserId, identity.provider, identity.provider_id]
|
||||
);
|
||||
}
|
||||
|
||||
// Переносим все сообщения
|
||||
await client.query(
|
||||
`UPDATE messages
|
||||
SET user_id = $1
|
||||
WHERE user_id = $2`,
|
||||
[toUserId, fromUserId]
|
||||
);
|
||||
|
||||
// Переносим все диалоги
|
||||
await client.query(
|
||||
`UPDATE conversations
|
||||
SET user_id = $1
|
||||
WHERE user_id = $2`,
|
||||
[toUserId, fromUserId]
|
||||
);
|
||||
|
||||
// Удаляем исходного пользователя
|
||||
await client.query(
|
||||
`DELETE FROM users WHERE id = $1`,
|
||||
[fromUserId]
|
||||
);
|
||||
|
||||
await client.query('COMMIT');
|
||||
|
||||
logger.info(`[IdentityService] Successfully migrated data from user ${fromUserId} to user ${toUserId}`);
|
||||
return {
|
||||
success: true,
|
||||
migratedIdentities: identitiesResult.rows.length
|
||||
};
|
||||
} catch (error) {
|
||||
await client.query('ROLLBACK');
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`[IdentityService] Error migrating data from user ${fromUserId} to user ${toUserId}:`, error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Находит всех пользователей с похожими идентификаторами
|
||||
* @param {object} identities - Объект с идентификаторами
|
||||
* @returns {Promise<Array>} - Массив ID пользователей
|
||||
*/
|
||||
async findRelatedUsers(identities) {
|
||||
try {
|
||||
const userIds = new Set();
|
||||
|
||||
for (const [provider, providerId] of Object.entries(identities)) {
|
||||
if (!providerId) continue;
|
||||
|
||||
const result = await db.query(
|
||||
`SELECT DISTINCT user_id
|
||||
FROM user_identities
|
||||
WHERE provider = $1 AND provider_id = $2`,
|
||||
[provider, providerId]
|
||||
);
|
||||
|
||||
result.rows.forEach(row => userIds.add(row.user_id));
|
||||
}
|
||||
|
||||
return Array.from(userIds);
|
||||
} catch (error) {
|
||||
logger.error(`[IdentityService] Error finding related users:`, error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new IdentityService();
|
||||
Reference in New Issue
Block a user