This commit is contained in:
root
2025-11-25 09:56:15 +03:00
commit 68c8f0e80d
23717 changed files with 3200521 additions and 0 deletions

41
mc_test/dist/main/electron.js vendored Executable file
View File

@ -0,0 +1,41 @@
"use strict";
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
function createWindow() {
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: true,
preload: path.join(__dirname, '../preload.js'),
},
});
// In development, load from Vite dev server
if (process.env.NODE_ENV === 'development') {
mainWindow.loadURL('http://localhost:5173');
mainWindow.webContents.openDevTools();
}
else {
// In production, load the built index.html
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'));
}
}
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
// Handle machine connection (stub)
ipcMain.handle('connect-to-machine', async (_event, machine) => {
console.log('Connecting to machine:', machine);
return { success: true, message: 'Connection successful (stub)' };
});

182
mc_test/dist/main/main/electron.js vendored Executable file
View File

@ -0,0 +1,182 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const logger_1 = require("./logger");
// Временное хранилище для демо
const machinesStore = {
'test-vm-01': {
id: 'test-vm-01',
name: 'Test VM 1',
status: 'running',
os: 'Windows 10',
ip: '192.168.1.100',
hypervisor: 'VMware',
specs: {
cpu: '4 cores',
ram: '8GB',
disk: '256GB'
},
testLinks: [
{ name: 'RDP', url: 'rdp://192.168.1.100' },
{ name: 'Web Console', url: 'https://192.168.1.100:8080' }
],
logs: [
{ timestamp: new Date().toISOString(), message: 'System started', level: 'info' }
]
}
};
function createWindow() {
logger_1.log.info('startup', 'Creating main window...');
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: true,
preload: path.join(__dirname, '..', 'preload.js'),
},
});
// In development, load from Vite dev server
const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL;
logger_1.log.debug('startup', 'VITE_DEV_SERVER_URL:', { url: VITE_DEV_SERVER_URL });
if (VITE_DEV_SERVER_URL) {
logger_1.log.info('startup', 'Loading from dev server', { url: VITE_DEV_SERVER_URL });
mainWindow.loadURL(VITE_DEV_SERVER_URL);
mainWindow.webContents.openDevTools();
}
else {
const indexPath = path.join(__dirname, '..', 'renderer', 'index.html');
logger_1.log.info('startup', 'Loading from file', { path: indexPath });
mainWindow.loadFile(indexPath);
}
// Handle window close
mainWindow.on('closed', () => {
logger_1.log.info('window', 'Main window closed, quitting application');
app.quit();
});
}
// This method will be called when Electron has finished initialization
app.whenReady().then(() => {
logger_1.log.info('startup', 'Application ready, initializing...');
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
logger_1.log.info('window', 'No windows available, creating new window');
createWindow();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
logger_1.log.info('window', 'All windows closed, quitting application');
app.quit();
}
});
// Обработка событий логирования от renderer процесса
ipcMain.on('log-event', (_event, { level, tag, message, context }) => {
logger_1.log[level](tag, message, context);
});
// Обработчики IPC событий
// Подключение к машине
ipcMain.handle('connect-to-machine', async (_event, machine) => {
logger_1.log.info('connect-machine', 'Connection request received', {
machineId: machine.id,
machineName: machine.name
});
try {
// TODO: Реальная логика подключения будет добавлена позже
return {
success: true,
message: 'Connection successful',
details: { machineId: machine.id }
};
}
catch (error) {
logger_1.log.error('connect-machine', 'Connection failed', {
machineId: machine.id,
error: error instanceof Error ? error.message : String(error)
});
throw error;
}
});
// Управление состоянием машины
ipcMain.handle('control-machine', async (_event, { machineId, action }) => {
logger_1.log.info('control-machine', `Machine ${action} requested`, { machineId, action });
try {
const machine = machinesStore[machineId];
if (!machine) {
throw new Error(`Machine ${machineId} not found`);
}
// Симуляция изменения состояния
switch (action) {
case 'start':
machine.status = 'running';
machine.logs.unshift({
timestamp: new Date().toISOString(),
message: 'Machine started',
level: 'info'
});
break;
case 'stop':
machine.status = 'stopped';
machine.logs.unshift({
timestamp: new Date().toISOString(),
message: 'Machine stopped',
level: 'info'
});
break;
case 'restart':
machine.status = 'stopped';
machine.logs.unshift({
timestamp: new Date().toISOString(),
message: 'Machine restarting',
level: 'info'
});
setTimeout(() => {
machine.status = 'running';
machine.logs.unshift({
timestamp: new Date().toISOString(),
message: 'Machine restarted successfully',
level: 'info'
});
logger_1.log.info('control-machine', 'Machine restarted', { machineId });
}, 2000);
break;
}
return {
success: true,
message: `Machine ${action} successful`,
details: { machineId, newStatus: machine.status }
};
}
catch (error) {
logger_1.log.error('control-machine', `Machine ${action} failed`, {
machineId,
error: error instanceof Error ? error.message : String(error)
});
throw error;
}
});
// Получение статуса машины
ipcMain.handle('get-machine-status', async (_event, machineId) => {
logger_1.log.debug('get-machine-status', 'Status requested', { machineId });
const machine = machinesStore[machineId];
if (!machine) {
throw new Error(`Machine ${machineId} not found`);
}
return {
success: true,
message: 'Status retrieved',
status: machine.status
};
});
// Получение списка машин
ipcMain.handle('get-machine-list', async () => {
logger_1.log.debug('get-machine-list', 'Machine list requested');
return {
success: true,
message: 'Machine list retrieved',
machines: Object.values(machinesStore)
};
});

