feat: complete multi-user RBAC integration, login system, and fix backend API crashing
This commit is contained in:
1 parent
4aa12511e8
commit
72ded25e4d
31 files changed
+954
-411
No files matched your search
+334
-187
File diff suppressed because it is too large.
Load diff
@@ -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
@@ -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
@@ -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
@@ -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) => {
|
||||
|
||||
Reference in new issue
Block a user