v2: /v2/test/api — CRUD эндпоинт + внешние тесты curl
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// V2 — тестовый эндпоинт для CRUD
|
||||
// Принимает ?action=...&user=... → JSON-ответ
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
const express = require('express');
|
||||
const q = require('../db/queries');
|
||||
const { pool } = require('../db');
|
||||
|
||||
// Мок-юзеры
|
||||
const USERS = {
|
||||
u1: { email:'u1@t.ru', clientId:'WZ10001', activeClientId:'WZ10001', allClientIds:['WZ10001'], companyName:'Одна', isAdmin:false, profiles:[{client_id:'WZ10001',company_name:'Одна'}] },
|
||||
u2: { email:'u2@t.ru', clientId:'WZ20001', activeClientId:'WZ20002', allClientIds:['WZ20001','WZ20002'], companyName:'Вторая', isAdmin:false, profiles:[{client_id:'WZ20001',company_name:'Первая'},{client_id:'WZ20002',company_name:'Вторая'}] },
|
||||
imp:{ email:'admin@t.ru', clientId:'WZ01112', activeClientId:'WZ01112', allClientIds:['WZ01112','WZ03709'], companyName:'Nubes', isAdmin:true, isImpersonated:true, originalUserEmail:'real@t.ru', impersonatedCompanyId:'WZ03709', profiles:[] },
|
||||
};
|
||||
|
||||
function createTestRouter() {
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/', async (req, res) => {
|
||||
try {
|
||||
const action = req.query.action;
|
||||
const user = USERS[req.query.user || 'u1'];
|
||||
if (!user) return res.json({ ok: false, error: 'unknown user' });
|
||||
|
||||
const email = user.isImpersonated ? user.originalUserEmail : user.email;
|
||||
const clientId = user.isImpersonated ? user.impersonatedCompanyId : user.activeClientId;
|
||||
const company = await q.getOrCreateCompany(clientId, user.companyName || clientId);
|
||||
const impBy = user.isImpersonated ? user.email : null;
|
||||
|
||||
switch (action) {
|
||||
// ── LIST ──
|
||||
case 'list':
|
||||
const entries = await q.listEntries(company.id, req.query.deleted === '1');
|
||||
return res.json({ ok: true, entries, count: entries.length, company: { id: company.id, client_id: company.client_id } });
|
||||
|
||||
// ── ADD ──
|
||||
case 'add': {
|
||||
const r = await q.createEntry(company.id, req.query.cidr || '', req.query.comment || '', email, impBy);
|
||||
return res.json({ ok: true, entry: r.entry, wasNormalized: r.wasNormalized });
|
||||
}
|
||||
|
||||
// ── EDIT ──
|
||||
case 'edit': {
|
||||
const r = await q.updateEntry(parseInt(req.query.id), company.id, req.query.cidr || '', req.query.comment || '', email, impBy);
|
||||
return res.json({ ok: true, entry: r.entry, wasNormalized: r.wasNormalized });
|
||||
}
|
||||
|
||||
// ── DELETE ──
|
||||
case 'delete':
|
||||
await q.deleteEntry(parseInt(req.query.id), company.id, email, impBy);
|
||||
return res.json({ ok: true });
|
||||
|
||||
// ── AUDIT ──
|
||||
case 'audit': {
|
||||
const audit = await q.getAudit(company.id);
|
||||
return res.json({ ok: true, audit, count: audit.length });
|
||||
}
|
||||
|
||||
// ── LIMIT ──
|
||||
case 'limit':
|
||||
return res.json({ ok: true, limit: await q.getLimit(company) });
|
||||
|
||||
// ── CLEANUP ──
|
||||
case 'cleanup': {
|
||||
const cids = (req.query.cids || '').split(',');
|
||||
for (const c of cids) {
|
||||
await pool.query('DELETE FROM v2_entries WHERE company_id IN (SELECT id FROM v2_companies WHERE client_id=$1)',[c]).catch(()=>{});
|
||||
await pool.query('DELETE FROM v2_audit WHERE company_id IN (SELECT id FROM v2_companies WHERE client_id=$1)',[c]).catch(()=>{});
|
||||
await pool.query('DELETE FROM v2_companies WHERE client_id=$1',[c]).catch(()=>{});
|
||||
}
|
||||
return res.json({ ok: true });
|
||||
}
|
||||
|
||||
default:
|
||||
return res.json({ ok: false, error: 'unknown action: ' + action });
|
||||
}
|
||||
} catch (e) {
|
||||
return res.json({ ok: false, error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
module.exports = { createTestRouter };
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# CRUD-тесты через /v2/test/api
|
||||
# Запуск: bash test.sh https://whitelist.nodejsk8s.services.ngcloud.ru
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
BASE="${1:-http://localhost:3000}/v2/test/api"
|
||||
P=0 F=0
|
||||
|
||||
t() { local name="$1"; shift; if "$@"; then echo "✅ $name"; ((P++)); else echo "❌ $name"; ((F++)); fi; }
|
||||
ok() { curl -sk "$BASE$1" | python3 -c "import sys,json; d=json.load(sys.stdin); sys.exit(0 if d.get('ok') else 1)"; }
|
||||
|
||||
echo "=== 1. Одна компания ==="
|
||||
|
||||
t "создание компании" ok "?action=list&user=u1"
|
||||
|
||||
t "добавление" ok "?action=add&user=u1&cidr=1.2.3.0/24&comment=тест"
|
||||
|
||||
t "дубликат" '!' 'ok "?action=add&user=u1&cidr=1.2.3.0/24"'
|
||||
|
||||
t "пересечение" '!' 'ok "?action=add&user=u1&cidr=1.2.3.128/25"'
|
||||
|
||||
t "запрещённый диапазон" '!' 'ok "?action=add&user=u1&cidr=10.0.0.0/24"'
|
||||
|
||||
t "/32 работает" ok "?action=add&user=u1&cidr=5.5.5.5"
|
||||
|
||||
ID=$(curl -sk "$BASE?action=list&user=u1" | python3 -c "import sys,json; print(json.load(sys.stdin)['entries'][0]['id'])")
|
||||
|
||||
t "изменение" ok "?action=edit&user=u1&id=$ID&cidr=6.6.6.0/24&comment=изменено"
|
||||
|
||||
t "удаление" ok "?action=delete&user=u1&id=$ID"
|
||||
|
||||
t "аудит" ok "?action=audit&user=u1"
|
||||
|
||||
echo ""
|
||||
echo "=== 2. Две компании ==="
|
||||
|
||||
t "добавление в активную" ok "?action=add&user=u2&cidr=7.7.7.0/24"
|
||||
|
||||
LIST1=$(curl -sk "$BASE?action=list&user=u2" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['entries']))")
|
||||
t "в активной есть запись" [ "$LIST1" -gt 0 ]
|
||||
|
||||
echo ""
|
||||
echo "=== 3. Имперсонация ==="
|
||||
|
||||
t "добавление с impersonated_by" ok "?action=add&user=imp&cidr=8.8.8.0/24"
|
||||
|
||||
AUDIT=$(curl -sk "$BASE?action=audit&user=imp" | python3 -c "import sys,json; a=json.load(sys.stdin)['audit']; print(a[0].get('impersonated_by','NONE'))")
|
||||
t "impersonated_by в аудите" [ "$AUDIT" = "admin@t.ru" ]
|
||||
|
||||
echo ""
|
||||
echo "=== Чистка ==="
|
||||
ok "?action=cleanup&cids=WZ10001,WZ20001,WZ20002,WZ01112,WZ03709"
|
||||
|
||||
echo ""
|
||||
echo "$P passed, $F failed"
|
||||
[ "$F" -eq 0 ] || exit 1
|
||||
Reference in New Issue
Block a user