84
mc_test/dist/main/main/logger.js vendored Executable file
View File

@ -0,0 +1,84 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.log = void 0;
const winston_1 = __importDefault(require("winston"));
const winston_daily_rotate_file_1 = __importDefault(require("winston-daily-rotate-file"));
const path_1 = __importDefault(require("path"));
// Создание кастомного формата
const customFormat = winston_1.default.format.printf(({ level, message, timestamp, tag, context }) => {
const contextStr = context ? ` | context: ${JSON.stringify(context)}` : '';
return `[${timestamp}] [${tag || 'main'}] [${level.toUpperCase()}]: ${message}${contextStr}`;
});
// Конфигурация логгера
const logger = winston_1.default.createLogger({
level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',
format: winston_1.default.format.combine(winston_1.default.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss'
}), winston_1.default.format.errors({ stack: true }), customFormat),
transports: [
// Логирование в файл с ротацией
new winston_daily_rotate_file_1.default({
dirname: path_1.default.join(process.cwd(), 'logs'),
filename: 'app-%DATE%.log',
datePattern: 'YYYY-MM-DD',
zippedArchive: true,
maxSize: '20m',
maxFiles: '14d',
level: 'info'
}),
// Логирование в консоль с цветами
new winston_1.default.transports.Console({
format: winston_1.default.format.combine(winston_1.default.format.colorize(), customFormat)
})
]
});
// Обработка необработанных исключений и промисов
logger.exceptions.handle(new winston_1.default.transports.File({ filename: path_1.default.join(process.cwd(), 'logs', 'exceptions.log') }));
logger.rejections.handle(new winston_1.default.transports.File({ filename: path_1.default.join(process.cwd(), 'logs', 'rejections.log') }));
// Создание методов для разных уровней логирования
const createLogMethod = (level) => {
return (tag, message, context) => {
logger.log({
level,
message,
tag,
context
});
};
};
// Экспорт интерфейса логгера
exports.log = {
error: createLogMethod('error'),
warn: createLogMethod('warn'),
info: createLogMethod('info'),
debug: createLogMethod('debug'),
// Метод для логирования необработанных ошибок
fatal: (error, context) => {
logger.error({
level: 'error',
message: error.message,
tag: 'uncaught',
context: {
...context,
stack: error.stack
}
});
}
};
// Настройка обработчиков необработанных ошибок
process.on('uncaughtException', (error) => {
exports.log.fatal(error);
process.exit(1);
});
process.on('unhandledRejection', (reason) => {
if (reason instanceof Error) {
exports.log.fatal(reason);
}
else {
exports.log.error('unhandledRejection', 'Unhandled promise rejection', { reason });
}
});
exports.default = exports.log;

