Reflex/backend/controllers/authController.js
2025-05-26 12:05:51 +07:00

303 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Контроллер аутентификации
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('Административный аккаунт не найден в базе данных');
console.log('Создание административного аккаунта...');
try {
// Если админ не найден, можно попытаться создать его на месте
const adminUser = new User({
name: 'Администратор',
email: 'admin',
password: 'admin124', // Пароль будет хеширован pre-save hook
dateOfBirth: new Date('1990-01-01'),
gender: 'other',
isActive: true,
isAdmin: true,
location: {
city: 'Admin',
country: 'System'
}
});
await adminUser.save();
console.log('Административный аккаунт создан успешно');
res.status(200).json({
_id: adminUser._id,
name: adminUser.name,
email: adminUser.email,
isAdmin: true,
token: generateToken(adminUser._id),
message: 'Административный аккаунт создан. Вход выполнен успешно!'
});
return;
} catch (adminError) {
console.error('Ошибка при создании админ-аккаунта:', adminError);
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) {
// Обновляем дату последнего входа
user.lastSeen = new Date();
await user.save();
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;
}
// Перед проверкой обычных пользователей, проверим наличие админа с почтой
if (email === 'admin@example.com') {
console.log('Попытка входа с email администратора: admin@example.com');
// Проверяем наличие админа с логином admin
const adminUser = await User.findOne({ email: 'admin' }).select('+password');
if (adminUser && await adminUser.matchPassword(password)) {
console.log('Успешный вход через email администратора, перенаправление на логин admin');
// Обновляем дату последнего входа
adminUser.lastSeen = new Date();
await adminUser.save();
res.status(200).json({
_id: adminUser._id,
name: adminUser.name,
email: adminUser.email,
isAdmin: true,
token: generateToken(adminUser._id),
message: 'Вход выполнен успешно!'
});
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
};