// Контроллер аутентификации const User = require('../models/User'); const jwt = require('jsonwebtoken'); const profanityFilter = require('../utils/profanityFilter'); // Вспомогательная функция для генерации JWT const generateToken = (id) => { return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: '30d', }); }; // @desc Регистрация нового пользователя // @route POST /api/auth/register // @access Public const registerUser = async (req, res, next) => { try { const { name, email, password, dateOfBirth, gender, city } = req.body; console.log('Начало регистрации пользователя с email:', email); if (!name || !email || !password || !dateOfBirth) { res.status(400); throw new Error('Пожалуйста, заполните все обязательные поля: имя, email, пароль и дату рождения.'); } // Проверяем наличие города if (!city) { res.status(400); throw new Error('Пожалуйста, выберите город.'); } // Проверка имени на наличие запрещенных слов if (await profanityFilter.isProfane(name)) { res.status(400); throw new Error('Имя содержит запрещённые слова. Пожалуйста, используйте другое имя.'); } // Проверка возраста (минимум 14 лет) const birthDate = new Date(dateOfBirth); const today = new Date(); let age = today.getFullYear() - birthDate.getFullYear(); const monthDiff = today.getMonth() - birthDate.getMonth(); if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { age--; } if (age < 14) { res.status(400); throw new Error('Для регистрации необходим возраст не менее 14 лет.'); } const normalizedEmail = email.toLowerCase(); console.log('Нормализованный email для поиска:', normalizedEmail); const userExists = await User.findOne({ email: normalizedEmail }); if (userExists) { console.log('Пользователь с таким email уже существует'); res.status(400); throw new Error('Пользователь с таким email уже существует.'); } console.log('Создание нового пользователя...'); const user = await User.create({ name, email: normalizedEmail, password, dateOfBirth, gender, location: { city: city, country: 'Россия' // Устанавливаем страну по умолчанию } }); console.log('Пользователь создан успешно:', user ? 'Да' : 'Нет', 'ID:', user ? user._id : 'N/A'); if (user) { res.status(201).json({ _id: user._id, name: user.name, email: user.email, token: generateToken(user._id), message: 'Пользователь успешно зарегистрирован!' }); } else { res.status(400); throw new Error('Неверные данные пользователя. Не удалось создать пользователя.'); } } catch (error) { console.error('Ошибка при регистрации:', error.message); if (!res.statusCode || res.statusCode < 400) { res.status(400); } res.json({ message: error.message, stack: process.env.NODE_ENV === 'production' ? null : error.stack }); } }; // @desc Аутентификация пользователя и получение токена (Вход) // @route POST /api/auth/login // @access Public const loginUser = async (req, res, next) => { try { const { email, password } = req.body; console.log('Попытка входа с email/логином:', email); if (!email || !password) { res.status(400); throw new Error('Пожалуйста, укажите email и пароль.'); } // Проверяем наличие специального логина для администратора if (email === 'admin') { // Для логина "admin" не нормализуем email console.log('Попытка входа с административным логином'); const user = await User.findOne({ email: 'admin' }).select('+password'); if (!user) { console.log('Административный аккаунт не найден в базе данных'); res.status(401); throw new Error('Неверный логин или пароль.'); } if (!user.password) { console.error('Ошибка: Пароль не загружен из базы данных для административного аккаунта'); res.status(500); throw new Error('Внутренняя ошибка сервера при проверке учетных данных.'); } console.log('Проверка пароля для административного аккаунта...'); const isMatch = await user.matchPassword(password); console.log('Результат проверки пароля:', isMatch ? 'Успешно' : 'Неверный пароль'); if (isMatch) { res.status(200).json({ _id: user._id, name: user.name, email: user.email, isAdmin: user.isAdmin || false, token: generateToken(user._id), message: 'Вход выполнен успешно!' }); } else { res.status(401); throw new Error('Неверный логин или пароль.'); } return; } // Для обычных пользователей продолжаем проверку email const normalizedEmail = email.toLowerCase(); console.log('Нормализованный email для поиска:', normalizedEmail); const user = await User.findOne({ email: normalizedEmail }).select('+password'); console.log('Найден пользователь:', user ? 'Да' : 'Нет'); console.log('Пользователь содержит пароль:', user && user.password ? 'Да' : 'Нет'); if (!user) { console.log('Пользователь не найден в базе данных'); res.status(401); throw new Error('Неверный email или пароль.'); } if (!user.password) { console.error('Ошибка: Пароль не загружен из базы данных'); res.status(500); throw new Error('Внутренняя ошибка сервера при проверке учетных данных.'); } console.log('Проверка пароля...'); const isMatch = await user.matchPassword(password); console.log('Результат проверки пароля:', isMatch ? 'Успешно' : 'Неверный пароль'); // Проверка если аккаунт неактивен (заблокирован) if (isMatch && !user.isActive && !user.isAdmin) { res.status(403); throw new Error('Ваш аккаунт заблокирован. Пожалуйста, обратитесь в поддержку.'); } if (isMatch) { res.status(200).json({ _id: user._id, name: user.name, email: user.email, isAdmin: user.isAdmin || false, // Добавляем информацию о правах администратора token: generateToken(user._id), message: 'Вход выполнен успешно!' }); } else { res.status(401); throw new Error('Неверный email или пароль.'); } } catch (error) { console.error('Ошибка при входе:', error.message); if (!res.statusCode || res.statusCode < 400) { res.status(401); } res.json({ message: error.message, stack: process.env.NODE_ENV === 'production' ? null : error.stack }); } }; // @desc Получение данных профиля текущего пользователя // @route GET /api/auth/me // @access Private const getMe = async (req, res, next) => { try { if (!req.user) { res.status(404); throw new Error('Пользователь не найден.'); } res.status(200).json({ _id: req.user._id, name: req.user.name, email: req.user.email, dateOfBirth: req.user.dateOfBirth, gender: req.user.gender, bio: req.user.bio, photos: req.user.photos, location: req.user.location, preferences: req.user.preferences, isAdmin: req.user.isAdmin || false, // Добавляем информацию об административных правах createdAt: req.user.createdAt, updatedAt: req.user.updatedAt, }); } catch (error) { console.error('Ошибка при получении данных пользователя:', error.message); if (!res.statusCode || res.statusCode < 400) { res.status(500); } res.json({ message: error.message, stack: process.env.NODE_ENV === 'production' ? null : error.stack }); } }; // Экспортируем все функции module.exports = { registerUser, loginUser, getMe };