v0.5.10: /export — attachment default, ?view=1 inline, ?filename=custom

This commit is contained in:
2026-06-02 14:49:50 +03:00
parent 72e021acfe
commit 51a003e078
4 changed files with 26 additions and 8 deletions
+11 -4
View File
@@ -39,8 +39,12 @@ function createRouter({ q, exportLimiter, aggregateCIDRs }) {
if (!req.user.isAdmin) {
// Обычный пользователь: только его компания.
// getOrCreateCompany — атомарная UPSERT, безопасна для параллельных вызовов.
const company = await q.getOrCreateCompany(req.user.clientId, req.user.companyName);
// ?client_id= для мульти-компании
const requestedId = (req.query.client_id || '').trim();
const effectiveClientId = (requestedId && req.user.allClientIds && req.user.allClientIds.includes(requestedId))
? requestedId
: req.user.clientId;
const company = await q.getOrCreateCompany(effectiveClientId, effectiveClientId);
companyId = company.id;
} else if (req.query.company) {
// Администратор с необязательным фильтром по компании.
@@ -56,9 +60,12 @@ function createRouter({ q, exportLimiter, aggregateCIDRs }) {
const aggregated = aggregateCIDRs(cidrs);
// Content-Type: text/plain — чтобы браузер не пытался разбирать как HTML.
// Content-Disposition: inline — открывается в браузере, а не скачивается.
// ?view=1 → inline (просмотр в браузере), иначе → attachment (скачивание)
// ?filename=X → своё имя файла, по умолчанию white-list.txt
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.setHeader('Content-Disposition', 'inline; filename="whitelist.txt"');
const fname = req.query.filename || 'white-list.txt';
const disp = req.query.view === '1' ? 'inline' : 'attachment';
res.setHeader('Content-Disposition', `${disp}; filename="${fname}"`);
// Один CIDR на строку. Если список пустой — возвращаем пустую строку (не ошибку).
res.send(aggregated.join('\n') + (aggregated.length ? '\n' : ''));