feat(prod): deploy web dashboard, migrate mongodb configuration, resolve server components render error and fix logo static asset paths
This commit is contained in:
1 parent
4882108068
commit
b2ea883601
119 files changed
+7123
-2011
No files matched your search
@@ -0,0 +1,175 @@
|
||||
// test/agent_geolocation_test.js
|
||||
const mongoose = require('../backend/node_modules/mongoose');
|
||||
const path = require('path');
|
||||
|
||||
// Load environment variables
|
||||
require('dotenv').config({ path: path.join(__dirname, '../.env.local') });
|
||||
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
|
||||
|
||||
const { CustomAgentLocation, DeviceStat, Flow } = require('../backend/models/Schemas');
|
||||
|
||||
let testCount = 0;
|
||||
let passedCount = 0;
|
||||
|
||||
function assert(label, condition) {
|
||||
testCount++;
|
||||
if (condition) {
|
||||
console.log(` ✓ PASSED: ${label}`);
|
||||
passedCount++;
|
||||
} else {
|
||||
console.error(` ✗ FAILED: ${label}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function runTests() {
|
||||
console.log('\n=========================================');
|
||||
console.log(' RUNNING TDD TESTS FOR GEOLOCATION & FLOWS');
|
||||
console.log('=========================================\n');
|
||||
|
||||
try {
|
||||
// 1. Connect to DB
|
||||
await mongoose.connect(MONGODB_URI);
|
||||
console.log('✓ Connected to MongoDB');
|
||||
|
||||
// 2. Validate Geolocation Seeding
|
||||
const count = await CustomAgentLocation.countDocuments();
|
||||
assert('CustomAgentLocation collection should have seeded documents', count >= 3);
|
||||
|
||||
const balarajaLoc = await CustomAgentLocation.findOne({ agent_uuid: 'F6-2V-DT-8A' });
|
||||
assert('CPI Balaraja Agent location should exist', !!balarajaLoc);
|
||||
if (balarajaLoc) {
|
||||
assert('CPI Balaraja latitude matches', balarajaLoc.latitude === -6.2263304);
|
||||
assert('CPI Balaraja longitude matches', balarajaLoc.longitude === 106.4247322);
|
||||
assert('CPI Balaraja belongs to SIAB site', balarajaLoc.site_uuid === '6681452d_9cae_4ff4_8ae8_0d504774265e');
|
||||
}
|
||||
|
||||
const cibuburLoc = await CustomAgentLocation.findOne({ agent_uuid: '2F-TF-1D-GK' });
|
||||
assert('JRP Cibubur Agent location should exist', !!cibuburLoc);
|
||||
if (cibuburLoc) {
|
||||
assert('JRP Cibubur latitude matches', cibuburLoc.latitude === -6.3763318);
|
||||
assert('JRP Cibubur longitude matches', cibuburLoc.longitude === 106.8983017);
|
||||
}
|
||||
|
||||
const ifgLoc = await CustomAgentLocation.findOne({ agent_uuid: '8A-V3-PB-85' });
|
||||
assert('IFG LT.18 Agent location should exist', !!ifgLoc);
|
||||
if (ifgLoc) {
|
||||
assert('IFG LT.18 latitude matches', ifgLoc.latitude === -6.2253265);
|
||||
assert('IFG LT.18 longitude matches', ifgLoc.longitude === 106.8061484);
|
||||
}
|
||||
|
||||
// 3. Test Location Updates (Simulation of POST API)
|
||||
const testUuid = 'TEST-AGENT-UUID';
|
||||
const testSite = 'test-site-uuid';
|
||||
|
||||
// Remove if exists
|
||||
await CustomAgentLocation.deleteOne({ agent_uuid: testUuid });
|
||||
|
||||
const updated = await CustomAgentLocation.findOneAndUpdate(
|
||||
{ agent_uuid: testUuid },
|
||||
{
|
||||
agent_uuid: testUuid,
|
||||
site_uuid: testSite,
|
||||
latitude: -6.1234,
|
||||
longitude: 106.1234,
|
||||
label: 'Test Location Label'
|
||||
},
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
assert('Location upsert should return the saved document', !!updated);
|
||||
assert('Upserted latitude matches', updated.latitude === -6.1234);
|
||||
assert('Upserted longitude matches', updated.longitude === 106.1234);
|
||||
assert('Upserted label matches', updated.label === 'Test Location Label');
|
||||
|
||||
// 4. Test Location Reset (Simulation of DELETE API)
|
||||
const delRes = await CustomAgentLocation.deleteOne({ agent_uuid: testUuid });
|
||||
assert('Location delete should succeed', delRes.deletedCount > 0);
|
||||
|
||||
const checkedDel = await CustomAgentLocation.findOne({ agent_uuid: testUuid });
|
||||
assert('Location should no longer exist after delete', !checkedDel);
|
||||
|
||||
// 5. Test Inter-Agent Flow Aggregation Logic
|
||||
// Let's seed a mock device belonging to Cibubur agent and a flow from Balaraja to Cibubur's device IP.
|
||||
const mockDestIp = '192.168.99.123';
|
||||
|
||||
// Cleanup if existing
|
||||
await DeviceStat.deleteOne({ ip_address: mockDestIp });
|
||||
await Flow.deleteMany({ dst_ip: mockDestIp });
|
||||
|
||||
// Seed mock device monitored by Cibubur agent (2F-TF-1D-GK)
|
||||
await DeviceStat.create({
|
||||
timestamp: new Date(),
|
||||
ip_address: mockDestIp,
|
||||
agent_uuid: '2F-TF-1D-GK',
|
||||
site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
|
||||
mac_address: '00:11:22:33:44:55',
|
||||
});
|
||||
|
||||
// Seed mock flow from Balaraja agent (F6-2V-DT-8A) to mockDestIp
|
||||
await Flow.create({
|
||||
timestamp: new Date(),
|
||||
agent_uuid: 'F6-2V-DT-8A',
|
||||
site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
|
||||
src_ip: '192.168.10.50',
|
||||
dst_ip: mockDestIp,
|
||||
download: 15000000,
|
||||
upload: 5000000,
|
||||
});
|
||||
|
||||
// Run the aggregation logic
|
||||
const devices = await DeviceStat.find({ site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e' }).select('ip_address agent_uuid').lean();
|
||||
const deviceIpToAgent = {};
|
||||
for (const dev of devices) {
|
||||
if (dev.ip_address && dev.agent_uuid) {
|
||||
deviceIpToAgent[dev.ip_address] = dev.agent_uuid;
|
||||
}
|
||||
}
|
||||
|
||||
const flows = await Flow.find({ site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e' }).select('agent_uuid src_ip dst_ip download upload').lean();
|
||||
|
||||
const flowMap = {};
|
||||
for (const flow of flows) {
|
||||
const srcAgent = flow.agent_uuid;
|
||||
const dstAgent = deviceIpToAgent[flow.dst_ip];
|
||||
|
||||
if (srcAgent && dstAgent && srcAgent !== dstAgent) {
|
||||
const key = `${srcAgent}->${dstAgent}`;
|
||||
if (!flowMap[key]) {
|
||||
flowMap[key] = {
|
||||
source: srcAgent,
|
||||
target: dstAgent,
|
||||
bytes: 0,
|
||||
flowsCount: 0
|
||||
};
|
||||
}
|
||||
flowMap[key].bytes += ((flow.download || 0) + (flow.upload || 0));
|
||||
flowMap[key].flowsCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const result = Object.values(flowMap);
|
||||
assert('Inter-agent flows aggregation should detect flows', result.length > 0);
|
||||
|
||||
const detectedFlow = result.find(f => f.source === 'F6-2V-DT-8A' && f.target === '2F-TF-1D-GK');
|
||||
assert('Mock flow from Balaraja to Cibubur should be detected', !!detectedFlow);
|
||||
if (detectedFlow) {
|
||||
assert('Mock flow bytes matches (15MB down + 5MB up = 20MB)', detectedFlow.bytes >= 20000000);
|
||||
assert('Mock flow connection count is correct', detectedFlow.flowsCount >= 1);
|
||||
}
|
||||
|
||||
// Cleanup mock telemetry
|
||||
await DeviceStat.deleteOne({ ip_address: mockDestIp });
|
||||
await Flow.deleteMany({ dst_ip: mockDestIp });
|
||||
|
||||
console.log('\n=========================================');
|
||||
console.log(` RESULT: ${passedCount} / ${testCount} tests passed.`);
|
||||
console.log('=========================================\n');
|
||||
|
||||
await mongoose.disconnect();
|
||||
} catch (err) {
|
||||
console.error('TDD Test run error:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
runTests();
|
||||
@@ -0,0 +1,101 @@
|
||||
// test/analyze_inter_agent_flows.js — diagnostic script
|
||||
// Checks if there are real inter-agent flows in MongoDB
|
||||
|
||||
const mongoose = require('../backend/node_modules/mongoose');
|
||||
const path = require('path');
|
||||
require('dotenv').config({ path: path.join(__dirname, '../.env.local') });
|
||||
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
|
||||
const { DeviceStat, Flow } = require('../backend/models/Schemas');
|
||||
const { CustomAgentLocation } = require('../backend/models/SchemasAux');
|
||||
|
||||
async function run() {
|
||||
await mongoose.connect(MONGODB_URI);
|
||||
console.log('\n✓ Connected to MongoDB\n');
|
||||
|
||||
const SIAB_SITE = '6681452d_9cae_4ff4_8ae8_0d504774265e';
|
||||
|
||||
// 1. List registered agent coordinates
|
||||
const locations = await CustomAgentLocation.find({ site_uuid: SIAB_SITE }).lean();
|
||||
const agentUuids = locations.map(l => l.agent_uuid);
|
||||
console.log(`=== Agent Locations Registered (${locations.length}) ===`);
|
||||
for (const loc of locations) {
|
||||
console.log(` • ${loc.agent_uuid} → ${loc.label || '(no label)'} [${loc.latitude}, ${loc.longitude}]`);
|
||||
}
|
||||
|
||||
// 2. Build IP → agent_uuid map from DeviceStat
|
||||
const devices = await DeviceStat.find({ site_uuid: SIAB_SITE }).select('ip_address agent_uuid').lean();
|
||||
const ipToAgent = {};
|
||||
for (const d of devices) {
|
||||
if (d.ip_address && d.agent_uuid) ipToAgent[d.ip_address] = d.agent_uuid;
|
||||
}
|
||||
console.log(`\n=== DeviceStat Records (total ${devices.length}) ===`);
|
||||
const agentDeviceCount = {};
|
||||
for (const [ip, agent] of Object.entries(ipToAgent)) {
|
||||
agentDeviceCount[agent] = (agentDeviceCount[agent] || 0) + 1;
|
||||
}
|
||||
for (const [agent, count] of Object.entries(agentDeviceCount)) {
|
||||
console.log(` • Agent ${agent}: ${count} unique IP(s) tracked`);
|
||||
}
|
||||
|
||||
// 3. Sample flows to see dst_ip patterns
|
||||
const since24h = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
const flowCount = await Flow.countDocuments({ site_uuid: SIAB_SITE, timestamp: { $gte: since24h } });
|
||||
const flows = await Flow.find({ site_uuid: SIAB_SITE, timestamp: { $gte: since24h } })
|
||||
.select('agent_uuid src_ip dst_ip download upload app_label')
|
||||
.limit(200)
|
||||
.lean();
|
||||
|
||||
console.log(`\n=== Flows in Last 24h: ${flowCount} total (inspecting up to 200) ===`);
|
||||
|
||||
const interAgentFlowMap = {};
|
||||
let matchCount = 0;
|
||||
|
||||
for (const flow of flows) {
|
||||
const srcAgent = flow.agent_uuid;
|
||||
const dstAgent = ipToAgent[flow.dst_ip];
|
||||
if (srcAgent && dstAgent && srcAgent !== dstAgent) {
|
||||
matchCount++;
|
||||
const key = `${srcAgent} → ${dstAgent}`;
|
||||
if (!interAgentFlowMap[key]) {
|
||||
interAgentFlowMap[key] = { bytes: 0, count: 0, examples: [] };
|
||||
}
|
||||
interAgentFlowMap[key].bytes += (flow.download || 0) + (flow.upload || 0);
|
||||
interAgentFlowMap[key].count++;
|
||||
if (interAgentFlowMap[key].examples.length < 2) {
|
||||
interAgentFlowMap[key].examples.push({ src: flow.src_ip, dst: flow.dst_ip, app: flow.app_label });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n=== Inter-Agent Flows Detected: ${matchCount} (from ${flows.length} sampled) ===`);
|
||||
if (Object.keys(interAgentFlowMap).length > 0) {
|
||||
for (const [pair, data] of Object.entries(interAgentFlowMap)) {
|
||||
const mb = (data.bytes / 1024 / 1024).toFixed(2);
|
||||
console.log(` ✓ ${pair} — ${data.count} flows, ${mb} MB`);
|
||||
for (const ex of data.examples) {
|
||||
console.log(` Example: ${ex.src} → ${ex.dst} (${ex.app || 'Unclassified'})`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(' ✗ No inter-agent flows detected in sampled data.');
|
||||
console.log('\n — Checking sample of dst_ip values that appear in flows...');
|
||||
const dstIps = [...new Set(flows.map(f => f.dst_ip).filter(Boolean))].slice(0, 10);
|
||||
console.log(' dst_ip samples:', dstIps);
|
||||
const matched = dstIps.filter(ip => ipToAgent[ip]);
|
||||
console.log(' dst_ip matched to agents:', matched.map(ip => `${ip} → ${ipToAgent[ip]}`));
|
||||
}
|
||||
|
||||
// 4. Check if any flows have dst_ip in the devicestats table at all
|
||||
const allDstIps = [...new Set(flows.map(f => f.dst_ip).filter(Boolean))];
|
||||
let trackedCount = 0;
|
||||
for (const ip of allDstIps) {
|
||||
if (ipToAgent[ip]) trackedCount++;
|
||||
}
|
||||
console.log(`\n=== dst_ip Resolution: ${trackedCount} / ${allDstIps.length} unique dst IPs found in DeviceStat ===`);
|
||||
|
||||
await mongoose.disconnect();
|
||||
console.log('\n✓ Done.\n');
|
||||
}
|
||||
|
||||
run().catch(err => { console.error(err); process.exit(1); });
|
||||
@@ -0,0 +1,30 @@
|
||||
// test/check_local_db.js
|
||||
const { MongoClient } = require('mongodb');
|
||||
|
||||
const LOCAL_URI = 'mongodb://127.0.0.1:27017';
|
||||
const DB_NAME = 'backone_dpi';
|
||||
|
||||
async function main() {
|
||||
const client = new MongoClient(LOCAL_URI, { serverSelectionTimeoutMS: 2000 });
|
||||
try {
|
||||
await client.connect();
|
||||
console.log("✓ Connected to local MongoDB successfully!");
|
||||
const db = client.db(DB_NAME);
|
||||
const collections = await db.listCollections().toArray();
|
||||
console.log("Collections in local database:", collections.map(c => c.name));
|
||||
|
||||
if (collections.some(c => c.name === 'users')) {
|
||||
const users = await db.collection('users').find({}).toArray();
|
||||
console.log(`Users in local database (${users.length}):`);
|
||||
users.forEach(u => console.log(`- Username: ${u.username}, Role: ${u.role}, Email: ${u.email || 'N/A'}`));
|
||||
} else {
|
||||
console.log("No 'users' collection locally.");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("✗ Local MongoDB connection failed:", err.message);
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,27 @@
|
||||
// test/check_pm2_restarts.js
|
||||
const { Client } = require('ssh2');
|
||||
|
||||
const sshConfig = {
|
||||
host: '103.185.47.52',
|
||||
port: 2222,
|
||||
username: 'adminbackend',
|
||||
password: 'htEo7x6LsBQiEHHH'
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const conn = new Client();
|
||||
conn.on('ready', () => {
|
||||
conn.exec('. ~/.nvm/nvm.sh && nvm use 20 && npx pm2 list', (err, stream) => {
|
||||
if (err) throw err;
|
||||
let out = '';
|
||||
stream.on('close', () => {
|
||||
conn.end();
|
||||
console.log(out);
|
||||
}).on('data', (data) => {
|
||||
out += data;
|
||||
});
|
||||
});
|
||||
}).connect(sshConfig);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,30 @@
|
||||
// test/check_prod_after_migration.js
|
||||
const { MongoClient } = require('mongodb');
|
||||
|
||||
const REMOTE_URI = 'mongodb://backone_user:SusuKudaLiar@mongodb.prod.proit.id:27017/backone_dpi?authSource=backone_dpi';
|
||||
const DB_NAME = 'backone_dpi';
|
||||
|
||||
async function main() {
|
||||
const client = new MongoClient(REMOTE_URI, { serverSelectionTimeoutMS: 5000 });
|
||||
try {
|
||||
await client.connect();
|
||||
console.log("✓ Connected to production MongoDB successfully!");
|
||||
const db = client.db(DB_NAME);
|
||||
const collections = await db.listCollections().toArray();
|
||||
console.log("Collections in production database:", collections.map(c => c.name));
|
||||
|
||||
const users = await db.collection('users').find({}).toArray();
|
||||
console.log(`Users in production MongoDB (${users.length}):`);
|
||||
users.forEach(u => console.log(`- Username: ${u.username}, Role: ${u.role}, Site UUID: ${u.site_uuid || 'N/A'}`));
|
||||
|
||||
const configCount = await db.collection('tenantconfigs').countDocuments();
|
||||
const locCount = await db.collection('customagentlocations').countDocuments();
|
||||
console.log(`\nConfig entries: ${configCount}, Custom location entries: ${locCount}`);
|
||||
} catch (err) {
|
||||
console.error("✗ Production MongoDB connection failed:", err.message);
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,50 @@
|
||||
// test/check_remote_env.js
|
||||
const { Client } = require('ssh2');
|
||||
|
||||
const sshConfig = {
|
||||
host: '103.185.47.52',
|
||||
port: 2222,
|
||||
username: 'adminbackend',
|
||||
password: 'htEo7x6LsBQiEHHH'
|
||||
};
|
||||
|
||||
async function runSSHCommands(commands) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const conn = new Client();
|
||||
conn.on('ready', () => {
|
||||
let combinedCmd = commands.join(' && echo "=== CMD_SEPARATOR ===" && ');
|
||||
conn.exec(combinedCmd, (err, stream) => {
|
||||
if (err) {
|
||||
conn.end();
|
||||
return reject(err);
|
||||
}
|
||||
let out = '';
|
||||
stream.on('close', (code, signal) => {
|
||||
conn.end();
|
||||
resolve(out);
|
||||
}).on('data', (data) => {
|
||||
out += data;
|
||||
}).stderr.on('data', (data) => {
|
||||
out += data;
|
||||
});
|
||||
});
|
||||
}).on('error', reject).connect(sshConfig);
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const commands = [
|
||||
'echo "=== FLUSH LOGS ===" && . ~/.nvm/nvm.sh && nvm use 20 && npx pm2 flush',
|
||||
'echo "=== HIT AGENTS ===" && curl -s https://demoplace.my.id/agents > /dev/null || echo "Hit failed"',
|
||||
'echo "=== LATEST FRONTEND ERR LOGS ===" && cat /home/adminbackend/.pm2/logs/backone-frontend-error.log'
|
||||
];
|
||||
|
||||
try {
|
||||
const output = await runSSHCommands(commands);
|
||||
console.log(output);
|
||||
} catch (err) {
|
||||
console.error("SSH Commands failed:", err.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,32 @@
|
||||
const mongoose = require('../backend/node_modules/mongoose');
|
||||
const dotenv = require('../backend/node_modules/dotenv');
|
||||
const path = require('path');
|
||||
|
||||
// Load environment variables from .env.local
|
||||
dotenv.config({ path: path.join(__dirname, '../.env.local') });
|
||||
|
||||
const mongoUri = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log(`Connecting to: ${mongoUri}`);
|
||||
await mongoose.connect(mongoUri);
|
||||
console.log('Connected! Deleting all demo user accounts (all except admin, siab, and nexus)...');
|
||||
|
||||
const db = mongoose.connection.db;
|
||||
const usernamesToKeep = ['admin', 'siab', 'nexus'];
|
||||
|
||||
const res = await db.collection('users').deleteMany({
|
||||
username: { $nin: usernamesToKeep }
|
||||
});
|
||||
|
||||
console.log(`Deleted ${res.deletedCount} demo users.`);
|
||||
await mongoose.disconnect();
|
||||
console.log('Done!');
|
||||
} catch (err) {
|
||||
console.error('Error deleting users:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,32 @@
|
||||
const mongoose = require('../backend/node_modules/mongoose');
|
||||
const dotenv = require('../backend/node_modules/dotenv');
|
||||
const path = require('path');
|
||||
|
||||
// Load environment variables from .env.local
|
||||
dotenv.config({ path: path.join(__dirname, '../.env.local') });
|
||||
|
||||
const mongoUri = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log(`Connecting to: ${mongoUri}`);
|
||||
await mongoose.connect(mongoUri);
|
||||
console.log('Connected! Deleting superadmin external accounts...');
|
||||
|
||||
const db = mongoose.connection.db;
|
||||
const usernamesToDelete = ['super_analyst', 'super_engineer', 'sulist', 'suner'];
|
||||
|
||||
const res = await db.collection('users').deleteMany({
|
||||
username: { $in: usernamesToDelete }
|
||||
});
|
||||
|
||||
console.log(`Deleted ${res.deletedCount} users:`, usernamesToDelete);
|
||||
await mongoose.disconnect();
|
||||
console.log('Done!');
|
||||
} catch (err) {
|
||||
console.error('Error deleting users:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,27 @@
|
||||
// test/find_mongoose_chunk.js
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const filePath = path.join(__dirname, '../.next/server/chunks/ssr/[root-of-the-server]__081-pwf._.js');
|
||||
|
||||
try {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
const lines = content.split('\n');
|
||||
console.log(`Total lines: ${lines.length}`);
|
||||
|
||||
let matchCount = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].includes('mongoose-8b99e611e7552af3')) {
|
||||
console.log(`Line ${i + 1}:`);
|
||||
// Print a slice of the line around the match
|
||||
const index = lines[i].indexOf('mongoose-8b99e611e7552af3');
|
||||
const start = Math.max(0, index - 100);
|
||||
const end = Math.min(lines[i].length, index + 100);
|
||||
console.log(lines[i].slice(start, end));
|
||||
matchCount++;
|
||||
if (matchCount > 5) break;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error reading file:", err.message);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// test/fix_blacklist_indexes.js
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
async function run() {
|
||||
console.log("Connecting to MongoDB...");
|
||||
await mongoose.connect('mongodb://127.0.0.1:27017/backone_dpi');
|
||||
console.log("Connected successfully!");
|
||||
|
||||
const db = mongoose.connection.db;
|
||||
const collection = db.collection('blacklistrules');
|
||||
|
||||
console.log("Dropping all existing indexes on blacklistrules collection...");
|
||||
try {
|
||||
await collection.dropIndexes();
|
||||
console.log("✓ Indexes dropped successfully.");
|
||||
} catch (err) {
|
||||
console.warn("Could not drop indexes (probably collection doesn't exist yet):", err.message);
|
||||
}
|
||||
|
||||
console.log("Cleaning up old blacklist rules that don't have agent_uuid...");
|
||||
const deleteResult = await collection.deleteMany({
|
||||
$or: [
|
||||
{ agent_uuid: { $exists: false } },
|
||||
{ agent_uuid: null },
|
||||
{ agent_uuid: "" }
|
||||
]
|
||||
});
|
||||
console.log(`✓ Deleted ${deleteResult.deletedCount} legacy blacklist rules.`);
|
||||
|
||||
console.log("Rebuilding Mongoose model indexes...");
|
||||
const { BlacklistRule } = require('../backend/models/Schemas');
|
||||
await BlacklistRule.cleanIndexes();
|
||||
await BlacklistRule.createIndexes();
|
||||
console.log("✓ New compound indexes built successfully!");
|
||||
|
||||
await mongoose.disconnect();
|
||||
console.log("Disconnected from MongoDB.");
|
||||
}
|
||||
|
||||
run().catch(err => {
|
||||
console.error("Migration failed:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
// test/get_db_date_range.js
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const MONGODB_URI = 'mongodb://backone_user:SusuKudaLiar@mongodb.prod.proit.id:27017/backone_dpi?authSource=backone_dpi';
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
await mongoose.connect(MONGODB_URI);
|
||||
console.log('✓ Connected to Production MongoDB');
|
||||
|
||||
const db = mongoose.connection.db;
|
||||
const summariesCol = db.collection('summaries');
|
||||
|
||||
// Get list of agents
|
||||
const agents = await summariesCol.distinct('agent_uuid', { agent_uuid: { $ne: null } });
|
||||
console.log('Agents found in database:', agents);
|
||||
|
||||
console.log('\n--- DATE RANGE ANALYSIS PER AGENT ---');
|
||||
for (const agentUuid of agents) {
|
||||
// Find earliest and latest timestamp in summaries for this agent
|
||||
const bounds = await summariesCol.aggregate([
|
||||
{ $match: { agent_uuid: agentUuid } },
|
||||
{
|
||||
$group: {
|
||||
_id: '$agent_uuid',
|
||||
minDate: { $min: '$timestamp' },
|
||||
maxDate: { $max: '$timestamp' },
|
||||
count: { $sum: 1 }
|
||||
}
|
||||
}
|
||||
]).toArray();
|
||||
|
||||
if (bounds.length > 0) {
|
||||
const { minDate, maxDate, count } = bounds[0];
|
||||
console.log(`Agent: ${agentUuid}`);
|
||||
console.log(` Earliest Date: ${minDate ? new Date(minDate).toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' }) : 'N/A'}`);
|
||||
console.log(` Latest Date : ${maxDate ? new Date(maxDate).toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' }) : 'N/A'}`);
|
||||
console.log(` Total Summaries Documents: ${count}`);
|
||||
} else {
|
||||
console.log(`Agent: ${agentUuid} (No summary documents found)`);
|
||||
}
|
||||
}
|
||||
|
||||
// Also get overall collections bounds
|
||||
console.log('\n--- OVERALL COLLECTION BOUNDS ---');
|
||||
const colsToCheck = ['flows', 'appstats', 'threats', 'events'];
|
||||
for (const colName of colsToCheck) {
|
||||
const col = db.collection(colName);
|
||||
const firstDoc = await col.find().sort({ timestamp: 1 }).limit(1).toArray();
|
||||
const lastDoc = await col.find().sort({ timestamp: -1 }).limit(1).toArray();
|
||||
|
||||
console.log(`Collection: ${colName}`);
|
||||
console.log(` Earliest Doc: ${firstDoc[0]?.timestamp ? new Date(firstDoc[0].timestamp).toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' }) : 'N/A'}`);
|
||||
console.log(` Latest Doc : ${lastDoc[0]?.timestamp ? new Date(lastDoc[0].timestamp).toLocaleString('id-ID', { timeZone: 'Asia/Jakarta' }) : 'N/A'}`);
|
||||
}
|
||||
|
||||
await mongoose.disconnect();
|
||||
} catch (err) {
|
||||
console.error('Error:', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,27 @@
|
||||
// test/inspect_pm2_config.js
|
||||
const { Client } = require('ssh2');
|
||||
|
||||
const sshConfig = {
|
||||
host: '103.185.47.52',
|
||||
port: 2222,
|
||||
username: 'adminbackend',
|
||||
password: 'htEo7x6LsBQiEHHH'
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const conn = new Client();
|
||||
conn.on('ready', () => {
|
||||
conn.exec('find /home/adminbackend/backone-production -name "server.js"', (err, stream) => {
|
||||
if (err) throw err;
|
||||
let out = '';
|
||||
stream.on('close', () => {
|
||||
conn.end();
|
||||
console.log("Found server.js at:\n", out);
|
||||
}).on('data', (data) => {
|
||||
out += data;
|
||||
});
|
||||
});
|
||||
}).connect(sshConfig);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,50 @@
|
||||
// test/inspect_remote_structure.js
|
||||
const { Client } = require('ssh2');
|
||||
|
||||
const sshConfig = {
|
||||
host: '103.185.47.52',
|
||||
port: 2222,
|
||||
username: 'adminbackend',
|
||||
password: 'htEo7x6LsBQiEHHH'
|
||||
};
|
||||
|
||||
async function runSSHCommands(commands) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const conn = new Client();
|
||||
conn.on('ready', () => {
|
||||
let combinedCmd = commands.join(' && echo "=== CMD_SEPARATOR ===" && ');
|
||||
conn.exec(combinedCmd, (err, stream) => {
|
||||
if (err) {
|
||||
conn.end();
|
||||
return reject(err);
|
||||
}
|
||||
let out = '';
|
||||
stream.on('close', (code, signal) => {
|
||||
conn.end();
|
||||
resolve(out);
|
||||
}).on('data', (data) => {
|
||||
out += data;
|
||||
}).stderr.on('data', (data) => {
|
||||
out += data;
|
||||
});
|
||||
});
|
||||
}).on('error', reject).connect(sshConfig);
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const commands = [
|
||||
'echo "=== LS -LA ROOT ===" && ls -la /home/adminbackend/backone-production/',
|
||||
'echo "=== LS -LA .NEXT ===" && ls -la /home/adminbackend/backone-production/.next/ || echo "no .next"',
|
||||
'echo "=== LS -LA STANDALONE ===" && ls -la /home/adminbackend/backone-production/.next/standalone/ || echo "no standalone"'
|
||||
];
|
||||
|
||||
try {
|
||||
const output = await runSSHCommands(commands);
|
||||
console.log(output);
|
||||
} catch (err) {
|
||||
console.error("SSH Commands failed:", err.message);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,35 @@
|
||||
const mongoose = require('mongoose');
|
||||
const path = require('path');
|
||||
|
||||
require('dotenv').config({ path: path.join(__dirname, '../.env.local') });
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
|
||||
|
||||
async function run() {
|
||||
console.log('Connecting to:', MONGODB_URI);
|
||||
try {
|
||||
await mongoose.connect(MONGODB_URI, {
|
||||
serverSelectionTimeoutMS: 5000,
|
||||
});
|
||||
console.log('Connected!');
|
||||
|
||||
const db = mongoose.connection.db;
|
||||
const collections = await db.listCollections().toArray();
|
||||
console.log('Collections:', collections.map(c => c.name));
|
||||
|
||||
// Try raw query on users collection
|
||||
const users = await db.collection('users').find({}).toArray();
|
||||
console.log('Raw users in DB:', users.map(u => ({
|
||||
username: u.username,
|
||||
role: u.role,
|
||||
site_uuid: u.site_uuid,
|
||||
agent_uuid: u.agent_uuid,
|
||||
created_by: u.created_by
|
||||
})));
|
||||
|
||||
await mongoose.disconnect();
|
||||
} catch (err) {
|
||||
console.error('Error:', err);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -0,0 +1,123 @@
|
||||
// test/multitenant_branding_test.js
|
||||
const mongoose = require('../backend/node_modules/mongoose');
|
||||
const path = require('path');
|
||||
|
||||
// Load environment variables
|
||||
require('dotenv').config({ path: path.join(__dirname, '../.env.local') });
|
||||
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
|
||||
|
||||
const User = require('../backend/models/User');
|
||||
const { TenantConfig } = require('../backend/models/Schemas');
|
||||
|
||||
let testCount = 0;
|
||||
let passedCount = 0;
|
||||
|
||||
function assert(label, condition) {
|
||||
testCount++;
|
||||
if (condition) {
|
||||
console.log(` ✓ PASSED: ${label}`);
|
||||
passedCount++;
|
||||
} else {
|
||||
console.error(` ✗ FAILED: ${label}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function runTests() {
|
||||
console.log('\n=========================================');
|
||||
console.log(' RUNNING TDD TESTS FOR MULTI-TENANCY & BRANDING');
|
||||
console.log('=========================================\n');
|
||||
|
||||
try {
|
||||
// 1. Connect to DB
|
||||
await mongoose.connect(MONGODB_URI);
|
||||
console.log('✓ Connected to MongoDB');
|
||||
|
||||
// 2. Validate User Accounts Seeding
|
||||
const adminUser = await User.findOne({ username: 'admin' });
|
||||
assert('User "admin" should exist', !!adminUser);
|
||||
if (adminUser) {
|
||||
assert('User "admin" should have SUPER_ADMIN role', adminUser.role === 'SUPER_ADMIN');
|
||||
}
|
||||
|
||||
const siabUser = await User.findOne({ username: 'siab' });
|
||||
assert('User "siab" should exist', !!siabUser);
|
||||
if (siabUser) {
|
||||
assert('User "siab" should have TENANT_ADMIN role', siabUser.role === 'TENANT_ADMIN');
|
||||
assert('User "siab" should belong to SIAB site_uuid', siabUser.site_uuid === '6681452d_9cae_4ff4_8ae8_0d504774265e');
|
||||
}
|
||||
|
||||
const nexusUser = await User.findOne({ username: 'nexus' });
|
||||
assert('User "nexus" should exist', !!nexusUser);
|
||||
if (nexusUser) {
|
||||
assert('User "nexus" should have TENANT_ADMIN role', nexusUser.role === 'TENANT_ADMIN');
|
||||
assert('User "nexus" should belong to Nexus site_uuid', nexusUser.site_uuid === 'd7902405_0dc2_458b_8584_ed4d24b64f24');
|
||||
}
|
||||
|
||||
// 3. Validate TenantConfig configurations
|
||||
const backoneConfig = await TenantConfig.findOne({ site_uuid: 'default' });
|
||||
assert('Default branding config should exist', !!backoneConfig);
|
||||
if (backoneConfig) {
|
||||
assert('Default brand_name should be BackOne', backoneConfig.brand_name === 'BackOne');
|
||||
assert('Default brand_logo should be /backone-logo.png', backoneConfig.brand_logo === '/backone-logo.png');
|
||||
}
|
||||
|
||||
const siabConfig = await TenantConfig.findOne({ site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e' });
|
||||
assert('SIAB branding config should exist', !!siabConfig);
|
||||
if (siabConfig) {
|
||||
assert('SIAB brand_name should be SIAB', siabConfig.brand_name === 'SIAB');
|
||||
assert('SIAB brand_logo should be /siab-logo.png', siabConfig.brand_logo === '/siab-logo.png');
|
||||
}
|
||||
|
||||
const nexusConfig = await TenantConfig.findOne({ site_uuid: 'd7902405_0dc2_458b_8584_ed4d24b64f24' });
|
||||
assert('Nexus branding config should exist', !!nexusConfig);
|
||||
if (nexusConfig) {
|
||||
assert('Nexus brand_name should be Nexus', nexusConfig.brand_name === 'Nexus');
|
||||
assert('Nexus brand_logo should be /nexus-logo.png', nexusConfig.brand_logo === '/nexus-logo.png');
|
||||
}
|
||||
|
||||
// 4. Validate Agent listing isolation per site_uuid (summaries collection)
|
||||
const db = mongoose.connection.db;
|
||||
const siabAgents = await db.collection('summaries').distinct('agent_uuid', { site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e' });
|
||||
const nexusAgents = await db.collection('summaries').distinct('agent_uuid', { site_uuid: 'd7902405_0dc2_458b_8584_ed4d24b64f24' });
|
||||
|
||||
assert('SIAB agents count should be greater than 0', siabAgents.length > 0);
|
||||
assert('Nexus agents count should be greater than 0', nexusAgents.length > 0);
|
||||
|
||||
// Check that agents do not overlap
|
||||
const overlap = siabAgents.filter(uuid => nexusAgents.includes(uuid));
|
||||
assert('SIAB and Nexus agent lists should have 0 overlapping agents', overlap.length === 0);
|
||||
|
||||
// 5. Validate User creation isolation (created_by query)
|
||||
const testAdminCreated = await User.find({ created_by: 'admin' });
|
||||
const testNexusCreated = await User.find({ created_by: 'nexus' });
|
||||
assert('Superadmin users should return a queryable list of registered accounts', Array.isArray(testAdminCreated));
|
||||
assert('Nexus admin users should return a queryable list of registered accounts', Array.isArray(testNexusCreated));
|
||||
|
||||
// Verify tenant-admin custom query filter returns AGENT_VIEWER accounts for their site
|
||||
const mockTenantUser = { role: 'TENANT_ADMIN', site_uuid: 'd7902405_0dc2_458b_8584_ed4d24b64f24', username: 'nexus' };
|
||||
const query = {
|
||||
$or: [
|
||||
{ role: 'AGENT_VIEWER', site_uuid: mockTenantUser.site_uuid },
|
||||
{ created_by: mockTenantUser.username }
|
||||
]
|
||||
};
|
||||
const queryResults = await User.find(query);
|
||||
assert('Tenant user list query should execute successfully', Array.isArray(queryResults));
|
||||
|
||||
console.log(`\n=========================================`);
|
||||
console.log(` RESULT: ${passedCount} / ${testCount} tests passed.`);
|
||||
console.log(`=========================================\n`);
|
||||
|
||||
if (passedCount !== testCount) {
|
||||
process.exit(1);
|
||||
} else {
|
||||
process.exit(0);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Test execution failed with error:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
runTests();
|
||||
@@ -0,0 +1,128 @@
|
||||
const mongoose = require('../backend/node_modules/mongoose');
|
||||
const path = require('path');
|
||||
const bcrypt = require('bcryptjs');
|
||||
|
||||
require('dotenv').config({ path: path.join(__dirname, '../.env.local') });
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
|
||||
|
||||
const User = require('../backend/models/User');
|
||||
const { TenantConfig, CustomAgentLocation } = require('../backend/models/Schemas');
|
||||
|
||||
async function run() {
|
||||
console.log('Connecting to MongoDB at:', MONGODB_URI);
|
||||
try {
|
||||
await mongoose.connect(MONGODB_URI);
|
||||
console.log('Connected successfully. Running seeding...');
|
||||
|
||||
// 1. Seed SIAB user
|
||||
const siabCount = await User.countDocuments({ username: 'siab' });
|
||||
if (siabCount === 0) {
|
||||
const hash = bcrypt.hashSync('siab', 10);
|
||||
await User.create({
|
||||
username: 'siab',
|
||||
password_hash: hash,
|
||||
account_name: 'SIAB Administrator',
|
||||
role: 'TENANT_ADMIN',
|
||||
site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
|
||||
agent_uuid: null,
|
||||
});
|
||||
console.log('✓ Seeded SIAB Tenant User: siab / siab');
|
||||
} else {
|
||||
console.log('SIAB user already exists');
|
||||
}
|
||||
|
||||
// 2. Seed Nexus user
|
||||
const nexusCount = await User.countDocuments({ username: 'nexus' });
|
||||
if (nexusCount === 0) {
|
||||
const hash = bcrypt.hashSync('nexus', 10);
|
||||
await User.create({
|
||||
username: 'nexus',
|
||||
password_hash: hash,
|
||||
account_name: 'Nexus Administrator',
|
||||
role: 'TENANT_ADMIN',
|
||||
site_uuid: 'd7902405_0dc2_458b_8584_ed4d24b64f24',
|
||||
agent_uuid: null,
|
||||
});
|
||||
console.log('✓ Seeded Nexus Tenant User: nexus / nexus');
|
||||
} else {
|
||||
console.log('Nexus user already exists');
|
||||
}
|
||||
|
||||
// 3. Seed TenantConfigs
|
||||
const defaultConfigs = [
|
||||
{
|
||||
site_uuid: 'default',
|
||||
brand_name: 'BackOne',
|
||||
brand_logo: '/backone-logo.png',
|
||||
footer_copyright: 'PT. Data Bisnis Solusi',
|
||||
primary_color: '#E11D48',
|
||||
},
|
||||
{
|
||||
site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
|
||||
brand_name: 'SIAB',
|
||||
brand_logo: '/siab-logo.png',
|
||||
footer_copyright: 'PT. SIAB Indonesia',
|
||||
primary_color: '#3B82F6',
|
||||
},
|
||||
{
|
||||
site_uuid: 'd7902405_0dc2_458b_8584_ed4d24b64f24',
|
||||
brand_name: 'Nexus',
|
||||
brand_logo: '/nexus-logo.png',
|
||||
footer_copyright: 'PT. Nexus Solusi',
|
||||
primary_color: '#8B5CF6',
|
||||
}
|
||||
];
|
||||
|
||||
for (const config of defaultConfigs) {
|
||||
const existing = await TenantConfig.findOne({ site_uuid: config.site_uuid });
|
||||
if (!existing) {
|
||||
await TenantConfig.create(config);
|
||||
console.log(`✓ Seeded TenantConfig for: ${config.brand_name}`);
|
||||
} else {
|
||||
console.log(`TenantConfig for ${config.brand_name} already exists`);
|
||||
}
|
||||
}
|
||||
|
||||
// Seed default agent locations
|
||||
const defaultLocations = [
|
||||
{
|
||||
agent_uuid: 'F6-2V-DT-8A',
|
||||
site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
|
||||
latitude: -6.2263304,
|
||||
longitude: 106.4247322,
|
||||
label: 'CPI Balaraja Agent Office'
|
||||
},
|
||||
{
|
||||
agent_uuid: '2F-TF-1D-GK',
|
||||
site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
|
||||
latitude: -6.3763318,
|
||||
longitude: 106.8983017,
|
||||
label: 'JRP Cibubur Agent Office'
|
||||
},
|
||||
{
|
||||
agent_uuid: '8A-V3-PB-85',
|
||||
site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
|
||||
latitude: -6.2253265,
|
||||
longitude: 106.8061484,
|
||||
label: 'IFG LT.18 Agent HQ'
|
||||
}
|
||||
];
|
||||
|
||||
for (const loc of defaultLocations) {
|
||||
const existing = await CustomAgentLocation.findOne({ agent_uuid: loc.agent_uuid });
|
||||
if (!existing) {
|
||||
await CustomAgentLocation.create(loc);
|
||||
console.log(`✓ Seeded CustomAgentLocation for: ${loc.agent_uuid}`);
|
||||
} else {
|
||||
console.log(`CustomAgentLocation for ${loc.agent_uuid} already exists`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Seeding completed successfully!');
|
||||
await mongoose.disconnect();
|
||||
} catch (err) {
|
||||
console.error('Seeding error:', err);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -0,0 +1,67 @@
|
||||
// test/test_agent_flows.js
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
async function test() {
|
||||
await mongoose.connect('mongodb://127.0.0.1:27017/backone_dpi');
|
||||
console.log("Connected to MongoDB");
|
||||
|
||||
const { DeviceStat, Flow } = require('../backend/models/Schemas');
|
||||
|
||||
const siteUuid = '6681452d_9cae_4ff4_8ae8_0d504774265e';
|
||||
|
||||
// Build IP-to-Agent mapping from DeviceStat
|
||||
console.log("Querying devices...");
|
||||
const devices = await DeviceStat.find({ site_uuid: siteUuid }).select('ip_address agent_uuid').lean();
|
||||
console.log(`Found ${devices.length} devices`);
|
||||
|
||||
const deviceIpToAgent = {};
|
||||
for (const dev of devices) {
|
||||
if (dev.ip_address && dev.agent_uuid) {
|
||||
deviceIpToAgent[dev.ip_address] = dev.agent_uuid;
|
||||
}
|
||||
}
|
||||
|
||||
// Query flows
|
||||
console.log("Querying flows...");
|
||||
const flows = await Flow.find({ site_uuid: siteUuid }).select('agent_uuid src_ip dst_ip download upload app_label').lean();
|
||||
console.log(`Found ${flows.length} flows`);
|
||||
|
||||
const flowMap = {};
|
||||
for (const flow of flows) {
|
||||
const srcAgent = flow.agent_uuid;
|
||||
const dstAgent = deviceIpToAgent[flow.dst_ip];
|
||||
|
||||
if (srcAgent && dstAgent && srcAgent !== dstAgent) {
|
||||
const key = `${srcAgent}->${dstAgent}`;
|
||||
if (!flowMap[key]) {
|
||||
flowMap[key] = {
|
||||
source: srcAgent,
|
||||
target: dstAgent,
|
||||
bytes: 0,
|
||||
flowsCount: 0,
|
||||
details: []
|
||||
};
|
||||
}
|
||||
const bytes = ((flow.download || 0) + (flow.upload || 0));
|
||||
flowMap[key].bytes += bytes;
|
||||
flowMap[key].flowsCount += 1;
|
||||
flowMap[key].details.push({
|
||||
src_ip: flow.src_ip,
|
||||
dst_ip: flow.dst_ip,
|
||||
app: flow.app_label || 'Unclassified',
|
||||
bytes: bytes
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const result = Object.values(flowMap);
|
||||
console.log(`Generated ${result.length} agent flows`);
|
||||
|
||||
await mongoose.disconnect();
|
||||
console.log("Disconnected from MongoDB");
|
||||
}
|
||||
|
||||
test().catch(err => {
|
||||
console.error("Test failed:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
const path = require('path');
|
||||
require('dotenv').config({ path: path.join(__dirname, '..', '.env.local') });
|
||||
|
||||
const assert = require('assert');
|
||||
const netify = require('../proxy/netifyClient');
|
||||
|
||||
async function testAll() {
|
||||
console.log('Starting TDD API Migration Tests against Netify API...');
|
||||
|
||||
// Test 1: fetchAgents
|
||||
console.log('\n--- Test 1: fetchAgents ---');
|
||||
const agents = await netify.fetchAgents('6681452d_9cae_4ff4_8ae8_0d504774265e');
|
||||
console.log('Agents returned count:', agents?.length);
|
||||
assert(Array.isArray(agents), 'Agents must be an array');
|
||||
assert(agents.length > 0, 'Should find at least 1 agent');
|
||||
assert(agents[0].uuid, 'Agent must have a uuid');
|
||||
assert(agents[0].label, 'Agent must have a label');
|
||||
|
||||
// Test 2: fetchBandwidthSummary
|
||||
console.log('\n--- Test 2: fetchBandwidthSummary ---');
|
||||
const summary = await netify.fetchBandwidthSummary(1440, 'F6-2V-DT-8A', '6681452d_9cae_4ff4_8ae8_0d504774265e');
|
||||
console.log('Bandwidth summary returned:', summary);
|
||||
assert(summary, 'Summary should not be null');
|
||||
assert(typeof summary.bandwidth_down === 'number', 'bandwidth_down must be a number');
|
||||
assert(typeof summary.bandwidth_up === 'number', 'bandwidth_up must be a number');
|
||||
|
||||
// Test 3: fetchTopApps
|
||||
console.log('\n--- Test 3: fetchTopApps ---');
|
||||
const apps = await netify.fetchTopApps(1440, 10, 'F6-2V-DT-8A', '6681452d_9cae_4ff4_8ae8_0d504774265e');
|
||||
console.log('Top Apps returned count:', apps?.length);
|
||||
if (apps && apps.length > 0) {
|
||||
console.log('First App:', apps[0]);
|
||||
assert(apps[0].application?.label, 'App must have application.label');
|
||||
assert(typeof apps[0].download === 'number', 'download must be a number');
|
||||
assert(typeof apps[0].upload === 'number', 'upload must be a number');
|
||||
assert(typeof apps[0].flows === 'number', 'flows must be a number');
|
||||
}
|
||||
|
||||
// Test 4: fetchDiscoveredDevices
|
||||
console.log('\n--- Test 4: fetchDiscoveredDevices ---');
|
||||
const devices = await netify.fetchDiscoveredDevices(120, 10, 'F6-2V-DT-8A', '6681452d_9cae_4ff4_8ae8_0d504774265e');
|
||||
console.log('Discovered devices count:', devices?.length);
|
||||
if (devices && devices.length > 0) {
|
||||
console.log('First Device:', devices[0]);
|
||||
assert(devices[0].ip_address, 'Device must have ip_address');
|
||||
}
|
||||
|
||||
// Test 5: fetchFlows
|
||||
console.log('\n--- Test 5: fetchFlows ---');
|
||||
const flows = await netify.fetchFlows(10, 'F6-2V-DT-8A', '6681452d_9cae_4ff4_8ae8_0d504774265e');
|
||||
console.log('Flows count:', flows?.length);
|
||||
if (flows && flows.length > 0) {
|
||||
console.log('First Flow:', flows[0]);
|
||||
assert(flows[0].flow_id, 'Flow must have flow_id');
|
||||
assert(flows[0].src_ip, 'Flow must have src_ip');
|
||||
assert(flows[0].download >= 0, 'download must be >= 0');
|
||||
assert(flows[0].upload >= 0, 'upload must be >= 0');
|
||||
assert(flows[0].first_seen, 'first_seen must exist');
|
||||
}
|
||||
|
||||
console.log('\n✓ All TDD API Migration Tests PASSED!');
|
||||
}
|
||||
|
||||
testAll().catch(err => {
|
||||
console.error('\n✗ Test failed:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
// test/test_native_mongo.js
|
||||
const { MongoClient } = require('mongodb');
|
||||
|
||||
async function test() {
|
||||
const url = 'mongodb://127.0.0.1:27017';
|
||||
const client = new MongoClient(url);
|
||||
|
||||
try {
|
||||
console.log("Connecting natively to MongoDB...");
|
||||
await client.connect();
|
||||
console.log("Connected successfully!");
|
||||
|
||||
const db = client.db('backone_dpi');
|
||||
const collection = db.collection('devicestats');
|
||||
|
||||
console.log("Querying devicestats natively...");
|
||||
const start = Date.now();
|
||||
const count = await collection.countDocuments({});
|
||||
console.log(`Successfully queried! Total docs in devicestats: ${count}`);
|
||||
console.log(`Query took ${Date.now() - start} ms`);
|
||||
|
||||
} catch (err) {
|
||||
console.error("Native test failed:", err);
|
||||
} finally {
|
||||
await client.close();
|
||||
console.log("Disconnected.");
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
||||
Reference in new issue
Block a user