const express = require('express'); const router = express.Router(); const crypto = require('crypto'); const User = require('../models/User'); const config = require('../config'); const { validateTelegramId } = require('../middleware/validator'); const { logSecurityEvent } = require('../middleware/logger'); const { strictAuthLimiter } = require('../middleware/security'); // Проверка подписи Telegram OAuth (Login Widget) function validateTelegramOAuth(authData, botToken) { if (!authData || !authData.hash) { return false; } const { hash, ...data } = authData; const dataCheckString = Object.keys(data) .sort() .map(key => `${key}=${data[key]}`) .join('\n'); const secretKey = crypto .createHmac('sha256', 'WebAppData') .update(botToken) .digest(); const calculatedHash = crypto .createHmac('sha256', secretKey) .update(dataCheckString) .digest('hex'); return calculatedHash === hash; } // Авторизация через Telegram OAuth (Login Widget) router.post('/oauth', strictAuthLimiter, async (req, res) => { try { const { user: telegramUser, auth_date, hash } = req.body; if (!telegramUser || !auth_date || !hash) { logSecurityEvent('INVALID_OAUTH_DATA', req); return res.status(400).json({ error: 'Неверные данные авторизации' }); } // Валидация Telegram ID if (!validateTelegramId(telegramUser.id)) { logSecurityEvent('INVALID_TELEGRAM_ID', req, { telegramId: telegramUser.id }); return res.status(400).json({ error: 'Неверный ID пользователя' }); } // Проверка подписи Telegram (строгая проверка в production) if (config.telegramBotToken) { const authData = { id: telegramUser.id, first_name: telegramUser.first_name, last_name: telegramUser.last_name, username: telegramUser.username, photo_url: telegramUser.photo_url, auth_date: auth_date, hash: hash }; const isValid = validateTelegramOAuth(authData, config.telegramBotToken); if (!isValid) { logSecurityEvent('INVALID_OAUTH_SIGNATURE', req, { telegramId: telegramUser.id }); // В production строгая проверка if (config.isProduction()) { return res.status(401).json({ error: 'Неверная подпись Telegram OAuth' }); } } } // Найти или создать пользователя let user = await User.findOne({ telegramId: telegramUser.id.toString() }); if (!user) { user = new User({ telegramId: telegramUser.id.toString(), username: telegramUser.username || telegramUser.first_name, firstName: telegramUser.first_name, lastName: telegramUser.last_name, photoUrl: telegramUser.photo_url }); await user.save(); console.log(`✅ Создан новый пользователь через OAuth: ${user.username}`); } else { // Обновить данные пользователя user.username = telegramUser.username || telegramUser.first_name; user.firstName = telegramUser.first_name; user.lastName = telegramUser.last_name; user.photoUrl = telegramUser.photo_url; await user.save(); } // Получить полные данные пользователя const populatedUser = await User.findById(user._id).populate([ { path: 'followers', select: 'username firstName lastName photoUrl' }, { path: 'following', select: 'username firstName lastName photoUrl' } ]); res.json({ success: true, user: { id: populatedUser._id, telegramId: populatedUser.telegramId, username: populatedUser.username, firstName: populatedUser.firstName, lastName: populatedUser.lastName, photoUrl: populatedUser.photoUrl, bio: populatedUser.bio, role: populatedUser.role, followersCount: populatedUser.followers.length, followingCount: populatedUser.following.length, settings: populatedUser.settings, banned: populatedUser.banned } }); } catch (error) { console.error('Ошибка OAuth:', error); res.status(500).json({ error: 'Ошибка сервера' }); } }); // Проверка авторизации и получение данных пользователя const { authenticate } = require('../middleware/auth'); router.post('/verify', authenticate, async (req, res) => { try { const user = await req.user.populate([ { path: 'followers', select: 'username firstName lastName photoUrl' }, { path: 'following', select: 'username firstName lastName photoUrl' } ]); res.json({ success: true, user: { id: user._id, telegramId: user.telegramId, username: user.username, firstName: user.firstName, lastName: user.lastName, photoUrl: user.photoUrl, bio: user.bio, role: user.role, followersCount: user.followers.length, followingCount: user.following.length, settings: user.settings, banned: user.banned } }); } catch (error) { console.error('Ошибка verify:', error); res.status(500).json({ error: 'Ошибка сервера' }); } }); module.exports = router;