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

This commit is contained in:
2025-04-16 16:39:58 +03:00
parent 0f5a931f30
commit 483a1ef854
11 changed files with 777 additions and 76 deletions

View File

@@ -82,18 +82,49 @@ router.post('/verify', async (req, res) => {
return res.status(401).json({ success: false, error: 'Invalid signature' });
}
// Нормализуем адрес для использования в запросах
const normalizedAddress = ethers.getAddress(address).toLowerCase();
// Проверяем nonce
const nonceResult = await db.query('SELECT nonce FROM nonces WHERE identity_value = $1', [address.toLowerCase()]);
const nonceResult = await db.query('SELECT nonce FROM nonces WHERE identity_value = $1', [normalizedAddress]);
if (nonceResult.rows.length === 0 || nonceResult.rows[0].nonce !== message.match(/Nonce: ([^\n]+)/)[1]) {
return res.status(401).json({ success: false, error: 'Invalid nonce' });
}
// Находим или создаем пользователя
const { userId, isAdmin } = await authService.findOrCreateUser(address.toLowerCase());
let userId;
let isAdmin = false;
// Сохраняем идентификаторы
await identityService.saveIdentity(userId, 'wallet', address.toLowerCase(), true);
// Проверяем, авторизован ли пользователь уже
if (req.session.authenticated && req.session.userId) {
// Если пользователь уже авторизован, привязываем кошелек к существующему пользователю
userId = req.session.userId;
logger.info(`[verify] Using existing authenticated user ${userId} for wallet ${normalizedAddress}`);
// Связываем кошелек с пользователем через identity-service для предотвращения дубликатов
const linkResult = await authService.linkIdentity(
userId,
'wallet',
address
);
if (!linkResult.success && linkResult.error) {
return res.status(400).json({
success: false,
error: linkResult.error
});
}
// Если linkResult.message содержит 'already exists', значит кошелек уже привязан
logger.info(`[verify] Wallet ${normalizedAddress} linked to user ${userId}: ${linkResult.message || 'success'}`);
} else {
// Находим или создаем пользователя, если не авторизован
const result = await authService.findOrCreateUser(address);
userId = result.userId;
isAdmin = result.isAdmin;
logger.info(`[verify] Found or created user ${userId} for wallet ${normalizedAddress}`);
}
// Сохраняем идентификаторы гостевой сессии
if (guestId) {
await identityService.saveIdentity(userId, 'guest', guestId, true);
}
@@ -103,10 +134,11 @@ router.post('/verify', async (req, res) => {
}
// Проверяем наличие админских токенов
const adminStatus = await authService.checkAdminTokens(address.toLowerCase());
const adminStatus = await authService.checkAdminTokens(normalizedAddress);
if (adminStatus) {
await db.query('UPDATE users SET role = $1 WHERE id = $2', ['admin', userId]);
isAdmin = true;
}
// Обновляем сессию
@@ -114,7 +146,7 @@ router.post('/verify', async (req, res) => {
req.session.authenticated = true;
req.session.authType = 'wallet';
req.session.isAdmin = adminStatus || isAdmin;
req.session.address = address.toLowerCase();
req.session.address = normalizedAddress; // Всегда сохраняем нормализованный адрес
// Удаляем временный ID
delete req.session.tempUserId;
@@ -129,7 +161,7 @@ router.post('/verify', async (req, res) => {
return res.json({
success: true,
userId,
address,
address: normalizedAddress, // Возвращаем нормализованный адрес
isAdmin: adminStatus || isAdmin,
authenticated: true
});

View File

@@ -3,6 +3,7 @@ const router = express.Router();
const { requireAuth } = require('../middleware/auth');
const authService = require('../services/auth-service');
const logger = require('../utils/logger');
const db = require('../db');
// Получение всех идентификаторов пользователя
router.get('/', requireAuth, async (req, res) => {
@@ -22,7 +23,29 @@ router.post('/link', requireAuth, async (req, res) => {
const { type, value } = req.body;
const userId = req.session.userId;
await authService.linkIdentity(userId, type, value);
// Если тип - wallet, сначала проверим, не привязан ли он уже к другому пользователю
if (type === 'wallet') {
const normalizedWallet = value.toLowerCase();
// Проверяем, существует ли уже такой кошелек
const existingCheck = await db.query(
`SELECT user_id FROM user_identities
WHERE provider = 'wallet' AND provider_id = $1`,
[normalizedWallet]
);
if (existingCheck.rows.length > 0) {
const existingUserId = existingCheck.rows[0].user_id;
if (existingUserId !== userId) {
return res.status(400).json({
success: false,
error: `This wallet (${value}) is already linked to another account`
});
}
}
}
const result = await authService.linkIdentity(userId, type, value);
// Обновляем сессию
if (type === 'wallet') {
@@ -41,6 +64,15 @@ router.post('/link', requireAuth, async (req, res) => {
});
} catch (error) {
logger.error('Error linking identity:', error);
// Делаем более понятные сообщения об ошибках
if (error.message && error.message.includes('already belongs to another user')) {
return res.status(400).json({
success: false,
error: `This identity is already linked to another account`
});
}
res.status(500).json({ error: error.message || 'Internal server error' });
}
});

View File

@@ -43,4 +43,76 @@ router.post('/update-language', requireAuth, async (req, res) => {
}
});
// Маршрут для обновления имени и фамилии пользователя
router.post('/update-profile', requireAuth, async (req, res) => {
try {
const { firstName, lastName } = req.body;
const userId = req.session.userId;
// Проверка валидности данных
if (firstName && firstName.length > 255) {
return res.status(400).json({ error: 'Имя слишком длинное (максимум 255 символов)' });
}
if (lastName && lastName.length > 255) {
return res.status(400).json({ error: 'Фамилия слишком длинная (максимум 255 символов)' });
}
// Обновление имени и фамилии в базе данных
await db.query(
'UPDATE users SET first_name = $1, last_name = $2 WHERE id = $3',
[firstName || null, lastName || null, userId]
);
res.json({ success: true });
} catch (error) {
logger.error('Error updating user profile:', error);
res.status(500).json({ error: 'Внутренняя ошибка сервера' });
}
});
// Маршрут для получения профиля пользователя
router.get('/profile/current', requireAuth, async (req, res) => {
try {
const userId = req.session.userId;
// Получение данных пользователя
const userResult = await db.query(
'SELECT id, username, first_name, last_name, role, status, created_at, preferred_language FROM users WHERE id = $1',
[userId]
);
if (userResult.rows.length === 0) {
return res.status(404).json({ error: 'Пользователь не найден' });
}
// Получение идентификаторов пользователя
const identitiesResult = await db.query(
'SELECT provider, provider_id FROM user_identities WHERE user_id = $1',
[userId]
);
const user = userResult.rows[0];
const identities = identitiesResult.rows.reduce((acc, identity) => {
acc[identity.provider] = identity.provider_id;
return acc;
}, {});
res.json({
id: user.id,
username: user.username,
firstName: user.first_name,
lastName: user.last_name,
role: user.role,
status: user.status,
createdAt: user.created_at,
preferredLanguage: user.preferred_language,
identities
});
} catch (error) {
logger.error('Error getting user profile:', error);
res.status(500).json({ error: 'Внутренняя ошибка сервера' });
}
});
module.exports = router;