v2: export слой — GET /v2/export, агрегация CIDR
This commit is contained in:
+1
-1
@@ -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": {
|
||||
|
||||
@@ -677,3 +677,74 @@ WZ01112: entries=10 audit=10 dupes=False overLimit=False
|
||||
|
||||
Предыдущие тесты (test.sh, router): 64 теста.
|
||||
Общий итог: **105 тестов, все пройдены** ✅
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Полное тестирование всех комбинаций (0.5.95, 2026-06-13)
|
||||
|
||||
### Новый мок-юзер: adm
|
||||
|
||||
Добавлен для покрытия сценария «админ без имперсонации, много компаний»:
|
||||
|
||||
| Поле | Значение |
|
||||
|------|---------|
|
||||
| email | admin@t.ru |
|
||||
| clientId | WZ01112 |
|
||||
| allClientIds | WZ01112, WZ03709, WZ09999 |
|
||||
| isAdmin | true |
|
||||
| isImpersonated | false |
|
||||
| profiles | 3 компании (Nubes, Дочка, Третья) |
|
||||
|
||||
### Матрица тестирования — все комбинации
|
||||
|
||||
| # | Сценарий | Юзер | Действия | Результат |
|
||||
|---|---------|------|----------|-----------|
|
||||
| 1 | 1 компания, CRUD | u1 | add×2, blocked, list=2, edit, delete, after=1 | ✅ 7/7 |
|
||||
| 2 | 2 компании, switch | u2 | add WZ20002, switch→WZ20001, add, list=1, switch→WZ20002, list=1 | ✅ 6/6 |
|
||||
| 3 | Имперсонация, CRUD | imp | add×2, list=2, created_by=real@t.ru, edit, delete | ✅ 5/5 |
|
||||
| 4 | Имперсонация, аудит | imp | audit: imp_by=admin@t.ru, user=real@t.ru, action=DELETE | ✅ 3/3 |
|
||||
| 5 | Админ, 3 компании | adm | add WZ01112, switch→WZ03709, add, switch→WZ09999, add, list=1, created_by=admin@t.ru, switch→WZ01112, list=1 | ✅ 9/9 |
|
||||
| 6 | Лимит 15 | u1 | 15 записей + 16-я fail | ✅ 1/1 |
|
||||
| 7 | Лимит — другая компания | u2 | add после лимита u1 | ✅ 1/1 |
|
||||
| 8 | Нормализация | u1 | /22 ok, /21 fail, IPv6 fail, normalize | ✅ 4/4 |
|
||||
| 9 | UserFlow u1/u2/imp | u1,u2,imp | add, list, blocked, imp | ✅ 5/5 |
|
||||
| 10 | Chaos (параллельно) | — | 40 ops, 4 компании | ✅ 1/1 |
|
||||
|
||||
### Ключевые проверки
|
||||
|
||||
| Проверка | Сценарий | Результат |
|
||||
|----------|---------|-----------|
|
||||
| created_by = originalUserEmail при имперсонации | imp add | ✅ real@t.ru |
|
||||
| created_by = email админа БЕЗ имперсонации | adm add | ✅ admin@t.ru |
|
||||
| impersonated_by в аудите | imp audit | ✅ admin@t.ru |
|
||||
| user_email в аудите = originalUserEmail | imp audit | ✅ real@t.ru |
|
||||
| switch компаний сохраняет изоляцию | u2 switch | ✅ |
|
||||
| админ видит 3 компании и переключается | adm switch×3 | ✅ |
|
||||
| лимит 15 не влияет на другие компании | u1+u2 | ✅ |
|
||||
|
||||
### Итого: 42 тестовых сценария пройдены
|
||||
|
||||
| Группа | Тестов |
|
||||
|--------|--------|
|
||||
| u1 (1 компания) | 7 |
|
||||
| u2 (2 компании) | 6 |
|
||||
| imp (имперсонация) | 8 |
|
||||
| adm (админ, 3 компании) | 9 |
|
||||
| Лимиты | 2 |
|
||||
| Нормализация | 4 |
|
||||
| UserFlow | 5 |
|
||||
| Chaos | 1 |
|
||||
| **Всего** | **42** |
|
||||
|
||||
Плюс предыдущие: 105 тестов (test.sh + router + ранние).
|
||||
**Общий итог: 147 тестов, все пройдены** ✅
|
||||
|
||||
### Что дальше
|
||||
|
||||
| # | Задача | Статус |
|
||||
|---|--------|--------|
|
||||
| 1 | export/ — выгрузка CIDR | ❌ |
|
||||
| 2 | EJS-шаблоны вместо inline HTML | ❌ |
|
||||
| 3 | Auth end-to-end (KC callback) | ❌ |
|
||||
| 4 | Интеграция в основной код (убрать v2_) | ❌ |
|
||||
|
||||
@@ -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'));
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
module.exports = {
|
||||
version: '0.5.95',
|
||||
version: '0.5.96',
|
||||
|
||||
// ── IAM ──────────────────────────────────────────────────────────────────
|
||||
iamUrl: process.env.V2_IAM_URL || 'https://auth-api.ngcloud.ru/api/v1/auth/user',
|
||||
|
||||
@@ -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 };
|
||||
Reference in New Issue
Block a user