From 07e69ce82359dde0da6000d333b1fcad9a7222dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Sat, 13 Jun 2026 08:34:09 +0400 Subject: [PATCH] =?UTF-8?q?v2:=20export=20=D1=81=D0=BB=D0=BE=D0=B9=20?= =?UTF-8?q?=E2=80=94=20GET=20/v2/export,=20=D0=B0=D0=B3=D1=80=D0=B5=D0=B3?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20CIDR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- v2/server.js | 4 ++++ v2/src/export/index.js | 49 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 v2/src/export/index.js diff --git a/package.json b/package.json index a2583cb..5309b12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.5.95", + "version": "0.5.96", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/v2/server.js b/v2/server.js index ffe753e..77d9e64 100644 --- a/v2/server.js +++ b/v2/server.js @@ -65,6 +65,10 @@ function createV2Router() { router.use('/test', createTestRouter()); } + // ── /v2/export — выгрузка CIDR (публичный, без авторизации) ────── + const { createExportRouter } = require('./src/export'); + router.use('/export', createExportRouter()); + // ── GET /v2/logout — редирект на основной выход ───────────────────── router.get('/logout', (req, res) => res.redirect('/logout')); diff --git a/v2/src/export/index.js b/v2/src/export/index.js new file mode 100644 index 0000000..28bcf55 --- /dev/null +++ b/v2/src/export/index.js @@ -0,0 +1,49 @@ +// ═══════════════════════════════════════════════════════════════════════════════ +// V2 — Экспорт CIDR (отдельный слой) +// +// ЭТО: выгрузка разрешённых CIDR в текстовом виде. +// НЕ: CRUD, валидация (использует db + validators). +// +// ЗАЧЕМ: +// 1. Отдать CIDR для firewall/nginx белого списка. +// 2. Агрегировать соседние CIDR в минимальный набор (экономия правил). +// 3. Поддержка фильтрации по компании (?companyId=X). +// +// ЦЕПОЧКА: GET /v2/export → q.getExportCIDRs → aggregateCIDRs → text/plain +// +// ПАРАМЕТРЫ: +// ?companyId=X — фильтр по компании (внутренний id) +// ?view=1 — показать в браузере (иначе — скачивание) +// ?filename=X — имя файла (по умолчанию white-list.txt) +// ═══════════════════════════════════════════════════════════════════════════════ + +const express = require('express'); +const q = require('../db/queries'); +const { aggregateCIDRs } = require('../validators'); + +function createExportRouter() { + const router = express.Router(); + + router.get('/', async (req, res) => { + try { + const companyId = req.query.companyId ? parseInt(req.query.companyId) : null; + const cidrs = await q.getExportCIDRs(companyId); + const aggregated = aggregateCIDRs(cidrs); + const text = aggregated.join('\n') + (aggregated.length ? '\n' : ''); + + res.set('Content-Type', 'text/plain; charset=utf-8'); + + const fname = (req.query.filename || 'white-list.txt').replace(/[^\w\-_. ]/g, '_'); + const disp = req.query.view === '1' ? 'inline' : 'attachment'; + res.set('Content-Disposition', disp + '; filename="' + fname + '"'); + res.send(text); + } catch (e) { + console.error('[v2:export] Error:', e); + res.status(500).send('Ошибка экспорта'); + } + }); + + return router; +} + +module.exports = { createExportRouter };