From 335af011162cc49d996acf9a9bbb92653ca431fc Mon Sep 17 00:00:00 2001 From: shats Date: Tue, 3 Feb 2026 21:56:30 +0700 Subject: [PATCH] feat(mikrotikConfigRoutes, FilterManager): add run-script endpoint and integrate BGP update functionality in FilterManager --- backend/routes/mikrotikConfigRoutes.js | 36 ++++++++++++++++++++++++++ backend/server.js | 1 + frontend/src/FilterManager.jsx | 26 +++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/backend/routes/mikrotikConfigRoutes.js b/backend/routes/mikrotikConfigRoutes.js index ece721e..fa032a6 100644 --- a/backend/routes/mikrotikConfigRoutes.js +++ b/backend/routes/mikrotikConfigRoutes.js @@ -272,10 +272,46 @@ async function applyMikrotikConfig(req, res) { } } +/** + * POST /api/mikrotik/run-script + * Body: { serverId, script?: string } — по умолчанию script=update_bgp_filter + */ +async function runScript(req, res) { + try { + const { serverId, script = 'update_bgp_filter' } = req.body || {}; + if (!serverId) { + return sendError(res, 400, 'serverId is required', 'E_BAD_REQUEST'); + } + + const servers = await readServersFromS3(); + const server = servers.find(s => (s.id || s.dns || s.ip) === serverId); + if (!server || server.type !== 'jumphost') { + return sendError(res, 400, 'Jumphost server not found', 'E_NOT_FOUND'); + } + + const creds = getMikrotikCredentials(server); + if (!creds) { + return sendError(res, 400, 'MikroTik credentials not configured for this server', 'E_CREDENTIALS'); + } + + const client = createRosClient(creds); + // /rest/execute — выполнение произвольной команды (как в CLI) + await client.command('execute', { script: `/system script run ${script}` }); + + return sendOk(res, { ok: true, message: `Скрипт ${script} запущен` }); + } catch (error) { + const msg = error.response?.data?.message || error.message || 'Ошибка запуска скрипта'; + const status = error.response?.status; + console.error('runScript:', error); + return sendError(res, status && status >= 400 ? status : 502, msg, 'E_SCRIPT'); + } +} + module.exports = { generateMikrotikConfig, generateInterfaces, generateRecursiveRoutes, testMikrotikConnection, applyMikrotikConfig, + runScript, }; diff --git a/backend/server.js b/backend/server.js index e0dca61..f090df9 100644 --- a/backend/server.js +++ b/backend/server.js @@ -452,6 +452,7 @@ app.get('/api/mikrotik/generate-recursive-routes', mikrotikConfigRoutes.generate app.post('/api/mikrotik/test-connection', mikrotikConfigRoutes.testMikrotikConnection); app.get('/api/mikrotik/ping', (req, res) => res.json({ ok: true, ts: Date.now() })); app.post('/api/mikrotik/apply', mikrotikConfigRoutes.applyMikrotikConfig); +app.post('/api/mikrotik/run-script', mikrotikConfigRoutes.runScript); // === MIKROTIK VALIDATION === app.post('/api/mikrotik/validate', async (req, res) => { diff --git a/frontend/src/FilterManager.jsx b/frontend/src/FilterManager.jsx index f09ad8f..1229038 100644 --- a/frontend/src/FilterManager.jsx +++ b/frontend/src/FilterManager.jsx @@ -746,6 +746,7 @@ function FilterManager() { // Состояние для массовых действий const [selectedFilterKeys, setSelectedFilterKeys] = useState(new Set()); const [confirmState, setConfirmState] = useState({ open: false, text: '', onConfirm: null }); + const [bgpUpdateLoading, setBgpUpdateLoading] = useState(false); // Состояние для копирования правил с сервера const [copyFromServerModalOpen, setCopyFromServerModalOpen] = useState(false); @@ -1070,6 +1071,22 @@ function FilterManager() { } }; + const handleBgpUpdate = async () => { + if (!selectedServer) return; + setBgpUpdateLoading(true); + setError(''); + try { + await api.post('/mikrotik/run-script', { serverId: selectedServer.id, script: 'update_bgp_filter' }); + setSuccess(`Скрипт update_bgp_filter запущен на ${selectedServer.name}`); + setTimeout(() => setSuccess(''), 3000); + } catch (err) { + const msg = err.response?.data?.message || err.message || 'Не удалось запустить скрипт'; + setError(msg); + } finally { + setBgpUpdateLoading(false); + } + }; + const handleSaveServerConfig = async (serverId) => { try { const config = await generateMikrotikConfig(); @@ -1802,6 +1819,15 @@ function FilterManager() { Сохранить + )}