86 lines
3.8 KiB
JavaScript
86 lines
3.8 KiB
JavaScript
// ═══════════════════════════════════════════════════════════════════════════════
|
|
// 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 — text/plain inline (копирование)
|
|
// ?view=2 — HTML таблица с выровненными IP
|
|
// ?filename=X — имя файла (скачивание, когда нет view)
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
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);
|
|
|
|
// ?view=2 — HTML таблица с выровненными IP
|
|
if (req.query.view === '2') {
|
|
res.set('Content-Type', 'text/html; charset=utf-8');
|
|
return res.send(renderTable(aggregated));
|
|
}
|
|
|
|
// ?view=1 — text/plain inline
|
|
if (req.query.view === '1') {
|
|
const text = aggregated.join('\n') + (aggregated.length ? '\n' : '');
|
|
res.set('Content-Type', 'text/plain; charset=utf-8');
|
|
res.set('Content-Disposition', 'inline');
|
|
return res.send(text);
|
|
}
|
|
|
|
// Скачивание (по умолчанию) — без filename чтобы браузер показал диалог сохранения
|
|
const text = aggregated.join('\n') + (aggregated.length ? '\n' : '');
|
|
res.set('Content-Type', 'text/plain; charset=utf-8');
|
|
res.set('Content-Disposition', 'attachment');
|
|
res.send(text);
|
|
} catch (e) {
|
|
console.error('[v2:export] Error:', e);
|
|
res.status(500).send('Ошибка экспорта');
|
|
}
|
|
});
|
|
|
|
return router;
|
|
}
|
|
|
|
function renderTable(cidrs) {
|
|
const rows = cidrs.map(c => {
|
|
const [ip, mask] = c.split('/');
|
|
const [a, b, c2, d] = ip.split('.');
|
|
return '<tr>'
|
|
+ '<td>' + a.padStart(2, ' ') + '</td>'
|
|
+ '<td>' + b.padStart(2, ' ') + '</td>'
|
|
+ '<td>' + c2.padStart(2, ' ') + '</td>'
|
|
+ '<td>' + d.padStart(2, ' ') + '</td>'
|
|
+ '<td> / ' + mask + '</td>'
|
|
+ '</tr>';
|
|
}).join('\n');
|
|
return '<!DOCTYPE html><html><head><meta charset="utf-8"><title>WhiteList Export</title>'
|
|
+ '<style>body{font-family:monospace;background:#fff;color:#111;padding:1rem}'
|
|
+ 'h2{font-size:1rem;color:#666;margin-bottom:.5rem}'
|
|
+ 'table{border-collapse:collapse}'
|
|
+ 'td{padding:.15rem .5rem .15rem 0;white-space:pre;font-size:.9rem;text-align:right}'
|
|
+ '</style></head><body>'
|
|
+ '<h2>WhiteList — ' + cidrs.length + ' записей</h2>'
|
|
+ '<table>' + rows + '</table>'
|
|
+ '</body></html>';
|
|
}
|
|
|
|
module.exports = { createExportRouter };
|