diff --git a/server.js b/server.js index 0525762..6629ce6 100644 --- a/server.js +++ b/server.js @@ -2,42 +2,100 @@ const express = require('express'); const path = require('path'); require('dotenv').config(); const { checkConnection } = require('./src/db'); +const q = require('./src/queries'); const app = express(); const PORT = process.env.PORT || 3000; +const DEV = process.env.DEV_MODE === 'true'; -// Шаблоны app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views')); - -// Статика app.use(express.static(path.join(__dirname, 'public'))); - -// Парсинг форм app.use(express.urlencoded({ extended: true })); -// Health check — всегда 200 если сервер жив. -// Статус БД проверяется отдельно. -app.get('/healthz', (req, res) => { - res.status(200).send('OK'); -}); - -// Главная — показывает реальный статус БД -app.get('/', async (req, res) => { - let dbStatus = 'неизвестно'; - try { - await checkConnection(); - dbStatus = 'подключена'; - } catch (e) { - dbStatus = 'ошибка: ' + e.message; +// ── Auth middleware ── +app.use((req, res, next) => { + if (DEV) { + req.user = { email: 'dev@test.local', clientId: 'WZ01325', companyId: null, companyName: 'DEV' }; + return next(); } - res.render('index', { title: 'IP WhiteList', dbStatus }); + const auth = req.headers.authorization || ''; + try { + const payload = JSON.parse(Buffer.from(auth.replace('Bearer ', '').split('.')[1], 'base64').toString()); + req.user = { + email: payload.email || 'unknown', + clientId: payload.ClientID, + companyId: payload.company_id, + companyName: payload.company_name || payload.ClientID, + }; + } catch { req.user = {}; } + next(); }); -// Не падаем если БД недоступна — healthcheck покажет статус -let dbOk = false; +// ── Health ── +app.get('/healthz', (req, res) => res.send('OK')); + +// ── Главная ── +app.get('/', async (req, res) => { + const { clientId, companyName } = req.user; + try { + const company = await q.getOrCreateCompany(clientId, companyName); + const limit = await q.getLimit(company); + const entries = await q.listEntries(company.id); + res.render('index', { entries, limit, used: entries.length, user: req.user, error: null, message: null, wasNormalized: false }); + } catch (e) { + res.render('index', { entries: [], limit: 15, used: 0, user: req.user, error: e.message, message: null, wasNormalized: false }); + } +}); + +// ── Создать ── +app.post('/add', async (req, res) => { + const { value, comment } = req.body; + const { clientId, companyName, email } = req.user; + try { + const company = await q.getOrCreateCompany(clientId, companyName); + const result = await q.createEntry(company.id, value, comment, email); + const limit = await q.getLimit(company); + const entries = await q.listEntries(company.id); + res.render('index', { + entries, limit, used: entries.length, user: req.user, + message: result.wasNormalized ? `Адрес нормализован в ${result.entry.value_cidr}` : 'Добавлено', + error: null, wasNormalized: result.wasNormalized, + }); + } catch (e) { + const company = await q.getOrCreateCompany(clientId, companyName).catch(() => null); + const entries = company ? await q.listEntries(company.id).catch(() => []) : []; + const limit = company ? await q.getLimit(company).catch(() => 15) : 15; + res.render('index', { entries, limit, used: entries.length, user: req.user, error: e.message, message: null, wasNormalized: false }); + } +}); + +// ── Удалить (soft) ── +app.post('/delete/:id', async (req, res) => { + const { clientId, companyName, email } = req.user; + try { + const company = await q.getOrCreateCompany(clientId, companyName); + await q.deleteEntry(req.params.id, company.id, email); + res.redirect('/'); + } catch (e) { + res.redirect('/?error=' + encodeURIComponent(e.message)); + } +}); + +// ── Экспорт ── +app.get('/export', async (req, res) => { + try { + const cidrs = await q.getExportCIDRs(); + res.setHeader('Content-Type', 'text/plain; charset=utf-8'); + res.send(cidrs.join('\n') + '\n'); + } catch (e) { + res.status(500).send('Export error'); + } +}); + +// ── Старт ── checkConnection() - .then(() => { dbOk = true; console.log('DB connected'); }) - .catch((e) => console.error('DB not ready:', e.message)); + .then(() => console.log('DB connected')) + .catch(e => console.error('DB not ready:', e.message)); app.listen(PORT, () => console.log(`Server on port ${PORT}`)); diff --git a/views/index.ejs b/views/index.ejs index 82f7452..247887a 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -2,12 +2,69 @@ - - <%= title %> - + IP WhiteList + -

<%= title %>

-

Сервис работает. БД: <%= dbStatus %>

+

IP WhiteList

+

<%= user.email %> | <%= user.clientId %> | <%= user.companyName %>

+

Использовано <%= used %> из <%= limit %>

+ + <% if (message) { %>
<%= message %>
<% } %> + <% if (error) { %>
<%= error %>
<% } %> + +
+
+
+ = limit ? 'disabled' : '' %>> +
+
+
+ +
+ +
+ + + + + + + <% entries.forEach(e => { %> + + + + + + + + <% }) %> + +
Адрес / ПодсетьКомментарийКтоКогда
<%= e.value_cidr %><%= e.comment || '' %><%= e.created_by %><%= new Date(e.created_at).toLocaleString('ru') %> +
+ +
+