diff --git a/backend/server.js b/backend/server.js index 96ec6bf..11d75ff 100644 --- a/backend/server.js +++ b/backend/server.js @@ -26,6 +26,35 @@ const s3 = new AWS.S3({ const BUCKET_NAME = process.env.S3_BUCKET_NAME; const FILE_KEY = 'bgp_data/domains.txt'; +// Helper: build MikroTik nested if/else blocks (RouterOS v7 filter language does not support 'else if') +function buildNestedGatewayBlocks(gatewayGroups, baseIndentSpaces = 4) { + const indent = (n) => ' '.repeat(n); + const entries = Object.entries(gatewayGroups); + if (entries.length === 0) return ''; + + function buildAt(index, pad) { + const [gateway, communities] = entries[index]; + let s = ''; + s += `${indent(pad)}if (\n`; + communities.forEach((community, i) => { + s += `${indent(pad + 4)}(bgp-communities includes ${community})`; + if (i < communities.length - 1) s += ' or \n'; + }); + s += `\n${indent(pad)})\n`; + s += `${indent(pad)}{\n${indent(pad + 8 - 4)}set gw ${gateway}; accept;\n${indent(pad)}}\n`; + if (index < entries.length - 1) { + s += `${indent(pad)}else\n${indent(pad)}{\n`; + s += buildAt(index + 1, pad + 4); + s += `\n${indent(pad)}}`; + } else { + s += `${indent(pad)}else\n${indent(pad)}{\n${indent(pad + 4)}reject;\n${indent(pad)}}`; + } + return s; + } + + return buildAt(0, baseIndentSpaces); +} + // Get domains from S3 app.get('/api/domains', async (req, res) => { const params = { @@ -608,42 +637,8 @@ app.get('/api/filters/generate-config', async (req, res) => { config += `// Date: ${new Date().toISOString()}\n\n`; config += '/routing filter bgp-in-tmp {\n'; - // Если есть только один gateway, создаем простую конфигурацию - if (Object.keys(gatewayGroups).length === 1) { - const [gateway, communities] = Object.entries(gatewayGroups)[0]; - config += ` if (\n`; - communities.forEach((community, index) => { - config += ` (bgp-communities includes ${community})`; - if (index < communities.length - 1) { - config += ` or \n`; - } - }); - config += `\n )\n {\n set gw ${gateway}; accept;\n }\n else\n {\n reject;\n }\n`; - } else { - // Если несколько gateway, создаем каскадную структуру - const gatewayEntries = Object.entries(gatewayGroups); - gatewayEntries.forEach(([gateway, communities], gatewayIndex) => { - if (gatewayIndex === 0) { - config += ` if (\n`; - } else { - config += ` else if (\n`; - } - - communities.forEach((community, index) => { - config += ` (bgp-communities includes ${community})`; - if (index < communities.length - 1) { - config += ` or \n`; - } - }); - config += `\n )\n {\n set gw ${gateway}; accept;\n }`; - - if (gatewayIndex === gatewayEntries.length - 1) { - config += `\n else\n {\n reject;\n }\n`; - } else { - config += `\n`; - } - }); - } + // Строим вложенные if/else (RouterOS не поддерживает else if в данном контексте) + config += buildNestedGatewayBlocks(gatewayGroups, 4); config += '}\n'; @@ -698,42 +693,8 @@ app.post('/api/filters/export-config', async (req, res) => { config += `// Date: ${new Date().toISOString()}\n\n`; config += '/routing filter bgp-in-tmp {\n'; - // Если есть только один gateway, создаем простую конфигурацию - if (Object.keys(gatewayGroups).length === 1) { - const [gateway, communities] = Object.entries(gatewayGroups)[0]; - config += ` if (\n`; - communities.forEach((community, index) => { - config += ` (bgp-communities includes ${community})`; - if (index < communities.length - 1) { - config += ` or \n`; - } - }); - config += `\n )\n {\n set gw ${gateway}; accept;\n }\n else\n {\n reject;\n }\n`; - } else { - // Если несколько gateway, создаем каскадную структуру - const gatewayEntries = Object.entries(gatewayGroups); - gatewayEntries.forEach(([gateway, communities], gatewayIndex) => { - if (gatewayIndex === 0) { - config += ` if (\n`; - } else { - config += ` else if (\n`; - } - - communities.forEach((community, index) => { - config += ` (bgp-communities includes ${community})`; - if (index < communities.length - 1) { - config += ` or \n`; - } - }); - config += `\n )\n {\n set gw ${gateway}; accept;\n }`; - - if (gatewayIndex === gatewayEntries.length - 1) { - config += `\n else\n {\n reject;\n }\n`; - } else { - config += `\n`; - } - }); - } + // Строим вложенные if/else (RouterOS не поддерживает else if в данном контексте) + config += buildNestedGatewayBlocks(gatewayGroups, 4); config += '}\n'; @@ -977,42 +938,8 @@ app.post('/api/server-filters/generate-config', async (req, res) => { config += `// Date: ${new Date().toISOString()}\n\n`; config += '/routing filter bgp-in-tmp {\n'; - // Если есть только один gateway, создаем простую конфигурацию - if (Object.keys(gatewayGroups).length === 1) { - const [gateway, communities] = Object.entries(gatewayGroups)[0]; - config += ` if (\n`; - communities.forEach((community, index) => { - config += ` (bgp-communities includes ${community})`; - if (index < communities.length - 1) { - config += ` or \n`; - } - }); - config += `\n )\n {\n set gw ${gateway}; accept;\n }\n else\n {\n reject;\n }\n`; - } else { - // Если несколько gateway, создаем каскадную структуру - const gatewayEntries = Object.entries(gatewayGroups); - gatewayEntries.forEach(([gateway, communities], gatewayIndex) => { - if (gatewayIndex === 0) { - config += ` if (\n`; - } else { - config += ` else if (\n`; - } - - communities.forEach((community, index) => { - config += ` (bgp-communities includes ${community})`; - if (index < communities.length - 1) { - config += ` or \n`; - } - }); - config += `\n )\n {\n set gw ${gateway}; accept;\n }`; - - if (gatewayIndex === gatewayEntries.length - 1) { - config += `\n else\n {\n reject;\n }\n`; - } else { - config += `\n`; - } - }); - } + // Строим вложенные if/else (RouterOS не поддерживает else if в данном контексте) + config += buildNestedGatewayBlocks(gatewayGroups, 4); config += '}\n';