"use strict"; const fs = require('node:fs/promises'); const path = require('path'); const crypto = require('crypto'); // Функция генерации случайного хэша для сессии (как в старом коде) const genHash = (length) => { const chars = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890'; let result = ''; for (let i = 0; i < length; i++) { result += chars[Math.floor(Math.random() * chars.length)]; } return result; }; // Функция генерации хэша пароля как в оригинальной системе const generatePasswordHash = (password) => { // Шаг 1: MD5 от пароля const firstHash = crypto.createHash('md5').update(password).digest('hex'); // Шаг 2: MD5 от (первый_хэш + "pult2024") const finalHash = crypto.createHash('md5').update(firstHash + "pult2024").digest('hex'); return finalHash; }; exports.go = async (req, res, postData, urlParsed) => { try { console.log('[api/auth] Запрос авторизации пользователя:', { phone: postData.phone, hasPassword: !!postData.password, hasHash: !!postData.hash }); // Нормализуем номер телефона (убираем все кроме цифр) const normalizedPhone = postData.phone ? postData.phone.replace(/\D/g, '') : null; if (!normalizedPhone) { return res.end(JSON.stringify({ success: false, error: "Не указан номер телефона" })); } // Читаем данные пользователей и сессионных хэшей let avt = {}; let hash = {}; try { const avtData = await fs.readFile(path.join(__dirname, '../data/avt.ini'), 'utf8'); avt = JSON.parse(avtData); console.log('[api/auth] Загружены пользователи:', Object.keys(avt).length); } catch (error) { console.error('[api/auth] Ошибка чтения avt.ini:', error); return res.end(JSON.stringify({ success: false, error: "Ошибка загрузки данных пользователей" })); } try { const hashData = await fs.readFile(path.join(__dirname, '../data/hash.ini'), 'utf8'); hash = JSON.parse(hashData); } catch (error) { console.warn('[api/auth] Файл hash.ini не найден или пуст, создаем новый'); hash = {}; } let user = false; // АВТОРИЗАЦИЯ ПО ПАРОЛЮ (как в старом коде) if (postData.password && normalizedPhone in avt) { console.log('[api/auth] Попытка авторизации по паролю для:', normalizedPhone); // Генерируем хэш пароля по оригинальной схеме: MD5(MD5(пароль) + "pult2024") const inputPasswordHash = generatePasswordHash(postData.password); console.log('[api/auth] Схема: MD5(MD5(пароль) + "pult2024")'); console.log('[api/auth] Хэш введенного пароля:', inputPasswordHash); console.log('[api/auth] Хэш из базы:', avt[normalizedPhone].pass); // Сравниваем хэши по правильной схеме if (avt[normalizedPhone].pass === inputPasswordHash) { console.log('[api/auth] ✅ Пароль верен!'); // Копируем данные пользователя без пароля user = JSON.parse(JSON.stringify(avt[normalizedPhone])); delete user.pass; if (user.groupz && user.groupz.access) delete user.groupz.access; // Генерируем сессионный хэш hash[normalizedPhone] = genHash(15); user.hash = hash[normalizedPhone]; // Сохраняем сессионный хэш await fs.writeFile(path.join(__dirname, '../data/hash.ini'), JSON.stringify(hash)); console.log('[api/auth] Создан сессионный хэш:', user.hash); } else { console.log('[api/auth] ❌ Неверный пароль'); } } // АВТОРИЗАЦИЯ ПО СЕССИОННОМУ ХЭШУ (как в старом коде) if (postData.hash && normalizedPhone in hash && normalizedPhone in avt && hash[normalizedPhone] === postData.hash) { console.log('[api/auth] ✅ Авторизация по сессионному хэшу успешна'); user = JSON.parse(JSON.stringify(avt[normalizedPhone])); user.hash = hash[normalizedPhone]; delete user.pass; if (user.groupz && user.groupz.access) delete user.groupz.access; } // ФОРМИРУЕМ ОТВЕТ if (user !== false) { console.log('[api/auth] ✅ Авторизация успешна для:', user.fio || user._id); // Определяем роль пользователя let userRole = 'operator'; console.log('[api/auth] Данные пользователя для определения роли:', { taccess: user.taccess, access: user.access, groupz: user.groupz }); if (user.taccess) { // Простая обработка строковой роли if (user.taccess === 'technics') { userRole = 'technic'; } else if (user.taccess === 'operators') { userRole = 'operator'; } else { userRole = user.taccess; } console.log('[api/auth] Роль установлена из taccess:', user.taccess, '-> преобразована в:', userRole); } else if (user.access && user.access.fullaccess) { userRole = 'admin'; console.log('[api/auth] Роль установлена как admin из access.fullaccess'); } else if (user.groupz && user.groupz.name) { const groupName = user.groupz.name.toLowerCase(); console.log('[api/auth] Анализ группы:', groupName); if (groupName.includes('программист') || groupName.includes('админ')) { userRole = 'admin'; console.log('[api/auth] Роль установлена как admin из группы'); } else if (groupName.includes('оператор')) { userRole = 'operator'; console.log('[api/auth] Роль установлена как operator из группы'); } else if (groupName.includes('техник')) { userRole = 'technic'; console.log('[api/auth] Роль установлена как technic из группы'); } } console.log('[api/auth] Финальная роль пользователя:', userRole); // Возвращаем данные в формате React const response = { success: true, user: { id: user._id || normalizedPhone, name: user.fio || user.name || 'Пользователь', phone: normalizedPhone, role: userRole, // Возвращаем простую строковую роль isAuthenticated: true, hash: user.hash, // Сессионный хэш для последующих запросов // Дополнительные данные group: user.groupz ? user.groupz.name : null, color: user.color || null, balance: user.bal || null, serverConnected: global.conn_to_server || false } }; // Логируем отправляемого пользователя в отдельный файл const fsSync = require('fs'); try { fsSync.appendFileSync('./avt-server.log', JSON.stringify(response, null, 2) + '\n'); } catch (e) { console.error('[api/auth] Ошибка записи avt-server.log:', e); } res.end(JSON.stringify(response)); } else { console.log('[api/auth] ❌ Авторизация не удалась'); res.end(JSON.stringify({ success: false, error: "Неверный логин или пароль" })); } } catch (error) { console.error('[api/auth] Критическая ошибка:', error); res.end(JSON.stringify({ success: false, error: "Внутренняя ошибка сервера" })); } };