Files
vue-pult/server/api/auth.js
sasha 3e90269b0b Initial commit: Vue.js тир управления система
- Клиентская часть Vue 3 + Vite
- Серверная часть Node.js + WebSocket
- Система авторизации и смен
- Управление игровыми портами
- Поддержка тем (светлая/темная)
- Адаптивный дизайн

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 12:24:22 +03:00

196 lines
9.3 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.
"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: "Внутренняя ошибка сервера"
}));
}
};