feat: /export?format=json — JSON export for admin

This commit is contained in:
2026-06-11 16:29:24 +04:00
parent 3bc285dc93
commit e3c4c738aa
+13 -3
View File
@@ -85,9 +85,9 @@ function createEntriesRouter({ q }) {
} }
}); });
// GET /api/v1/entries/export — агрегированный список CIDR (text/plain) // GET /api/v1/entries/export — агрегированный список CIDR
// Доступен всем аутентифицированным пользователям. // ?format=json → JSON, иначе text/plain
// Admin: все компании или ?company=<id>. User: только своя компания или ?client_id=<id>. // Только для админа.
router.get('/export', async (req, res) => { router.get('/export', async (req, res) => {
try { try {
let companyId = null; let companyId = null;
@@ -104,6 +104,16 @@ function createEntriesRouter({ q }) {
} }
const cidrs = await q.getExportCIDRs(companyId); const cidrs = await q.getExportCIDRs(companyId);
const aggregated = aggregateCIDRs(cidrs); const aggregated = aggregateCIDRs(cidrs);
const isJson = req.query.format === 'json';
if (isJson) {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
const fname = (req.query.filename || 'white-list.json').replace(/[^\w\-_. ]/g, '_');
const disp = req.query.view === '1' ? 'inline' : 'attachment';
res.setHeader('Content-Disposition', `${disp}; filename="${fname}"`);
return res.json({ cidrs: aggregated, count: aggregated.length });
}
res.setHeader('Content-Type', 'text/plain; charset=utf-8'); res.setHeader('Content-Type', 'text/plain; charset=utf-8');
const fname = (req.query.filename || 'white-list.txt').replace(/[^\w\-_. ]/g, '_'); const fname = (req.query.filename || 'white-list.txt').replace(/[^\w\-_. ]/g, '_');
const disp = req.query.view === '1' ? 'inline' : 'attachment'; const disp = req.query.view === '1' ? 'inline' : 'attachment';