108 lines
3.9 KiB
JavaScript
108 lines
3.9 KiB
JavaScript
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' && process.env.NODE_ENV !== 'production';
|
|
|
|
if (DEV) console.warn('⚠ DEV_MODE активен — аутентификация отключена');
|
|
|
|
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, limit: '32kb' }));
|
|
|
|
// ── Health (выше auth — k8s probe не должна требовать токен) ──
|
|
app.get('/healthz', (req, res) => res.send('OK'));
|
|
|
|
// ── Auth middleware ──
|
|
app.use((req, res, next) => {
|
|
if (DEV) {
|
|
req.user = { email: 'dev@test.local', clientId: 'WZ01325', companyId: null, companyName: 'DEV' };
|
|
return next();
|
|
}
|
|
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 = {}; }
|
|
// Без clientId — 401, анонимы не должны делить NULL-компанию
|
|
if (!req.user.clientId) return res.status(401).send('Unauthorized');
|
|
next();
|
|
});
|
|
|
|
// ── Главная ──
|
|
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: req.query.error || null,
|
|
message: req.query.message || null,
|
|
wasNormalized: req.query.wasNormalized === '1',
|
|
});
|
|
} catch (e) {
|
|
res.render('index', { entries: [], limit: 15, used: 0, user: req.user, error: 'Ошибка загрузки', 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 message = result.wasNormalized
|
|
? `Адрес нормализован в ${result.entry.value_cidr}`
|
|
: 'Добавлено';
|
|
const wasNormalized = result.wasNormalized ? '1' : '0';
|
|
res.redirect(`/?message=${encodeURIComponent(message)}&wasNormalized=${wasNormalized}`);
|
|
} catch (e) {
|
|
res.redirect('/?error=' + encodeURIComponent(e.message));
|
|
}
|
|
});
|
|
|
|
// ── Удалить (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 { clientId, companyName } = req.user;
|
|
const company = await q.getOrCreateCompany(clientId, companyName);
|
|
const cidrs = await q.getExportCIDRs(company.id);
|
|
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(() => console.log('DB connected'))
|
|
.catch(e => console.error('DB not ready:', e.message));
|
|
|
|
app.listen(PORT, () => console.log(`Server on port ${PORT}`));
|