diff --git a/package.json b/package.json index 4ff0607..21b18b0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.5.92", + "version": "0.5.93", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/v2/src/admin/index.js b/v2/src/admin/index.js index 561b8ae..1c2bb30 100644 --- a/v2/src/admin/index.js +++ b/v2/src/admin/index.js @@ -1,23 +1,194 @@ // ═══════════════════════════════════════════════════════════════════════════════ -// V2 — админка (пустышка) -// Будет: аудит, лимиты, список всех компаний, toggle «Администратор» +// V2 — Админка (Dashboard, аудит, лимиты, все компании) +// +// Вход: req.isAdmin, req.email, req.clientId из resolveContext. +// Только для админов (isAdmin=true). +// Через crud/ для CRUD, через db/queries для admin-specific (аудит, лимиты). // ═══════════════════════════════════════════════════════════════════════════════ const express = require('express'); +const q = require('../db/queries'); +const crud = require('../crud'); function createAdminRouter() { const router = express.Router(); - router.get('/', (req, res) => { - res.send(`

Admin panel

-

email: ${req.email}

-

clientId: ${req.clientId}

-

Все компании: ${(req.allClientIds || []).join(', ') || '—'}

-

Пользовательский CRUD | Выйти

- `); + // ── middleware: только админы ─────────────────────────────────────────── + router.use((req, res, next) => { + if (!req.isAdmin) return res.redirect('/v2/app'); + next(); + }); + + // ── GET / — дашборд: все компании ────────────────────────────────────── + router.get('/', async (req, res) => { + try { + const companies = await q.getAllCompanies(); + const version = require('../config').version; + res.send(renderDashboard({ companies, user: req.user || {}, version })); + } catch (e) { + res.status(500).send('

Ошибка

' + e.message + '
'); + } + }); + + // ── GET /audit?companyId=X ───────────────────────────────────────────── + router.get('/audit', async (req, res) => { + try { + const companyId = req.query.companyId ? parseInt(req.query.companyId) : null; + const audit = await q.getAudit(companyId); + const company = companyId ? await q.getCompanyById(companyId) : null; + res.send(renderAudit({ audit, company, version: require('../config').version })); + } catch (e) { + res.status(500).send('

Ошибка

' + e.message + '
'); + } + }); + + // ── POST /limit ──────────────────────────────────────────────────────── + router.post('/limit', async (req, res) => { + try { + const companyId = parseInt(req.body.companyId); + const newLimit = parseInt(req.body.limit); + if (!companyId || !newLimit || newLimit < 1) throw new Error('Неверные параметры'); + await q.setLimit(companyId, newLimit); + res.redirect('/v2/admin?msg=' + encodeURIComponent('Лимит установлен: ' + newLimit)); + } catch (e) { + res.redirect('/v2/admin?error=' + encodeURIComponent(e.message)); + } + }); + + // ── GET /entries?companyId=X — записи любой компании ─────────────────── + router.get('/entries', async (req, res) => { + try { + const companyId = parseInt(req.query.companyId); + const company = companyId ? await q.getCompanyById(companyId) : null; + if (!company) return res.redirect('/v2/admin'); + const { entries, used, limit } = await crud.list(company.client_id, req.query.deleted === '1'); + const version = require('../config').version; + res.send(renderEntries({ entries, company, used, limit, includeDeleted: req.query.deleted === '1', version })); + } catch (e) { + res.status(500).send('

Ошибка

' + e.message + '
'); + } }); return router; } +// ── HTML-рендеринг ───────────────────────────────────────────────────────── + +function renderDashboard({ companies, user, version }) { + const rows = companies.map(c => ` + + ${c.name || c.client_id} + ${c.client_id} + ${c.active_count} / ${c.custom_limit != null ? c.custom_limit : 15} + ${c.custom_limit != null ? c.custom_limit : '—'} + + аудит | + записи + + +
+ + + +
+ + `).join(''); + + return ` +Admin — IP WhiteList v${version} + +
+ 🛡️ ADMIN v${version} + ${user.email || '—'} | ← Пользовательский | Выйти +
+${msgHtml()} +

Компании (${companies.length})

+ + + ${rows || ''} +
КомпанияClient IDЗаписейЛимитНовый лимит
Нет компаний
+`; +} + +function renderAudit({ audit, company, version }) { + const rows = audit.map(a => ` + + ${new Date(a.created_at).toLocaleString('ru')} + ${a.action} + ${a.user_email} + ${a.impersonated_by || '—'} + ${a.company_name || '—'} + ${a.old_value || '—'} → ${a.new_value || '—'} + `).join(''); + + return ` +Аудит — ${company ? company.client_id : 'Все'} — v${version} + +
+ 📋 Аудит ${company ? company.client_id : 'Все компании'} + ← Админка | Пользовательский +
+ + + ${rows || ''} +
ДатаДействиеКтоОт имениКомпанияЗначения
Нет записей
+

Показано: ${audit.length} (макс 500)

+`; +} + +function renderEntries({ entries, company, used, limit, includeDeleted, version }) { + const rows = entries.map(e => { + const del = e.deleted_at; + const style = del ? 'text-decoration:line-through;opacity:0.5' : ''; + return `${e.value_cidr}${e.comment || ''}${e.created_by}${new Date(e.created_at).toLocaleString('ru')}${del ? 'удалено' : 'активна'}`; + }).join(''); + + return ` +Записи — ${company.client_id} — v${version} + +
+ 📋 Записи ${company.client_id} — ${company.name || company.client_id} + ← Админка +
+

Записей: ${used} из ${limit} ${includeDeleted ? '(с удалёнными: ' + entries.length + ')' : ''}

+ + + ${rows || ''} +
CIDRКомментарийКтоКогдаСтатус
Нет записей
+

${includeDeleted ? 'Скрыть удалённые' : 'Показать удалённые'}

+`; +} + +function msgHtml() { + return ``; +} + module.exports = { createAdminRouter }; diff --git a/v2/src/config/index.js b/v2/src/config/index.js index 84f0cc8..b32e2b6 100644 --- a/v2/src/config/index.js +++ b/v2/src/config/index.js @@ -6,7 +6,7 @@ // ═══════════════════════════════════════════════════════════════════════════════ module.exports = { - version: '0.5.92', + version: '0.5.93', iamUrl: process.env.V2_IAM_API_URL || 'https://auth-api.ngcloud.ru', appUrl: process.env.V2_APP_URL || 'https://whitelist.nodejsk8s.services.ngcloud.ru', };