feat: implement password changes, agent headers, MAC routing tags, GeoIP caching lookups, port descriptions, and network infra agent isolation
This commit is contained in:
1 parent
72ded25e4d
commit
93d4002b27
10 files changed
+1206
-139
No files matched your search
+132
-3
@@ -1,7 +1,7 @@
|
||||
const express = require('express');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const { getUserByUsername } = require('../database');
|
||||
const { getUserByUsername, updateUserPassword, getDB } = require('../database');
|
||||
const router = express.Router();
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'super-secret-backone-key';
|
||||
@@ -23,7 +23,7 @@ router.post('/login', (req, res) => {
|
||||
}
|
||||
|
||||
const token = jwt.sign(
|
||||
{ id: user.id, username: user.username, role: user.role, site_uuid: user.site_uuid },
|
||||
{ id: user.id, username: user.username, role: user.role, site_uuid: user.site_uuid, agent_uuid: user.agent_uuid },
|
||||
JWT_SECRET,
|
||||
{ expiresIn: '1d' }
|
||||
);
|
||||
@@ -38,7 +38,7 @@ router.post('/login', (req, res) => {
|
||||
|
||||
res.json({
|
||||
message: 'Login successful',
|
||||
user: { id: user.id, username: user.username, role: user.role, site_uuid: user.site_uuid }
|
||||
user: { id: user.id, username: user.username, role: user.role, site_uuid: user.site_uuid, agent_uuid: user.agent_uuid }
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,9 +56,138 @@ router.get('/me', (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/change-password', (req, res) => {
|
||||
const token = req.cookies?.token;
|
||||
if (!token) {
|
||||
return res.status(401).json({ error: 'Not authenticated' });
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, JWT_SECRET);
|
||||
const { currentPassword, newPassword } = req.body;
|
||||
|
||||
if (!currentPassword || !newPassword) {
|
||||
return res.status(400).json({ error: 'Current password and new password are required' });
|
||||
}
|
||||
|
||||
// 1. Get user details from database
|
||||
const user = getUserByUsername(decoded.username);
|
||||
if (!user) {
|
||||
return res.status(404).json({ error: 'User not found' });
|
||||
}
|
||||
|
||||
// 2. Verify current password
|
||||
const isCurrentValid = bcrypt.compareSync(currentPassword, user.password_hash);
|
||||
if (!isCurrentValid) {
|
||||
return res.status(400).json({ error: 'Password saat ini salah' });
|
||||
}
|
||||
|
||||
// 3. Validate new password strength
|
||||
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>]).{8,}$/;
|
||||
if (!passwordRegex.test(newPassword)) {
|
||||
return res.status(400).json({
|
||||
error: 'Password baru tidak memenuhi kriteria: minimal 8 karakter, serta mengandung huruf besar, huruf kecil, angka, dan karakter spesial.'
|
||||
});
|
||||
}
|
||||
|
||||
// 4. Hash new password and save to DB
|
||||
const newHash = bcrypt.hashSync(newPassword, 10);
|
||||
updateUserPassword(user.id, newHash);
|
||||
|
||||
return res.json({ ok: true, message: 'Password berhasil diubah!' });
|
||||
} catch (err) {
|
||||
return res.status(401).json({ error: 'Invalid token' });
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/logout', (req, res) => {
|
||||
res.clearCookie('token');
|
||||
res.json({ message: 'Logged out successfully' });
|
||||
});
|
||||
|
||||
router.get('/geoip', async (req, res) => {
|
||||
const ip = req.query.ip;
|
||||
if (!ip) {
|
||||
return res.status(400).json({ error: 'IP is required' });
|
||||
}
|
||||
|
||||
const d = getDB();
|
||||
try {
|
||||
// 1. Check local cache
|
||||
let cached = d.prepare("SELECT * FROM geoip_cache WHERE ip_address = ?").get(ip);
|
||||
if (cached) {
|
||||
return res.json(cached);
|
||||
}
|
||||
|
||||
// 2. Check if private IP (IPv4 and IPv6 link local)
|
||||
const parts = ip.split('.');
|
||||
let isPrivate = false;
|
||||
if (parts.length === 4) {
|
||||
const o1 = parseInt(parts[0], 10);
|
||||
const o2 = parseInt(parts[1], 10);
|
||||
if (o1 === 10) isPrivate = true;
|
||||
else if (o1 === 192 && o2 === 168) isPrivate = true;
|
||||
else if (o1 === 172 && (o2 >= 16 && o2 <= 31)) isPrivate = true;
|
||||
else if (o1 === 127) isPrivate = true;
|
||||
else if (o1 === 169 && o2 === 254) isPrivate = true;
|
||||
} else if (ip.startsWith('fe80:') || ip === '::1' || ip.startsWith('fd')) {
|
||||
isPrivate = true;
|
||||
}
|
||||
|
||||
if (isPrivate) {
|
||||
const privateInfo = {
|
||||
ip_address: ip,
|
||||
isp: 'Intranet / Private Network',
|
||||
country: 'Local',
|
||||
city: 'Local',
|
||||
as_org: 'RFC 1918 Private Range'
|
||||
};
|
||||
d.prepare("INSERT OR IGNORE INTO geoip_cache (ip_address, isp, country, city, as_org) VALUES (?, ?, ?, ?, ?)").run(
|
||||
privateInfo.ip_address, privateInfo.isp, privateInfo.country, privateInfo.city, privateInfo.as_org
|
||||
);
|
||||
return res.json(privateInfo);
|
||||
}
|
||||
|
||||
// 3. Query public GeoIP API (ip-api.com) with timeout
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 3000); // 3-second timeout
|
||||
|
||||
const response = await fetch(`http://ip-api.com/json/${ip}`, { signal: controller.signal });
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
const geo = await response.json();
|
||||
if (geo && geo.status === 'success') {
|
||||
const publicInfo = {
|
||||
ip_address: ip,
|
||||
isp: geo.isp || 'Unknown ISP',
|
||||
country: geo.country || 'Unknown Country',
|
||||
city: geo.city || 'Unknown City',
|
||||
as_org: geo.as || geo.org || 'Data Center'
|
||||
};
|
||||
|
||||
d.prepare("INSERT OR IGNORE INTO geoip_cache (ip_address, isp, country, city, as_org) VALUES (?, ?, ?, ?, ?)").run(
|
||||
publicInfo.ip_address, publicInfo.isp, publicInfo.country, publicInfo.city, publicInfo.as_org
|
||||
);
|
||||
return res.json(publicInfo);
|
||||
} else {
|
||||
// Return temporary/fallback details for lookup failures without caching
|
||||
return res.json({
|
||||
ip_address: ip,
|
||||
isp: 'Public IP',
|
||||
country: 'Remote',
|
||||
city: 'Remote',
|
||||
as_org: 'Public Network'
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
return res.json({
|
||||
ip_address: ip,
|
||||
isp: 'Public IP',
|
||||
country: 'Remote',
|
||||
city: 'Remote',
|
||||
as_org: 'Public Network'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
+45
-45
@@ -6,8 +6,8 @@ const { runPoll } = require('../scheduler');
|
||||
|
||||
// GET /api/dashboard/summary — kartu ringkasan (top of page)
|
||||
router.get('/summary', (req, res) => {
|
||||
const stats = db.getStats(req.user?.site_uuid);
|
||||
const timeline = db.getBandwidthTimeline(1, req.user?.site_uuid);
|
||||
const stats = db.getStats(req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
const timeline = db.getBandwidthTimeline(1, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
const latest = timeline[0] ?? {};
|
||||
|
||||
res.json({
|
||||
@@ -27,54 +27,54 @@ router.get('/summary', (req, res) => {
|
||||
// GET /api/dashboard/apps — top aplikasi
|
||||
router.get('/apps', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 10);
|
||||
const data = db.getLatestBandwidthApps(limit, req.user?.site_uuid);
|
||||
const data = db.getLatestBandwidthApps(limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
res.json({ ok: true, data });
|
||||
});
|
||||
|
||||
// GET /api/dashboard/devices — daftar device
|
||||
router.get('/devices', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
const data = db.getLatestDevices(limit, req.user?.site_uuid);
|
||||
const data = db.getLatestDevices(limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
res.json({ ok: true, data });
|
||||
});
|
||||
|
||||
// GET /api/dashboard/flows — flow aktif
|
||||
router.get('/flows', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
const data = db.getLatestFlows(limit, req.user?.site_uuid);
|
||||
const data = db.getLatestFlows(limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
res.json({ ok: true, data });
|
||||
});
|
||||
|
||||
// GET /api/dashboard/threats — ancaman keamanan
|
||||
router.get('/threats', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 20);
|
||||
const data = db.getLatestThreats(limit, req.user?.site_uuid);
|
||||
const data = db.getLatestThreats(limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
res.json({ ok: true, data });
|
||||
});
|
||||
|
||||
// GET /api/dashboard/protocols — top protokol
|
||||
router.get('/protocols', (req, res) => {
|
||||
const data = db.getLatestProtocols(20, req.user?.site_uuid);
|
||||
const data = db.getLatestProtocols(20, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
res.json({ ok: true, data });
|
||||
});
|
||||
|
||||
// GET /api/dashboard/countries — top negara
|
||||
router.get('/countries', (req, res) => {
|
||||
const data = db.getLatestCountries(15, req.user?.site_uuid);
|
||||
const data = db.getLatestCountries(15, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
res.json({ ok: true, data });
|
||||
});
|
||||
|
||||
// GET /api/dashboard/dns — top DNS queries
|
||||
router.get('/dns', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 20);
|
||||
const data = db.getLatestDNS(limit, req.user?.site_uuid);
|
||||
const data = db.getLatestDNS(limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
res.json({ ok: true, data });
|
||||
});
|
||||
|
||||
// GET /api/dashboard/events — events terbaru
|
||||
router.get('/events', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 20);
|
||||
const rawData = db.getLatestEvents(limit, req.user?.site_uuid);
|
||||
const rawData = db.getLatestEvents(limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
const mappedData = rawData.map(r => ({
|
||||
id: r.id,
|
||||
event_id: r.event_id,
|
||||
@@ -90,7 +90,7 @@ router.get('/events', (req, res) => {
|
||||
// GET /api/dashboard/timeline — bandwidth timeline (grafik)
|
||||
router.get('/timeline', (req, res) => {
|
||||
const points = parseInt(req.query.points ?? 60);
|
||||
const data = db.getBandwidthTimeline(points, req.user?.site_uuid);
|
||||
const data = db.getBandwidthTimeline(points, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null);
|
||||
res.json({ ok: true, data });
|
||||
});
|
||||
|
||||
@@ -102,67 +102,67 @@ router.post('/refresh', async (req, res) => {
|
||||
|
||||
// ─── ROUTES FITUR BARU 1-11 ───────────────────────────────────────────────────
|
||||
router.get('/app-categories', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('app_categories', 'download', 15, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('app_categories', 'download', 15, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/continents', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('continents', 'download', 10, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('continents', 'download', 10, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/regions', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('regions', 'download', 20, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('regions', 'download', 20, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/cities', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('cities', 'download', 20, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('cities', 'download', 20, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/vlans', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('vlans', 'download', 20, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('vlans', 'download', 20, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/interfaces', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('interfaces', 'download', 20, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('interfaces', 'download', 20, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/flow-types', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('flow_types', 'download', 10, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('flow_types', 'download', 10, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/flow-origins', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('flow_origins', 'download', 10, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('flow_origins', 'download', 10, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/ip-versions', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('ip_versions', 'download', 5, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('ip_versions', 'download', 5, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/remote-ips', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 20);
|
||||
res.json({ ok: true, data: db.getLatest('remote_ips', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('remote_ips', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
router.get('/mac-bandwidth', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
res.json({ ok: true, data: db.getLatest('mac_bandwidth', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('mac_bandwidth', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// ─── FIX: ROUTES YANG SEBELUMNYA HILANG ──────────────────────────────────────
|
||||
|
||||
// TLS Versions
|
||||
router.get('/tls-versions', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('tls_versions', 'download', 10, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('tls_versions', 'download', 10, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// TLS Ciphers
|
||||
router.get('/tls-ciphers', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('tls_ciphers', 'download', 15, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('tls_ciphers', 'download', 15, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// TLS Security Level
|
||||
router.get('/tls-security', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('tls_security', 'download', 10, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('tls_security', 'download', 10, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// NetBIOS Hostnames (Windows devices)
|
||||
router.get('/netbios', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 30);
|
||||
res.json({ ok: true, data: db.getLatest('netbios_hostnames', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('netbios_hostnames', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// Discovery OS (sistem operasi yang terdeteksi)
|
||||
router.get('/discovery-os', (req, res) => {
|
||||
res.json({ ok: true, data: db.getLatest('discovery_os', 'download', 20, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('discovery_os', 'download', 20, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// ─── ROUTES DPI 12-21 ─────────────────────────────────────────────────────────
|
||||
@@ -170,110 +170,110 @@ router.get('/discovery-os', (req, res) => {
|
||||
// 12. DHCP Class Fingerprint
|
||||
router.get('/dhcp-fingerprints', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 30);
|
||||
res.json({ ok: true, data: db.getLatest('dhcp_fingerprints', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('dhcp_fingerprints', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 13. HTTP User-Agent
|
||||
router.get('/http-user-agents', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 30);
|
||||
res.json({ ok: true, data: db.getLatest('http_user_agents', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('http_user_agents', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 14. HTTPS SNI Hostname
|
||||
router.get('/sni-hostnames', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 30);
|
||||
res.json({ ok: true, data: db.getLatest('sni_hostnames', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('sni_hostnames', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 15. SSL Server Common Name
|
||||
router.get('/ssl-server-cn', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 30);
|
||||
res.json({ ok: true, data: db.getLatest('ssl_server_cn', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('ssl_server_cn', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 17. QUIC Hostname
|
||||
router.get('/quic-hostnames', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 30);
|
||||
res.json({ ok: true, data: db.getLatest('quic_hostnames', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('quic_hostnames', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 18. BitTorrent Info Hash
|
||||
router.get('/bittorrent-hashes', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 30);
|
||||
res.json({ ok: true, data: db.getLatest('bittorrent_hashes', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('bittorrent_hashes', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 19. SSH Version
|
||||
router.get('/ssh-versions', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 20);
|
||||
res.json({ ok: true, data: db.getLatest('ssh_versions', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('ssh_versions', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 21. mDNS Hostname (Chromecast, Apple TV, etc.)
|
||||
router.get('/mdns-hostnames', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 30);
|
||||
res.json({ ok: true, data: db.getLatest('mdns_hostnames', 'download', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getLatest('mdns_hostnames', 'download', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// ─── INTELLIGENCE ROUTES 22-30 ────────────────────────────────────────────────
|
||||
|
||||
// Stats ringkasan semua intelligence (untuk badge count di tab)
|
||||
router.get('/intelligence/stats', (req, res) => {
|
||||
res.json({ ok: true, data: db.getIntelStats(req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelStats(req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 22. Cryptocurrency Mining
|
||||
router.get('/intelligence/crypto-mining', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_crypto_mining', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_crypto_mining', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 23. Device Discovery
|
||||
router.get('/intelligence/device-discovery', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 100);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_device_discovery', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_device_discovery', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 24. Encryption Audit
|
||||
router.get('/intelligence/encryption-audit', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_encryption_audit', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_encryption_audit', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 25. Insecure Protocols
|
||||
router.get('/intelligence/insecure-protocols', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_insecure_protocols', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_insecure_protocols', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 26. IP Reputation
|
||||
router.get('/intelligence/ip-reputation', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_ip_reputation', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_ip_reputation', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 27. Server Discovery
|
||||
router.get('/intelligence/server-discovery', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 100);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_server_discovery', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_server_discovery', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 28. Tor Detection
|
||||
router.get('/intelligence/tor', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_tor_detection', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_tor_detection', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 29. Unencrypted Passwords
|
||||
router.get('/intelligence/unencrypted-passwords', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_unencrypted_passwords', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_unencrypted_passwords', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// 30. VPN Detection
|
||||
router.get('/intelligence/vpn', (req, res) => {
|
||||
const limit = parseInt(req.query.limit ?? 50);
|
||||
res.json({ ok: true, data: db.getIntelData('intel_vpn_detection', limit, req.user?.site_uuid) });
|
||||
res.json({ ok: true, data: db.getIntelData('intel_vpn_detection', limit, req.user?.site_uuid, req.user?.role === 'AGENT_VIEWER' ? req.user?.agent_uuid : null) });
|
||||
});
|
||||
|
||||
// ─── LOOKUP ROUTES ────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in new issue
Block a user