feat: complete multi-user RBAC integration, login system, and fix backend API crashing

This commit is contained in:
Rafif-Riqullah-Siregar committed 2026-07-01 11:47:17 +07:00
1 parent 4aa12511e8
commit 72ded25e4d
31 files changed
+954 -411

No files matched your search

+334 -187
View File
File diff suppressed because it is too large. Load diff
+64
View File
@@ -0,0 +1,64 @@
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { getUserByUsername } = require('../database');
const router = express.Router();
const JWT_SECRET = process.env.JWT_SECRET || 'super-secret-backone-key';
router.post('/login', (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).json({ error: 'Username and password are required' });
}
const user = getUserByUsername(username);
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const isValid = bcrypt.compareSync(password, user.password_hash);
if (!isValid) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = jwt.sign(
{ id: user.id, username: user.username, role: user.role, site_uuid: user.site_uuid },
JWT_SECRET,
{ expiresIn: '1d' }
);
// Set HttpOnly cookie
res.cookie('token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 24 * 60 * 60 * 1000 // 1 day
});
res.json({
message: 'Login successful',
user: { id: user.id, username: user.username, role: user.role, site_uuid: user.site_uuid }
});
});
router.get('/me', (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);
res.json({ user: decoded });
} catch (err) {
res.status(401).json({ error: 'Invalid token' });
}
});
router.post('/logout', (req, res) => {
res.clearCookie('token');
res.json({ message: 'Logged out successfully' });
});
module.exports = router;
+45 -45
View File
@@ -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();
const timeline = db.getBandwidthTimeline(1);
const stats = db.getStats(req.user?.site_uuid);
const timeline = db.getBandwidthTimeline(1, req.user?.site_uuid);
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);
const data = db.getLatestBandwidthApps(limit, req.user?.site_uuid);
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);
const data = db.getLatestDevices(limit, req.user?.site_uuid);
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);
const data = db.getLatestFlows(limit, req.user?.site_uuid);
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);
const data = db.getLatestThreats(limit, req.user?.site_uuid);
res.json({ ok: true, data });
});
// GET /api/dashboard/protocols — top protokol
router.get('/protocols', (req, res) => {
const data = db.getLatestProtocols();
const data = db.getLatestProtocols(20, req.user?.site_uuid);
res.json({ ok: true, data });
});
// GET /api/dashboard/countries — top negara
router.get('/countries', (req, res) => {
const data = db.getLatestCountries();
const data = db.getLatestCountries(15, req.user?.site_uuid);
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);
const data = db.getLatestDNS(limit, req.user?.site_uuid);
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);
const rawData = db.getLatestEvents(limit, req.user?.site_uuid);
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);
const data = db.getBandwidthTimeline(points, req.user?.site_uuid);
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) });
res.json({ ok: true, data: db.getLatest('app_categories', 'download', 15, req.user?.site_uuid) });
});
router.get('/continents', (req, res) => {
res.json({ ok: true, data: db.getLatest('continents', 'download', 10) });
res.json({ ok: true, data: db.getLatest('continents', 'download', 10, req.user?.site_uuid) });
});
router.get('/regions', (req, res) => {
res.json({ ok: true, data: db.getLatest('regions', 'download', 20) });
res.json({ ok: true, data: db.getLatest('regions', 'download', 20, req.user?.site_uuid) });
});
router.get('/cities', (req, res) => {
res.json({ ok: true, data: db.getLatest('cities', 'download', 20) });
res.json({ ok: true, data: db.getLatest('cities', 'download', 20, req.user?.site_uuid) });
});
router.get('/vlans', (req, res) => {
res.json({ ok: true, data: db.getLatest('vlans', 'download', 20) });
res.json({ ok: true, data: db.getLatest('vlans', 'download', 20, req.user?.site_uuid) });
});
router.get('/interfaces', (req, res) => {
res.json({ ok: true, data: db.getLatest('interfaces', 'download', 20) });
res.json({ ok: true, data: db.getLatest('interfaces', 'download', 20, req.user?.site_uuid) });
});
router.get('/flow-types', (req, res) => {
res.json({ ok: true, data: db.getLatest('flow_types', 'download', 10) });
res.json({ ok: true, data: db.getLatest('flow_types', 'download', 10, req.user?.site_uuid) });
});
router.get('/flow-origins', (req, res) => {
res.json({ ok: true, data: db.getLatest('flow_origins', 'download', 10) });
res.json({ ok: true, data: db.getLatest('flow_origins', 'download', 10, req.user?.site_uuid) });
});
router.get('/ip-versions', (req, res) => {
res.json({ ok: true, data: db.getLatest('ip_versions', 'download', 5) });
res.json({ ok: true, data: db.getLatest('ip_versions', 'download', 5, req.user?.site_uuid) });
});
router.get('/remote-ips', (req, res) => {
const limit = parseInt(req.query.limit ?? 20);
res.json({ ok: true, data: db.getLatest('remote_ips', 'download', limit) });
res.json({ ok: true, data: db.getLatest('remote_ips', 'download', limit, req.user?.site_uuid) });
});
router.get('/mac-bandwidth', (req, res) => {
const limit = parseInt(req.query.limit ?? 50);
res.json({ ok: true, data: db.getLatest('mac_bandwidth', 'download', limit) });
res.json({ ok: true, data: db.getLatest('mac_bandwidth', 'download', limit, req.user?.site_uuid) });
});
// ─── FIX: ROUTES YANG SEBELUMNYA HILANG ──────────────────────────────────────
// TLS Versions
router.get('/tls-versions', (req, res) => {
res.json({ ok: true, data: db.getLatest('tls_versions', 'download', 10) });
res.json({ ok: true, data: db.getLatest('tls_versions', 'download', 10, req.user?.site_uuid) });
});
// TLS Ciphers
router.get('/tls-ciphers', (req, res) => {
res.json({ ok: true, data: db.getLatest('tls_ciphers', 'download', 15) });
res.json({ ok: true, data: db.getLatest('tls_ciphers', 'download', 15, req.user?.site_uuid) });
});
// TLS Security Level
router.get('/tls-security', (req, res) => {
res.json({ ok: true, data: db.getLatest('tls_security', 'download', 10) });
res.json({ ok: true, data: db.getLatest('tls_security', 'download', 10, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getLatest('netbios_hostnames', 'download', limit, req.user?.site_uuid) });
});
// Discovery OS (sistem operasi yang terdeteksi)
router.get('/discovery-os', (req, res) => {
res.json({ ok: true, data: db.getLatest('discovery_os', 'download', 20) });
res.json({ ok: true, data: db.getLatest('discovery_os', 'download', 20, req.user?.site_uuid) });
});
// ─── 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) });
res.json({ ok: true, data: db.getLatest('dhcp_fingerprints', 'download', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getLatest('http_user_agents', 'download', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getLatest('sni_hostnames', 'download', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getLatest('ssl_server_cn', 'download', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getLatest('quic_hostnames', 'download', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getLatest('bittorrent_hashes', 'download', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getLatest('ssh_versions', 'download', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getLatest('mdns_hostnames', 'download', limit, req.user?.site_uuid) });
});
// ─── 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() });
res.json({ ok: true, data: db.getIntelStats(req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_crypto_mining', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_device_discovery', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_encryption_audit', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_insecure_protocols', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_ip_reputation', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_server_discovery', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_tor_detection', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_unencrypted_passwords', limit, req.user?.site_uuid) });
});
// 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) });
res.json({ ok: true, data: db.getIntelData('intel_vpn_detection', limit, req.user?.site_uuid) });
});
// ─── LOOKUP ROUTES ────────────────────────────────────────────────────────────
+44 -43
View File
@@ -2,6 +2,7 @@
const cron = require('node-cron');
const netify = require('./netify');
const db = require('./database');
const SITE_UUID = process.env.NETIFY_SITE_UUID || 'dummy_site_uuid';
let isRunning = false;
@@ -18,7 +19,7 @@ async function runPoll() {
// 1. Top Aplikasi
const apps = await netify.fetchTopApps(1440, 20);
if (apps && Array.isArray(apps)) {
db.insertBandwidthApps(apps, fetchedAt);
db.insertBandwidthApps(apps, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK Apps : ${apps.length} baris`);
} else {
console.log(`[Scheduler] -- Apps : tidak ada data`);
@@ -27,7 +28,7 @@ async function runPoll() {
// 2. Top Devices — pakai fetchDiscoveredDevices yg sudah dinormalisasi
const devices = await netify.fetchDiscoveredDevices(1440, 200);
if (devices && Array.isArray(devices)) {
db.insertDevices(devices, fetchedAt);
db.insertDevices(devices, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK Devices : ${devices.length} baris`);
} else {
console.log(`[Scheduler] -- Devices : tidak ada data`);
@@ -36,7 +37,7 @@ async function runPoll() {
// 3. Top Protokol
const protocols = await netify.fetchTopProtocols(1440, 20);
if (protocols && Array.isArray(protocols)) {
db.insertProtocols(protocols, fetchedAt);
db.insertProtocols(protocols, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK Protocols : ${protocols.length} baris`);
} else {
console.log(`[Scheduler] -- Protocols : tidak ada data`);
@@ -45,7 +46,7 @@ async function runPoll() {
// 4. Top Negara
const countries = await netify.fetchTopCountries(1440, 15);
if (countries && Array.isArray(countries)) {
db.insertCountries(countries, fetchedAt);
db.insertCountries(countries, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK Countries : ${countries.length} baris`);
} else {
console.log(`[Scheduler] -- Countries : tidak ada data`);
@@ -54,7 +55,7 @@ async function runPoll() {
// 5. Top Domain/DNS
const domains = await netify.fetchTopDomains(1440, 20);
if (domains && Array.isArray(domains)) {
db.insertDNS(domains, fetchedAt);
db.insertDNS(domains, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK DNS : ${domains.length} baris`);
} else {
console.log(`[Scheduler] -- DNS : tidak ada data`);
@@ -63,7 +64,7 @@ async function runPoll() {
// 6. Flows — pakai local_ip sebagai proxy
const flows = await netify.fetchFlows(200);
if (flows && Array.isArray(flows)) {
db.insertFlows(flows, fetchedAt);
db.insertFlows(flows, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK Flows : ${flows.length} baris`);
} else {
console.log(`[Scheduler] -- Flows : tidak ada data`);
@@ -72,7 +73,7 @@ async function runPoll() {
// 7. Threats — dari Events Status
const threats = await netify.fetchCyberThreats(1440, 50);
if (threats && Array.isArray(threats)) {
db.insertThreats(threats, fetchedAt);
db.insertThreats(threats, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK Threats : ${threats.length} baris`);
} else {
console.log(`[Scheduler] -- Threats : tidak ada data`);
@@ -81,7 +82,7 @@ async function runPoll() {
// 8. Events Log
const events = await netify.fetchEvents(50);
if (events && Array.isArray(events)) {
db.insertEvents(events, fetchedAt);
db.insertEvents(events, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK Events : ${events.length} baris`);
} else {
console.log(`[Scheduler] -- Events : tidak ada data`);
@@ -89,180 +90,180 @@ async function runPoll() {
// 10. App Categories
const appCats = await netify.fetchTopAppCategories(1440, 15);
if (appCats?.length) { db.insertAppCategories(appCats, fetchedAt); console.log(`[Scheduler] OK AppCats : ${appCats.length} baris`); }
if (appCats?.length) { db.insertAppCategories(appCats, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK AppCats : ${appCats.length} baris`); }
else console.log(`[Scheduler] -- AppCats : tidak ada data`);
// 11. Continents
const continents = await netify.fetchTopContinents(1440, 10);
if (continents?.length) { db.insertContinents(continents, fetchedAt); console.log(`[Scheduler] OK Continents : ${continents.length} baris`); }
if (continents?.length) { db.insertContinents(continents, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK Continents : ${continents.length} baris`); }
else console.log(`[Scheduler] -- Continents : tidak ada data`);
// 12. Regions
const regions = await netify.fetchTopRegions(1440, 20);
if (regions?.length) { db.insertRegions(regions, fetchedAt); console.log(`[Scheduler] OK Regions : ${regions.length} baris`); }
if (regions?.length) { db.insertRegions(regions, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK Regions : ${regions.length} baris`); }
else console.log(`[Scheduler] -- Regions : tidak ada data`);
// 13. Cities
const cities = await netify.fetchTopCities(1440, 20);
if (cities?.length) { db.insertCities(cities, fetchedAt); console.log(`[Scheduler] OK Cities : ${cities.length} baris`); }
if (cities?.length) { db.insertCities(cities, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK Cities : ${cities.length} baris`); }
else console.log(`[Scheduler] -- Cities : tidak ada data`);
// 14. VLANs
const vlans = await netify.fetchTopVLANs(1440, 20);
if (vlans?.length) { db.insertVLANs(vlans, fetchedAt); console.log(`[Scheduler] OK VLANs : ${vlans.length} baris`); }
if (vlans?.length) { db.insertVLANs(vlans, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK VLANs : ${vlans.length} baris`); }
else console.log(`[Scheduler] -- VLANs : tidak ada data`);
// 15. Interfaces
const ifaces = await netify.fetchTopInterfaces(1440, 20);
if (ifaces?.length) { db.insertInterfaces(ifaces, fetchedAt); console.log(`[Scheduler] OK Interfaces : ${ifaces.length} baris`); }
if (ifaces?.length) { db.insertInterfaces(ifaces, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK Interfaces : ${ifaces.length} baris`); }
else console.log(`[Scheduler] -- Interfaces : tidak ada data`);
// 16. Flow Types
const flowTypes = await netify.fetchTopFlowTypes(1440, 10);
if (flowTypes?.length) { db.insertFlowTypes(flowTypes, fetchedAt); console.log(`[Scheduler] OK FlowTypes : ${flowTypes.length} baris`); }
if (flowTypes?.length) { db.insertFlowTypes(flowTypes, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK FlowTypes : ${flowTypes.length} baris`); }
else console.log(`[Scheduler] -- FlowTypes : tidak ada data`);
// 17. Flow Origins
const flowOrigins = await netify.fetchTopFlowOrigins(1440, 10);
if (flowOrigins?.length) { db.insertFlowOrigins(flowOrigins, fetchedAt); console.log(`[Scheduler] OK FlowOrigin : ${flowOrigins.length} baris`); }
if (flowOrigins?.length) { db.insertFlowOrigins(flowOrigins, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK FlowOrigin : ${flowOrigins.length} baris`); }
else console.log(`[Scheduler] -- FlowOrigin : tidak ada data`);
// 18. IP Versions
const ipVersions = await netify.fetchTopIPVersions(1440, 5);
if (ipVersions?.length) { db.insertIPVersions(ipVersions, fetchedAt); console.log(`[Scheduler] OK IPVersions : ${ipVersions.length} baris`); }
if (ipVersions?.length) { db.insertIPVersions(ipVersions, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK IPVersions : ${ipVersions.length} baris`); }
else console.log(`[Scheduler] -- IPVersions : tidak ada data`);
// 19. Remote IPs
const remoteIPs = await netify.fetchTopRemoteIPs(1440, 20);
if (remoteIPs?.length) { db.insertRemoteIPs(remoteIPs, fetchedAt); console.log(`[Scheduler] OK RemoteIPs : ${remoteIPs.length} baris`); }
if (remoteIPs?.length) { db.insertRemoteIPs(remoteIPs, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK RemoteIPs : ${remoteIPs.length} baris`); }
else console.log(`[Scheduler] -- RemoteIPs : tidak ada data`);
// 20. MAC Bandwidth
const macBW = await netify.fetchTopLocalMACs(1440, 50);
if (macBW?.length) { db.insertMACBandwidth(macBW, fetchedAt); console.log(`[Scheduler] OK MACBandwdh : ${macBW.length} baris`); }
if (macBW?.length) { db.insertMACBandwidth(macBW, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK MACBandwdh : ${macBW.length} baris`); }
else console.log(`[Scheduler] -- MACBandwdh : tidak ada data`);
// 9. Bandwidth Timeline
const summary = await netify.fetchBandwidthSummary(1440);
const devCount = devices?.length ?? 0;
db.insertBandwidthTimeline({ ...summary, devices: devCount }, fetchedAt);
db.insertBandwidthTimeline({ ...summary, devices: devCount }, fetchedAt, SITE_UUID);
console.log(`[Scheduler] OK Timeline : saved`);
// 21. TLS Versions
const tlsVer = await netify.fetchTLSVersions(1440, 10);
if (tlsVer?.length) { db.insertTLSVersions(tlsVer, fetchedAt); console.log(`[Scheduler] OK TLS Ver : ${tlsVer.length} baris`); }
if (tlsVer?.length) { db.insertTLSVersions(tlsVer, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK TLS Ver : ${tlsVer.length} baris`); }
else console.log(`[Scheduler] -- TLS Ver : tidak ada data`);
// 22. TLS Ciphers
const tlsCipher = await netify.fetchTLSCiphers(1440, 15);
if (tlsCipher?.length) { db.insertTLSCiphers(tlsCipher, fetchedAt); console.log(`[Scheduler] OK TLS Cipher : ${tlsCipher.length} baris`); }
if (tlsCipher?.length) { db.insertTLSCiphers(tlsCipher, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK TLS Cipher : ${tlsCipher.length} baris`); }
else console.log(`[Scheduler] -- TLS Cipher : tidak ada data`);
// 23. TLS Security
const tlsSec = await netify.fetchTLSSecurity(1440, 10);
if (tlsSec?.length) { db.insertTLSSecurity(tlsSec, fetchedAt); console.log(`[Scheduler] OK TLS Sec : ${tlsSec.length} baris`); }
if (tlsSec?.length) { db.insertTLSSecurity(tlsSec, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK TLS Sec : ${tlsSec.length} baris`); }
else console.log(`[Scheduler] -- TLS Sec : tidak ada data`);
// 24. NetBIOS Hostnames
const netbios = await netify.fetchNetBIOSHostnames(1440, 30);
if (netbios?.length) { db.insertNetBIOSHostnames(netbios, fetchedAt); console.log(`[Scheduler] OK NetBIOS : ${netbios.length} baris`); }
if (netbios?.length) { db.insertNetBIOSHostnames(netbios, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK NetBIOS : ${netbios.length} baris`); }
else console.log(`[Scheduler] -- NetBIOS : tidak ada data`);
// 25. Discovery OS (standalone — OS yang terdeteksi di jaringan)
const discOs = await netify.fetchTopDiscoveryOS(1440, 20);
if (discOs?.length) { db.insertDiscoveryOS(discOs, fetchedAt); console.log(`[Scheduler] OK DiscOS : ${discOs.length} baris`); }
if (discOs?.length) { db.insertDiscoveryOS(discOs, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK DiscOS : ${discOs.length} baris`); }
else console.log(`[Scheduler] -- DiscOS : tidak ada data`);
// 26. DHCP Class Fingerprint
const dhcpFp = await netify.fetchDHCPClassFingerprints(1440, 30);
if (dhcpFp?.length) { db.insertDHCPFingerprints(dhcpFp, fetchedAt); console.log(`[Scheduler] OK DHCP FP : ${dhcpFp.length} baris`); }
if (dhcpFp?.length) { db.insertDHCPFingerprints(dhcpFp, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK DHCP FP : ${dhcpFp.length} baris`); }
else console.log(`[Scheduler] -- DHCP FP : tidak ada data`);
// 27. HTTP User-Agent
const userAgents = await netify.fetchHTTPUserAgents(1440, 30);
if (userAgents?.length) { db.insertHTTPUserAgents(userAgents, fetchedAt); console.log(`[Scheduler] OK UserAgent : ${userAgents.length} baris`); }
if (userAgents?.length) { db.insertHTTPUserAgents(userAgents, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK UserAgent : ${userAgents.length} baris`); }
else console.log(`[Scheduler] -- UserAgent : tidak ada data`);
// 28. HTTPS SNI Hostname
const sniHosts = await netify.fetchSNIHostnames(1440, 30);
if (sniHosts?.length) { db.insertSNIHostnames(sniHosts, fetchedAt); console.log(`[Scheduler] OK SNI Host : ${sniHosts.length} baris`); }
if (sniHosts?.length) { db.insertSNIHostnames(sniHosts, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK SNI Host : ${sniHosts.length} baris`); }
else console.log(`[Scheduler] -- SNI Host : tidak ada data`);
// 29. SSL Server Common Name
const sslCN = await netify.fetchSSLServerCN(1440, 30);
if (sslCN?.length) { db.insertSSLServerCN(sslCN, fetchedAt); console.log(`[Scheduler] OK SSL CN : ${sslCN.length} baris`); }
if (sslCN?.length) { db.insertSSLServerCN(sslCN, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK SSL CN : ${sslCN.length} baris`); }
else console.log(`[Scheduler] -- SSL CN : tidak ada data`);
// 30. QUIC Hostname
const quicHosts = await netify.fetchQUICHostnames(1440, 30);
if (quicHosts?.length) { db.insertQUICHostnames(quicHosts, fetchedAt); console.log(`[Scheduler] OK QUIC Host : ${quicHosts.length} baris`); }
if (quicHosts?.length) { db.insertQUICHostnames(quicHosts, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK QUIC Host : ${quicHosts.length} baris`); }
else console.log(`[Scheduler] -- QUIC Host : tidak ada data`);
// 31. BitTorrent Info Hash
const btHashes = await netify.fetchBitTorrentInfoHashes(1440, 30);
if (btHashes?.length) { db.insertBitTorrentHashes(btHashes, fetchedAt); console.log(`[Scheduler] OK BT Hash : ${btHashes.length} baris`); }
if (btHashes?.length) { db.insertBitTorrentHashes(btHashes, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK BT Hash : ${btHashes.length} baris`); }
else console.log(`[Scheduler] -- BT Hash : tidak ada data`);
// 32. SSH Client (field: ssh_client)
const sshClient = await netify.fetchSSHClients(1440, 20);
if (sshClient?.length) { db.insertSSHVersions(sshClient, fetchedAt); console.log(`[Scheduler] OK SSH Client : ${sshClient.length} baris`); }
if (sshClient?.length) { db.insertSSHVersions(sshClient, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK SSH Client : ${sshClient.length} baris`); }
else console.log(`[Scheduler] -- SSH Client : tidak ada data`);
// 32b. SSH Server (field: ssh_server)
const sshServer = await netify.fetchSSHServers(1440, 20);
if (sshServer?.length) { db.insertSSHVersions(sshServer, fetchedAt); console.log(`[Scheduler] OK SSH Server : ${sshServer.length} baris`); }
if (sshServer?.length) { db.insertSSHVersions(sshServer, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK SSH Server : ${sshServer.length} baris`); }
else console.log(`[Scheduler] -- SSH Server : tidak ada data`);
// 33. mDNS Hostname (Chromecast, Apple TV, etc.)
const mdnsHosts = await netify.fetchMDNSHostnames(1440, 30);
if (mdnsHosts?.length) { db.insertMDNSHostnames(mdnsHosts, fetchedAt); console.log(`[Scheduler] OK mDNS Host : ${mdnsHosts.length} baris`); }
if (mdnsHosts?.length) { db.insertMDNSHostnames(mdnsHosts, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK mDNS Host : ${mdnsHosts.length} baris`); }
else console.log(`[Scheduler] -- mDNS Host : tidak ada data`);
// ─── INTELLIGENCE 22-30 (derive dari data yang tersedia) ─────────────────
// 34. Cryptocurrency Mining (derive dari apps + flows ke port mining)
const cryptoMining = await netify.fetchCryptoMining(50);
if (cryptoMining?.length) { db.insertCryptoMining(cryptoMining, fetchedAt); console.log(`[Scheduler] OK CryptoMine : ${cryptoMining.length} baris`); }
if (cryptoMining?.length) { db.insertCryptoMining(cryptoMining, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK CryptoMine : ${cryptoMining.length} baris`); }
else console.log(`[Scheduler] -- CryptoMine : tidak ada data`);
// 35. Device Discovery (derive dari flows + bandwidth per-IP)
const devDisc = await netify.fetchDeviceDiscovery(100);
if (devDisc?.length) { db.insertDeviceDiscovery(devDisc, fetchedAt); console.log(`[Scheduler] OK DevDisc : ${devDisc.length} baris`); }
if (devDisc?.length) { db.insertDeviceDiscovery(devDisc, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK DevDisc : ${devDisc.length} baris`); }
else console.log(`[Scheduler] -- DevDisc : tidak ada data`);
// 36. Encryption Audit (derive dari flows per-IP: port encrypted vs plain)
const encAudit = await netify.fetchEncryptionAudit(50);
if (encAudit?.length) { db.insertEncryptionAudit(encAudit, fetchedAt); console.log(`[Scheduler] OK EncAudit : ${encAudit.length} baris`); }
if (encAudit?.length) { db.insertEncryptionAudit(encAudit, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK EncAudit : ${encAudit.length} baris`); }
else console.log(`[Scheduler] -- EncAudit : tidak ada data`);
// 37. Insecure Protocols (derive dari top protocols)
const insecProto = await netify.fetchInsecureProtocols(1440, 50);
if (insecProto?.length) { db.insertInsecureProtocols(insecProto, fetchedAt); console.log(`[Scheduler] OK InsecProto : ${insecProto.length} baris`); }
if (insecProto?.length) { db.insertInsecureProtocols(insecProto, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK InsecProto : ${insecProto.length} baris`); }
else console.log(`[Scheduler] -- InsecProto : tidak ada data`);
// 38. IP Reputation (derive dari top remote_ip + high-risk countries)
const ipRep = await netify.fetchIPReputation(50);
if (ipRep?.length) { db.insertIPReputation(ipRep, fetchedAt); console.log(`[Scheduler] OK IPRepute : ${ipRep.length} baris`); }
if (ipRep?.length) { db.insertIPReputation(ipRep, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK IPRepute : ${ipRep.length} baris`); }
else console.log(`[Scheduler] -- IPRepute : tidak ada data`);
// 39. Server Discovery (derive dari flows ke port server well-known)
const srvDisc = await netify.fetchServerDiscovery(100);
if (srvDisc?.length) { db.insertServerDiscovery(srvDisc, fetchedAt); console.log(`[Scheduler] OK SrvDisc : ${srvDisc.length} baris`); }
if (srvDisc?.length) { db.insertServerDiscovery(srvDisc, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK SrvDisc : ${srvDisc.length} baris`); }
else console.log(`[Scheduler] -- SrvDisc : tidak ada data`);
// 40. Tor Detection (derive dari apps/hostnames mengandung "tor")
const torDet = await netify.fetchTorDetection(50);
if (torDet?.length) { db.insertTorDetection(torDet, fetchedAt); console.log(`[Scheduler] OK TorDet : ${torDet.length} baris`); }
if (torDet?.length) { db.insertTorDetection(torDet, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK TorDet : ${torDet.length} baris`); }
else console.log(`[Scheduler] -- TorDet : tidak ada data`);
// 41. Unencrypted Password (derive dari flows ke port cleartext auth)
const unencPwd = await netify.fetchUnencryptedPasswords(50);
if (unencPwd?.length) { db.insertUnencryptedPasswords(unencPwd, fetchedAt); console.log(`[Scheduler] OK UnencPwd : ${unencPwd.length} baris`); }
if (unencPwd?.length) { db.insertUnencryptedPasswords(unencPwd, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK UnencPwd : ${unencPwd.length} baris`); }
else console.log(`[Scheduler] -- UnencPwd : tidak ada data`);
// 42. VPN Detection (derive dari apps/protocols/ports VPN)
const vpnDet = await netify.fetchVPNDetection(50);
if (vpnDet?.length) { db.insertVPNDetection(vpnDet, fetchedAt); console.log(`[Scheduler] OK VPNDet : ${vpnDet.length} baris`); }
if (vpnDet?.length) { db.insertVPNDetection(vpnDet, fetchedAt, SITE_UUID); console.log(`[Scheduler] OK VPNDet : ${vpnDet.length} baris`); }
else console.log(`[Scheduler] -- VPNDet : tidak ada data`);
} catch (err) {
+21 -2
View File
@@ -3,17 +3,36 @@ const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '..', '.env.local') });
const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const jwt = require('jsonwebtoken');
const app = express();
const PORT = process.env.BACKEND_PORT || 3001;
// ── Middleware ────────────────────────────────────────────────────────────────
app.use(cors());
app.use(cors({ origin: true, credentials: true }));
app.use(express.json());
app.use(cookieParser());
// ── API Routes ────────────────────────────────────────────────────────────────
const authRoutes = require('./routes/auth');
app.use('/api/auth', authRoutes);
// Auth Middleware for Dashboard
const JWT_SECRET = process.env.JWT_SECRET || 'super-secret-backone-key';
function requireAuth(req, res, next) {
const token = req.cookies?.token;
if (!token) return res.status(401).json({ error: 'Unauthorized' });
try {
req.user = jwt.verify(token, JWT_SECRET);
next();
} catch (err) {
res.status(401).json({ error: 'Invalid token' });
}
}
const dashboardRoutes = require('./routes/dashboard');
app.use('/api/dashboard', dashboardRoutes);
app.use('/api/dashboard', requireAuth, dashboardRoutes);
// ── Health Check ──────────────────────────────────────────────────────────────
app.get('/api/health', (req, res) => {