17
mc_test/dist/main/preload.js vendored Executable file
View File

@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const { contextBridge, ipcRenderer } = require('electron');
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld('electronAPI', {
// Подключение к машине
connectToMachine: (machine) => ipcRenderer.invoke('connect-to-machine', machine),
// Управление состоянием машины
controlMachine: (machineId, action) => ipcRenderer.invoke('control-machine', { machineId, action }),
// Получение статуса машины
getMachineStatus: (machineId) => ipcRenderer.invoke('get-machine-status', machineId),
// Получение списка машин
getMachineList: () => ipcRenderer.invoke('get-machine-list'),
// Логирование
logEvent: (level, tag, message, context) => ipcRenderer.send('log-event', { level, tag, message, context }),
});

2
mc_test/dist/main/renderer/types.js vendored Executable file
View File

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@ -0,0 +1 @@
import{r as n,l as c,j as e}from"./main-D-T5fPSb.js";function w({machine:t,connectionUrl:m,enableSftp:y,onError:l,onDisconnect:h}){const[p,d]=n.useState(!0),[k,x]=n.useState(null),[r,o]=n.useState(!1),s=n.useRef(null),f=n.useRef(null);return n.useEffect(()=>((async()=>{try{if(d(!0),x(null),c.info("guacamole-viewer","Initializing Guacamole session",{machineId:t.id,machineName:t.name,connectionUrl:m}),s.current)if(!s.current.src||s.current.src==="about:blank")c.debug("guacamole-viewer","Loading connection URL",{url:m}),s.current.src=m;else{c.debug("guacamole-viewer","iframe already loaded, keeping existing session"),d(!1);return}const a=()=>{d(!1),c.info("guacamole-viewer","Guacamole session loaded",{machineId:t.id}),setTimeout(()=>{s.current&&(s.current.focus(),o(!0))},500)},i=()=>{const u=new Error("Failed to load Guacamole session");x(u),d(!1),l==null||l(u)};if(s.current)return s.current.addEventListener("load",a),s.current.addEventListener("error",i),()=>{var u,b;(u=s.current)==null||u.removeEventListener("load",a),(b=s.current)==null||b.removeEventListener("error",i)}}catch(a){const i=a instanceof Error?a:new Error("Unknown error occurred");c.error("guacamole-viewer","Connection failed",{machineId:t.id,error:i.message}),x(i),l==null||l(i),d(!1)}})(),()=>{c.info("guacamole-viewer","Cleaning up connection",{machineId:t.id}),o(!1)}),[t.id]),n.useEffect(()=>{const g=a=>{f.current&&!f.current.contains(a.target)&&r&&(o(!1),s.current&&s.current.blur())};return document.addEventListener("mousedown",g),()=>{document.removeEventListener("mousedown",g)}},[r]),k?e.jsx("div",{className:"flex-1 flex items-center justify-center bg-red-50 text-red-600 p-4 rounded-kaspersky",children:e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"font-medium mb-2",children:"Connection Error"}),e.jsx("p",{className:"text-sm mb-4",children:k.message}),e.jsxs("div",{className:"flex gap-2 justify-center",children:[e.jsx("button",{onClick:()=>window.location.reload(),className:"px-4 py-2 bg-red-600 text-white rounded-kaspersky hover:bg-red-700 transition-colors",children:"Retry"}),e.jsx("button",{onClick:h,className:"px-4 py-2 bg-gray-600 text-white rounded-kaspersky hover:bg-gray-700 transition-colors",children:"Disconnect"})]})]})}):e.jsx("div",{className:"w-full h-full flex flex-col bg-kaspersky-bg",children:e.jsxs("div",{ref:f,className:`flex-1 relative bg-kaspersky-bg overflow-hidden ${r?"ring-2 ring-kaspersky-primary ring-opacity-50":""}`,children:[p&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-kaspersky-bg bg-opacity-75 z-10",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-8 h-8 border-4 border-kaspersky-base border-t-transparent rounded-full animate-spin mx-auto"}),e.jsxs("p",{className:"mt-2 text-kaspersky-text",children:["Connecting to ",t.name,"..."]})]})}),!p&&!r&&e.jsx("div",{className:"absolute inset-0 z-10 cursor-pointer",onClick:()=>{s.current&&(s.current.focus(),o(!0))},title:"Click to activate console"}),!p&&e.jsx("div",{className:"absolute top-4 left-1/2 transform -translate-x-1/2 z-20 pointer-events-none select-none",children:e.jsxs("div",{className:"flex flex-col items-center gap-2",children:[e.jsxs("div",{className:`flex items-center gap-3 px-4 py-2 rounded-lg text-sm font-semibold transition-all duration-300 ${r?"bg-kaspersky-primary text-white shadow-kaspersky-lg":"bg-kaspersky-secondary bg-opacity-90 text-kaspersky-text-white"}`,children:[e.jsx("div",{className:`w-3 h-3 rounded-full transition-all duration-300 ${r?"bg-kaspersky-danger animate-pulse":"bg-kaspersky-text-lighter"}`}),e.jsx("span",{children:r?"Console Active":"Console Inactive"})]}),e.jsx("div",{className:"bg-kaspersky-secondary bg-opacity-75 backdrop-blur-sm text-kaspersky-text-white px-3 py-1.5 rounded-md text-xs font-medium",children:y?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"opacity-75",children:"Settings & SFTP:"}),e.jsx("kbd",{className:"px-1.5 py-0.5 bg-kaspersky-base bg-opacity-50 rounded text-[10px] font-mono",children:"Ctrl+Shift+Alt"})]}):e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"opacity-75",children:"Settings:"}),e.jsx("kbd",{className:"px-1.5 py-0.5 bg-kaspersky-base bg-opacity-50 rounded text-[10px] font-mono",children:"Ctrl+Shift+Alt"})]})})]})}),e.jsx("iframe",{ref:s,className:"w-full h-full border-0",title:`Remote Desktop - ${t.name}`,allow:"clipboard-read; clipboard-write; keyboard-map *; pointer-lock",sandbox:"allow-same-origin allow-scripts allow-forms allow-popups allow-pointer-lock allow-modals allow-downloads",onFocus:()=>o(!0),onBlur:()=>o(!1)})]})})}export{w as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

309
mc_test/dist/renderer/assets/main-D-T5fPSb.js vendored Executable file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

44
mc_test/dist/renderer/index.html vendored Executable file
View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Machine Control Center</title>
<!-- Content Security Policy - DISABLED for debugging -->
<!--
<meta http-equiv="Content-Security-Policy" content="
default-src 'self' 'unsafe-inline' 'unsafe-eval';
script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost:* ws://localhost:*;
style-src 'self' 'unsafe-inline' http://localhost:*;
img-src 'self' data: blob: http://localhost:*;
font-src 'self' data: http://localhost:*;
connect-src 'self' http://localhost:* https://localhost:* ws://localhost:* wss://localhost:*;
frame-src 'self' http://localhost:* https://localhost:*;
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
">
-->
<script type="module" crossorigin src="./assets/main-D-T5fPSb.js"></script>
<link rel="stylesheet" crossorigin href="./assets/main-CnaqftHU.css">
</head>
<body>
<div id="root">Loading...</div>
<script>
console.log('🔍 HTML загружен, начинаем отладку...');
console.log('📍 Root element:', document.getElementById('root'));
</script>
<script>
// Добавляем обработчик ошибок
window.addEventListener('error', (e) => {
console.error('❌ JavaScript Error:', e.error);
});
window.addEventListener('unhandledrejection', (e) => {
console.error('❌ Unhandled Promise Rejection:', e.reason);
});
</script>
</body>