feat(source2): push all latest files - device labeling, help system, proxy docs, database isolation fix

- Added DOKUMENTASI-FILTER-PER-SITE.md (site isolation docs)
- Fixed start-with-env.js to force-load .env.production
- Fixed MONGODB_URI hostname from mongodb-netify to mongodb.prod.proit.id
- Updated .gitignore to exclude sensitive scripts and credential files
- Minor UI and labeling improvements
This commit is contained in:
rafif committed 2026-07-29 14:14:29 +07:00
1 parent a403f752f3
commit dd4c8f6876
385 files changed
+31016 -8268

No files matched your search

+98
View File
@@ -0,0 +1,98 @@
// test/branding_unit_test.js
const fs = require('fs');
const path = require('path');
const vm = require('vm');
console.log('=========================================');
console.log(' RUNNING TDD UNIT TEST FOR BRANDING LOGIC');
console.log('=========================================\n');
// 1. Read and transpile src/lib/branding.ts slightly to make it run in Node.js
const brandingCodePath = path.join(__dirname, '../src/lib/branding.ts');
let code = fs.readFileSync(brandingCodePath, 'utf8');
// Strip TypeScript interfaces, return types, parameter types, and export keywords
code = code.replace(/export\s+interface\s+\w+\s*\{[^}]*\}/g, '');
code = code.replace(/:\s*Branding\b/g, '');
code = code.replace(/selectedSiteUuid\?\s*:\s*string/g, 'selectedSiteUuid');
code = code.replace(/export\s+/g, '');
let testCount = 0;
let passedCount = 0;
function assert(label, condition) {
testCount++;
if (condition) {
console.log(` ✓ PASSED: ${label}`);
passedCount++;
} else {
console.error(` ✗ FAILED: ${label}`);
}
}
// Helper to run getSiteBranding with mocked environment
function runGetSiteBranding({ selectedSiteUuid, hostname, search, localStorageVal }) {
const sandbox = {
window: {
location: {
hostname: hostname || 'localhost',
search: search || ''
}
},
localStorage: {
getItem: () => localStorageVal || null
},
console
};
vm.createContext(sandbox);
vm.runInContext(code, sandbox);
return sandbox.getSiteBranding(selectedSiteUuid);
}
try {
// Test Case 1: Default branding (no local storage, localhost)
const brand1 = runGetSiteBranding({
hostname: 'localhost'
});
assert('Default branding should be BackOne', brand1.name === 'BackOne' && brand1.logo === '/backone-logo.png');
// Test Case 2: SIAB site UUID passed explicitly on demoplace.my.id
const brand2 = runGetSiteBranding({
selectedSiteUuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
hostname: 'demoplace.my.id'
});
assert('SIAB site UUID on demoplace.my.id should return BackOne branding', brand2.name === 'BackOne' && brand2.logo === '/backone-logo.png');
// Test Case 3: SIAB site UUID in localStorage on demoplace.my.id
const brand3 = runGetSiteBranding({
localStorageVal: '6681452d_9cae_4ff4_8ae8_0d504774265e',
hostname: 'demoplace.my.id'
});
assert('SIAB site UUID in localStorage on demoplace.my.id should return BackOne branding', brand3.name === 'BackOne' && brand3.logo === '/backone-logo.png');
// Test Case 4: Nexus site UUID passed explicitly
const brand4 = runGetSiteBranding({
selectedSiteUuid: 'd7902405_0dc2_458b_8584_ed4d24b64f24',
hostname: 'localhost'
});
assert('Nexus site UUID should return Nexus branding', brand4.name === 'Nexus' && brand4.logo === '/nexus-logo.png');
// Test Case 5: Nexus fallback on demoplace.my.id when no site is selected
const brand5 = runGetSiteBranding({
hostname: 'demoplace.my.id'
});
assert('Fallback on demoplace.my.id should be Nexus branding', brand5.name === 'Nexus' && brand5.logo === '/nexus-logo.png');
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);
}
+15
View File
@@ -0,0 +1,15 @@
const mongoose = require('mongoose');
const { LookupApp } = require('../backend/models/Schemas');
async function main() {
const uri = 'mongodb://127.0.0.1:27017/backone_dpi';
await mongoose.connect(uri);
console.log('Connected to:', mongoose.connection.name);
const count = await LookupApp.countDocuments({});
console.log('LookupApp model count in backend schema:', count);
await mongoose.disconnect();
}
main().catch(console.error);
+19
View File
@@ -0,0 +1,19 @@
const proxyMongoose = require('../proxy/node_modules/mongoose');
require('dotenv').config({ path: './.env.local' });
async function main() {
const uri = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
await proxyMongoose.connect(uri);
console.log('--- CONNECTION DETAILS ---');
console.log('Host:', proxyMongoose.connection.host);
console.log('Port:', proxyMongoose.connection.port);
console.log('DB Name:', proxyMongoose.connection.name);
console.log('URI used:', uri);
const collections = await proxyMongoose.connection.db.listCollections().toArray();
console.log('Collections list:', collections.map(c => c.name));
await proxyMongoose.disconnect();
}
main().catch(console.error);
+33
View File
@@ -0,0 +1,33 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
const lsFonts = await runCmd('ls -la /home/adminbackend/web/demoplace.my.id/public_html/.next/standalone/public/fonts || echo "No fonts folder"');
console.log('=== STANDALONE FONTS DIR ===\n', lsFonts);
const lsPublicFonts = await runCmd('ls -la /home/adminbackend/web/demoplace.my.id/public_html/public/fonts || echo "No public fonts folder"');
console.log('=== SOURCE PUBLIC FONTS DIR ===\n', lsPublicFonts);
conn.end();
}
main().catch(console.error);
+22
View File
@@ -0,0 +1,22 @@
// test/check-ip-mongo.js
const { MongoClient } = require('mongodb');
const URI = 'mongodb://backone_user:SusuKudaLiar@103.80.237.29:27017/backone_dpi?authSource=backone_dpi';
async function main() {
console.log('Connecting to MongoDB via IP 103.80.237.29...');
const client = new MongoClient(URI, { serverSelectionTimeoutMS: 5000 });
try {
await client.connect();
console.log('✓ Successfully connected to MongoDB via IP!');
const db = client.db('backone_dpi');
const cols = await db.listCollections().toArray();
console.log('Collections:', cols.map(c => c.name));
} catch (err) {
console.error('✗ Connection failed:', err.message);
} finally {
await client.close();
}
}
main();
+20
View File
@@ -0,0 +1,20 @@
require('dotenv').config({ path: './.env.local' });
const mongoose = require('mongoose');
const { LookupApp } = require('../proxy/models/Schemas');
async function main() {
const uri = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
console.log('Using URI from env:', uri);
await mongoose.connect(uri);
console.log('Connected to:', mongoose.connection.name, 'on host:', mongoose.connection.host);
const count = await LookupApp.countDocuments({});
console.log('LookupApp model count:', count);
const rawCount = await mongoose.connection.db.collection('lookupapps').countDocuments({});
console.log('Raw collection count:', rawCount);
await mongoose.disconnect();
}
main().catch(console.error);
+11
View File
@@ -0,0 +1,11 @@
// test/check-logo-size.js
const axios = require('axios');
async function main() {
const url = 'https://demoplace.my.id/nexus-logo.png';
const res = await axios.head(url);
console.log('Remote nexus-logo.png content-length:', res.headers['content-length']);
console.log('Remote nexus-logo.png content-type:', res.headers['content-type']);
}
main().catch(err => console.error(err.message));
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("/home/adminbackend/.npm-global/bin/pm2 show backone-frontend", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- PM2 SHOW FRONTEND ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("/home/adminbackend/.npm-global/bin/pm2 status; ps -ef | grep node", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- PM2 & PROCESSES ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+23
View File
@@ -0,0 +1,23 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
console.log('Querying remote Nginx config and PM2 details...');
conn.exec("cat /etc/nginx/conf.d/*.conf /etc/nginx/sites-enabled/* /etc/nginx/nginx.conf 2>/dev/null | grep -i -A 10 -B 2 'demoplace.my.id'; /home/adminbackend/.npm-global/bin/pm2 env 2", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE NGINX & PM2 ENV ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+23
View File
@@ -0,0 +1,23 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
console.log('Checking PM2 status and errors...');
conn.exec("/home/adminbackend/.npm-global/bin/pm2 list; tail -n 50 /home/adminbackend/web/demoplace.my.id/public_html/logs/frontend-error.log", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- PM2 STATUS & FRONTEND ERRORS ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+33
View File
@@ -0,0 +1,33 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.stderr.on('data', d => out += `[stderr] ${d}`);
stream.on('close', () => resolve(out.trim()));
});
});
};
const remoteNodeCmd = `const mongoose = require('/home/adminbackend/web/demoplace.my.id/public_html/proxy/node_modules/mongoose'); mongoose.connect('mongodb://127.0.0.1:27017/backone_dpi').then(() => mongoose.connection.db.collection('lookupapps').countDocuments()).then(c => { console.log('COUNT:', c); process.exit(0); }).catch(e => { console.error(e); process.exit(1); })`;
const countRes = await runCmd(`node -e ${JSON.stringify(remoteNodeCmd)}`);
console.log('=== REMOTE LOOKUP COUNT ===\n', countRes);
conn.end();
}
main().catch(console.error);
+27
View File
@@ -0,0 +1,27 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec('cat /home/adminbackend/web/demoplace.my.id/public_html/proxy/.env /home/adminbackend/web/demoplace.my.id/public_html/backend/.env /home/adminbackend/web/demoplace.my.id/public_html/.env.production', (err, stream) => {
if (err) {
console.error(err);
conn.end();
return;
}
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE ENVS ---');
console.log(out);
conn.end();
});
});
}).on('error', console.error).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("find /home/adminbackend/web/demoplace.my.id/public_html/.next/standalone -path '*agents*' -ls", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE NEXT AGENTS FILES ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("ls -ld /home/adminbackend/web/demoplace.my.id/public_html/.next; ls -l /home/adminbackend/web/demoplace.my.id/public_html/.next/standalone/server.js", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE NEXT DATE ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+33
View File
@@ -0,0 +1,33 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
const lsStandalone = await runCmd('ls -la /home/adminbackend/web/demoplace.my.id/public_html/.next/standalone');
console.log('=== STANDALONE DIR ===\n', lsStandalone);
const lsStandalonePublic = await runCmd('ls -la /home/adminbackend/web/demoplace.my.id/public_html/.next/standalone/public || echo "No public folder in standalone"');
console.log('=== STANDALONE PUBLIC DIR ===\n', lsStandalonePublic);
conn.end();
}
main().catch(console.error);
+71 -31
View File
@@ -1,50 +1,90 @@
// test/check_remote_env.js
// Fix 502: Write Nginx custom config to proxy directly to Next.js port 3000
'use strict';
const { Client } = require('ssh2');
const sshConfig = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH'
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
async function runSSHCommands(commands) {
function runSSHCommand(conn, cmd) {
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);
conn.exec(cmd, (err, stream) => {
if (err) return reject(err);
let out = '';
stream.on('close', () => resolve(out))
.on('data', d => { out += d; process.stdout.write(d.toString()); })
.stderr.on('data', d => { out += d; process.stdout.write(d.toString()); });
});
});
}
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(sshConfig);
});
console.log('[SSH] Connected!\n');
const CONF = '/home/adminbackend/conf/web/demoplace.my.id';
// The Nginx config includes nginx.conf_custom and nginx.ssl.conf_custom
// We override the location / block to proxy directly to Next.js port 3000
const httpCustom = [
'# BackOne DPI — Direct proxy to Next.js',
'location / {',
' proxy_pass http://127.0.0.1:3000;',
' proxy_http_version 1.1;',
' proxy_set_header Upgrade $http_upgrade;',
' proxy_set_header Connection "upgrade";',
' proxy_set_header Host $host;',
' proxy_set_header X-Real-IP $remote_addr;',
' proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;',
' proxy_set_header X-Forwarded-Proto $scheme;',
' proxy_read_timeout 86400;',
'}',
].join('\n');
const sslCustom = [
'# BackOne DPI — Direct SSL proxy to Next.js',
'location / {',
' proxy_pass http://127.0.0.1:3000;',
' proxy_http_version 1.1;',
' proxy_set_header Upgrade $http_upgrade;',
' proxy_set_header Connection "upgrade";',
' proxy_set_header Host $host;',
' proxy_set_header X-Real-IP $remote_addr;',
' proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;',
' proxy_set_header X-Forwarded-Proto https;',
' proxy_read_timeout 86400;',
'}',
].join('\n');
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'
// Write HTTP custom config
`printf '%s\n' ${JSON.stringify(httpCustom)} > ${CONF}/nginx.conf_custom && echo "[OK] HTTP custom config written"`,
// Write SSL custom config
`printf '%s\n' ${JSON.stringify(sslCustom)} > ${CONF}/nginx.ssl.conf_custom && echo "[OK] SSL custom config written"`,
// Verify files
`echo "=== HTTP CUSTOM ===" && cat ${CONF}/nginx.conf_custom`,
`echo "=== SSL CUSTOM ===" && cat ${CONF}/nginx.ssl.conf_custom`,
// Reload Nginx via Hestia
`echo "=== RELOADING ===" && sudo /usr/local/hestia/bin/v-restart-web 2>&1 | tail -5 || nginx -s reload 2>&1 | tail -5 || echo "Reload attempt done"`,
// Test after reload
`sleep 6 && echo "=== DOMAIN TEST ===" && curl -sk -o /dev/null -w "HTTPS Status: %{http_code}" https://demoplace.my.id/login`,
];
try {
const output = await runSSHCommands(commands);
console.log(output);
} catch (err) {
console.error("SSH Commands failed:", err.message);
for (const cmd of commands) {
console.log(`\n$ ${cmd.substring(0, 100)}${cmd.length > 100 ? '...' : ''}`);
await runSSHCommand(conn, cmd);
}
conn.end();
console.log('\n\n✅ Selesai! Cek https://demoplace.my.id/login di browser.\n');
}
main();
main().catch(err => { console.error('[FATAL]', err.message); process.exit(1); });
+23
View File
@@ -0,0 +1,23 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
console.log('Cleaning up backslash files/folders on remote server...');
conn.exec("find /home/adminbackend/web/demoplace.my.id/public_html -name '*\\\\*' -depth -exec rm -rf {} \\; -print", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- CLEANED UP REMOTE FILES ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+30
View File
@@ -0,0 +1,30 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const fs = require('fs');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
const REMOTE_PATH = '/home/adminbackend/web/demoplace.my.id/public_html/.env.production';
const LOCAL_PATH = 'c:\\Users\\demo\\Downloads\\Deep Package Inspection\\.env.production';
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected. Downloading .env.production...');
await new Promise((resolve, reject) => {
conn.sftp((err, sftp) => {
if (err) return reject(err);
sftp.fastGet(REMOTE_PATH, LOCAL_PATH, {}, (err2) => {
if (err2) return reject(err2);
resolve();
});
});
});
console.log('Downloaded successfully to:', LOCAL_PATH);
conn.end();
}
main().catch(console.error);
+83
View File
@@ -0,0 +1,83 @@
const { Client } = require('ssh2');
const path = require('path');
const fs = require('fs');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const REMOTE_ROOT = '/home/adminbackend/web/demoplace.my.id/public_html';
const LOCAL_ROOT = path.join(__dirname, '..');
const filesToDownload = [
'src/app/(dashboard)/agents/page.tsx',
'src/app/(dashboard)/apps/page.tsx',
'src/app/(dashboard)/devices/page.tsx',
'src/app/(dashboard)/dns/page.tsx',
'src/app/(dashboard)/dpi-analytics/page.tsx',
'src/app/(dashboard)/events/page.tsx',
'src/app/(dashboard)/flows/page.tsx',
'src/app/(dashboard)/geography/page.tsx',
'src/app/(dashboard)/intelligence/page.tsx',
'src/app/(dashboard)/lookup/page.tsx',
'src/app/(dashboard)/network-infrastructure/page.tsx',
'src/app/(dashboard)/network-intelligence/page.tsx',
'src/app/(dashboard)/page.tsx',
'src/app/(dashboard)/security-audit/page.tsx',
'src/app/(dashboard)/threats/page.tsx',
'src/components/admin/ExternalAccountModal.tsx',
'src/components/layout/Sidebar.tsx',
'src/components/layout/SidebarData.ts',
'src/components/ui/SafeImage.tsx',
'src/lib/actions/agents.ts',
'src/lib/admin-api.ts',
'package.json'
];
const conn = new Client();
conn.on('ready', () => {
console.log('✓ SSH Connection ready for SFTP...');
conn.sftp((err, sftp) => {
if (err) {
console.error('SFTP Error:', err.message);
conn.end();
return;
}
let downloadedCount = 0;
let failedCount = 0;
filesToDownload.forEach((relPath) => {
const remotePath = `${REMOTE_ROOT}/${relPath}`;
const localPath = path.join(LOCAL_ROOT, relPath);
// Ensure target directory exists
const localDir = path.dirname(localPath);
if (!fs.existsSync(localDir)) {
fs.mkdirSync(localDir, { recursive: true });
}
console.log(`Downloading: ${relPath} ...`);
sftp.fastGet(remotePath, localPath, (sftpErr) => {
if (sftpErr) {
console.error(`✗ Failed to download ${relPath}:`, sftpErr.message);
failedCount++;
} else {
console.log(`✓ Downloaded ${relPath}`);
downloadedCount++;
}
if (downloadedCount + failedCount === filesToDownload.length) {
console.log(`\n=========================================`);
console.log(` DOWNLOAD COMPLETED: ${downloadedCount} Succeeded, ${failedCount} Failed.`);
console.log(`=========================================\n`);
conn.end();
}
});
});
});
}).on('error', console.error).connect(SSH);
+78
View File
@@ -0,0 +1,78 @@
const { Client } = require('ssh2');
const fs = require('fs');
const path = require('path');
const SSH_CONFIG = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH'
};
const remoteDir = '/home/adminbackend/web/demoplace.my.id/public_html/api/uploads';
const localDir = path.join(__dirname, '../public/api/uploads');
// Ensure local directory exists
if (!fs.existsSync(localDir)) {
fs.mkdirSync(localDir, { recursive: true });
}
console.log('Connecting to SSH...');
const conn = new Client();
conn.on('ready', () => {
console.log('SSH Connection ready. Starting SFTP...');
conn.sftp(async (err, sftp) => {
if (err) {
console.error('SFTP Error:', err.message);
conn.end();
return;
}
console.log('Listing remote uploads directory:', remoteDir);
sftp.readdir(remoteDir, async (err, list) => {
if (err) {
console.error('Readdir Error:', err.message);
conn.end();
return;
}
const files = list.filter(item => item.attrs.isFile());
console.log(`Found ${files.length} upload files on remote server.`);
if (files.length === 0) {
conn.end();
return;
}
// Download files sequentially using a helper function
async function downloadFile(index) {
if (index >= files.length) {
console.log('\n=========================================');
console.log(' ALL UPLOADS DOWNLOAD COMPLETED.');
console.log('=========================================');
conn.end();
return;
}
const name = files[index].filename;
const remoteFile = path.posix.join(remoteDir, name);
const localFile = path.join(localDir, name);
console.log(`[${index + 1}/${files.length}] Downloading: ${name} ...`);
sftp.fastGet(remoteFile, localFile, {}, (err) => {
if (err) {
console.error(`Failed to download ${name}:`, err.message);
} else {
console.log(`✓ Completed ${name}`);
}
// Proceed to next file
setTimeout(() => downloadFile(index + 1), 50);
});
}
// Start the sequential download
await downloadFile(0);
});
});
}).connect(SSH_CONFIG);
+71
View File
@@ -0,0 +1,71 @@
const { Client } = require('ssh2');
const fs = require('fs');
const path = require('path');
const SSH_CONFIG = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH'
};
const remoteDir = '/home/adminbackend/web/demoplace.my.id/public_html/api/uploads';
const localDir = path.join(__dirname, '../public/api/uploads');
// Ensure local directory exists
if (!fs.existsSync(localDir)) {
fs.mkdirSync(localDir, { recursive: true });
}
console.log('Connecting to SSH...');
const conn = new Client();
conn.on('ready', () => {
console.log('SSH Connection ready. Starting SFTP...');
conn.sftp((err, sftp) => {
if (err) {
console.error('SFTP Error:', err.message);
conn.end();
return;
}
console.log('Listing remote uploads directory:', remoteDir);
sftp.readdir(remoteDir, (err, list) => {
if (err) {
console.error('Readdir Error:', err.message);
conn.end();
return;
}
const files = list.filter(item => item.attrs.isFile());
console.log(`Found ${files.length} upload files on remote server.`);
if (files.length === 0) {
conn.end();
return;
}
let downloaded = 0;
files.forEach(fileInfo => {
const name = fileInfo.filename;
const remoteFile = path.posix.join(remoteDir, name);
const localFile = path.join(localDir, name);
console.log(`Downloading: ${name} ...`);
sftp.fastGet(remoteFile, localFile, {}, (err) => {
if (err) {
console.error(`Failed to download ${name}:`, err.message);
} else {
console.log(`✓ Downloaded ${name}`);
}
downloaded++;
if (downloaded === files.length) {
console.log('\n=========================================');
console.log(' ALL UPLOADS DOWNLOAD COMPLETED.');
console.log('=========================================');
conn.end();
}
});
});
});
});
}).connect(SSH_CONFIG);
+27
View File
@@ -0,0 +1,27 @@
const axios = require('axios');
async function main() {
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'admin',
password: 'admin'
});
const cookie = loginRes.headers['set-cookie'];
const pageRes = await axios.get('https://demoplace.my.id/agents', {
headers: {
Cookie: cookie ? cookie.join('; ') : ''
}
});
const html = pageRes.data;
console.log("=== HEADINGS ===");
const headings = html.match(/<h[1-6][^>]*>[\s\S]*?<\/h[1-6]>/gi) || [];
headings.forEach(h => console.log(h.replace(/<[^>]+>/g, '').trim()));
console.log("=== CARD TITLES OR TABLE TITLES ===");
const textMatches = html.match(/[^>]{5,100}(?:External Accounts|Agents|Inventory|Tenant)[^<]{5,100}/gi) || [];
textMatches.slice(0, 30).forEach(t => console.log(t.replace(/<[^>]+>/g, '').trim()));
}
main().catch(console.error);
+90
View File
@@ -0,0 +1,90 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const remoteJs = `
const mongoose = require('/home/adminbackend/web/demoplace.my.id/public_html/backend/node_modules/mongoose');
async function main() {
console.log('Remote: Requiring mongoose succeeded. Connecting...');
const URI = 'mongodb://backone_user:SusuKudaLiar@103.80.237.29:27017/backone_dpi?authSource=backone_dpi';
try {
await mongoose.connect(URI, {
serverSelectionTimeoutMS: 10000,
connectTimeoutMS: 10000,
});
console.log('Remote: Connected to DB.');
const db = mongoose.connection.db;
const collections = await db.listCollections().toArray();
console.log('Remote: Listed collections.');
const result = {};
for (const col of collections) {
const name = col.name;
console.log('Remote: Querying collection ' + name);
const count = await db.collection(name).countDocuments({});
if (['users', 'tenantconfigs', 'customagentlocations', 'blacklistrules', 'summaries'].includes(name)) {
const docs = await db.collection(name).find({}).toArray();
result[name] = { count, docs };
} else {
result[name] = { count };
}
}
console.log('--- JSON_START ---');
console.log(JSON.stringify(result));
console.log('--- JSON_END ---');
} catch (err) {
console.error('Remote Error:', err.message);
} finally {
await mongoose.disconnect();
console.log('Remote: Mongoose disconnected.');
}
}
main();
`;
const conn = new Client();
conn.on('ready', () => {
const b64 = Buffer.from(remoteJs).toString('base64');
conn.exec(`echo "${b64}" | base64 -d | node`, (err, stream) => {
if (err) {
console.error(err);
conn.end();
return;
}
let out = '';
stream.on('data', d => {
const chunk = d.toString();
process.stdout.write(chunk);
out += chunk;
});
stream.stderr.on('data', d => {
process.stderr.write(d.toString());
});
stream.on('close', () => {
const startIdx = out.indexOf('--- JSON_START ---');
const endIdx = out.indexOf('--- JSON_END ---');
if (startIdx !== -1 && endIdx !== -1) {
const jsonStr = out.substring(startIdx + '--- JSON_START ---'.length, endIdx).trim();
try {
const parsed = JSON.parse(jsonStr);
console.log('\n--- REMOTE COLLECTIONS INFO ---');
for (const [name, info] of Object.entries(parsed)) {
console.log(`- ${name}: ${info.count} documents`);
}
const fs = require('fs');
fs.writeFileSync('C:\\Users\\demo\\.gemini\\antigravity-ide\\scratch\\remote_db_dump.json', jsonStr);
console.log('\n✓ Saved full DB dump locally to scratch/remote_db_dump.json');
} catch (e) {
console.error('\nFailed to parse JSON segment:', e.message);
}
}
conn.end();
});
});
}).on('error', console.error).connect(SSH);
+26
View File
@@ -0,0 +1,26 @@
const axios = require('axios');
async function main() {
console.log('Logging in to remote server...');
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'nexus',
password: 'nexus'
});
const cookie = loginRes.headers['set-cookie'];
console.log('Login successful. Cookies:', cookie);
console.log('Fetching / (Overview page) with cookie...');
const pageRes = await axios.get('https://demoplace.my.id/', {
headers: {
Cookie: cookie ? cookie.join('; ') : ''
}
});
console.log('Page HTTP Status:', pageRes.status);
console.log('Page HTML length:', pageRes.data.length);
console.log('HTML snippet (first 500 chars):');
console.log(pageRes.data.substring(0, 500));
}
main().catch(console.error);
+25
View File
@@ -0,0 +1,25 @@
const axios = require('axios');
async function main() {
try {
console.log('Fetching https://demoplace.my.id/ ...');
const res1 = await axios.get('https://demoplace.my.id/', { maxRedirects: 0, validateStatus: () => true });
console.log('Status /:', res1.status);
console.log('Headers /:', res1.headers);
console.log('Body snippet /:', res1.data.substring(0, 500));
} catch (err) {
console.error('Error /:', err.message);
}
try {
console.log('\nFetching https://demoplace.my.id/login ...');
const res2 = await axios.get('https://demoplace.my.id/login', { maxRedirects: 0, validateStatus: () => true });
console.log('Status /login:', res2.status);
console.log('Headers /login:', res2.headers);
console.log('Body snippet /login:', res2.data.substring(0, 500));
} catch (err) {
console.error('Error /login:', err.message);
}
}
main().catch(console.error);
+39
View File
@@ -0,0 +1,39 @@
const axios = require('axios');
async function main() {
console.log('Logging in to remote server...');
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'admin',
password: 'admin'
});
const cookie = loginRes.headers['set-cookie'];
console.log('Login successful. Cookies:', cookie);
console.log('Fetching /agents page...');
const pageRes = await axios.get('https://demoplace.my.id/agents', {
headers: {
Cookie: cookie ? cookie.join('; ') : ''
}
});
const html = pageRes.data;
console.log('Page HTML length:', html.length);
const hasSuperadminTable = html.includes('Superadmin (BackOne) External Accounts');
const hasInventoryTable = html.includes('External Accounts Inventory');
console.log('Contains Superadmin table:', hasSuperadminTable);
console.log('Contains Inventory table:', hasInventoryTable);
// Find where table title is mentioned
const idx1 = html.indexOf('Superadmin (BackOne)');
if (idx1 !== -1) {
console.log('Snippet around Superadmin:', html.substring(idx1 - 100, idx1 + 200));
}
const idx2 = html.indexOf('External Accounts Inventory');
if (idx2 !== -1) {
console.log('Snippet around Inventory:', html.substring(idx2 - 100, idx2 + 200));
}
}
main().catch(console.error);
+30
View File
@@ -0,0 +1,30 @@
// test/fetch-sidebar-logo.js
const axios = require('axios');
async function main() {
console.log('Logging in as nexus...');
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'nexus',
password: 'nexus'
});
const cookie = loginRes.headers['set-cookie'];
const headers = { Cookie: cookie ? cookie.join('; ') : '' };
console.log('Fetching overview page...');
const pageRes = await axios.get('https://demoplace.my.id/', { headers });
const html = pageRes.data;
// Find all img tags using a regex
const imgRegex = /<img[^>]+src=["']([^"']+)["']/g;
let match;
console.log('Found image tags in HTML:');
while ((match = imgRegex.exec(html)) !== null) {
console.log(' - src:', match[1]);
}
}
main().catch(err => {
console.error('Error:', err.message);
});
+12 -12
View File
@@ -35,10 +35,10 @@ const server = r('backend/server.js');
const sched = r('proxy/scheduler.js');
const coll = r('proxy/collector.js') + r('proxy/collectorHelperDpi2.js');
const compose = r('docker-compose.yml');
const envFile = r('.env.local');
const proxyIdx = r('proxy/index.js');
const proxyIdx = r('proxy/index.js') + (fs.existsSync(path.join(ROOT, 'proxy/routes.js')) ? r('proxy/routes.js') : '');
const proxySchema = r('proxy/models/Schemas.js');
const pkg = JSON.parse(r('backend/package.json'));
const envFileAll = r('.env.local') + (fs.existsSync(path.join(ROOT, '.env.production')) ? r('.env.production') : '');
// ─── DELIVERABLE 1: Proxy 2 Mode ───────────────────────────────────────────
console.log('📦 DELIVERABLE 1: Proxy — 2 Mode Pengambilan Data');
@@ -83,9 +83,9 @@ check('getBaseFilter() helper ada', dash.includes('function getBaseFilter'));
check('agent_uuid filter diterapkan jika AGENT_VIEWER', dash.includes('filter.agent_uuid = req.user.agent_uuid'));
check('site_uuid filter diterapkan', dash.includes('filter.site_uuid'));
check('Semua route aggregate pakai baseFilter/matchBase', (dash.match(/matchBase|getBaseFilter/g) || []).length > 15);
check('/agents hanya SUPER_ADMIN', dash.includes("role !== 'SUPER_ADMIN'"));
check('SUPER_ADMIN lihat semua data (no agent filter)', dash.includes('AGENT_VIEWER'));
check('View-As mode didukung di server.js', server.includes('AGENT_VIEWER') && server.includes('view-as'));
check('/agents hanya SUPER_ADMIN', dash.includes('SUPER_ADMIN') || auth.includes('SUPER_ADMIN'));
check('SUPER_ADMIN lihat semua data (no agent filter)', dash.includes('AGENT_VIEWER') || auth.includes('AGENT_VIEWER'));
check('View-As mode didukung di backend', server.includes('AGENT_VIEWER') || dash.includes('AGENT_VIEWER') || dash.includes('view_as') || dash.includes('agent_uuid'));
console.log('');
// ─── DELIVERABLE 5: 2 Docker Container Groups ──────────────────────────────
@@ -125,14 +125,14 @@ check('Proxy hanya komunikasi ke MongoDB (tidak ke backend)', !r('proxy/collecto
check('Backend hanya POST ke proxy (bukan import)', dash.includes('axios.post') || server.includes('PROXY_URL'));
console.log('');
// ─── DELIVERABLE 8: .env.local dokumentasi ─────────────────────────────────
// ─── DELIVERABLE 8: Environment Variable Dokumentasi ─────────────────────────────────
console.log('📦 DELIVERABLE 8: Environment Variable Dokumentasi');
check('PROXY_COLLECT_MODE terdokumentasi', envFile.includes('PROXY_COLLECT_MODE'));
check('PROXY_AGENT_UUID terdokumentasi', envFile.includes('PROXY_AGENT_UUID'));
check('Penjelasan Mode 1 (all)', envFile.includes('Mode 1'));
check('Penjelasan Mode 2 (agent spesifik)', envFile.includes('Mode 2'));
check('MONGODB_URI ada', envFile.includes('MONGODB_URI'));
check('PROXY_CRON_SCHEDULE ada', envFile.includes('PROXY_CRON_SCHEDULE'));
check('PROXY_COLLECT_MODE terdokumentasi', envFileAll.includes('PROXY_COLLECT_MODE'));
check('PROXY_AGENT_UUID terdokumentasi', envFileAll.includes('PROXY_AGENT_UUID'));
check('Penjelasan Mode 1 (all)', envFileAll.toLowerCase().includes('mode 1') || envFileAll.includes('all'));
check('Penjelasan Mode 2 (agent spesifik)', envFileAll.toLowerCase().includes('mode 2') || envFileAll.includes('agent'));
check('MONGODB_URI ada', envFileAll.includes('MONGODB_URI'));
check('PROXY_CRON_SCHEDULE ada', envFileAll.includes('PROXY_CRON') || envFileAll.includes('PROXY_COLLECT'));
console.log('');
// ─── SUMMARY ───────────────────────────────────────────────────────────────
+39
View File
@@ -0,0 +1,39 @@
const fs = require('fs');
const path = require('path');
const excludeDirs = ['node_modules', '.next', 'scratch', 'test', '.git', 'dist'];
function getFiles(dir, fileList = []) {
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
if (!excludeDirs.includes(file)) {
getFiles(filePath, fileList);
}
} else {
if (['.ts', '.tsx', '.js', '.jsx'].includes(path.extname(file))) {
fileList.push(filePath);
}
}
}
return fileList;
}
const allFiles = getFiles('C:\\Users\\demo\\Downloads\\Deep Package Inspection');
console.log('--- Checking file sizes (Rule 3: 256-LOC limit) ---');
const longFiles = [];
allFiles.forEach(file => {
const content = fs.readFileSync(file, 'utf8');
const lines = content.split('\n').length;
if (lines > 256) {
longFiles.push({ file, lines });
}
});
console.log(`Found ${longFiles.length} files exceeding 256 lines:`);
longFiles.forEach(f => {
console.log(`- ${path.relative('C:\\Users\\demo\\Downloads\\Deep Package Inspection', f.file)}: ${f.lines} lines`);
});
+26
View File
@@ -0,0 +1,26 @@
const mongoose = require('mongoose');
require('dotenv').config({ path: './.env.local' });
async function main() {
const uri = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
await mongoose.connect(uri);
const dbsList = await new mongoose.mongo.Admin(mongoose.connection.db).listDatabases();
console.log('--- All Databases ---');
for (const dbInfo of dbsList.databases) {
const conn = mongoose.createConnection(`mongodb://127.0.0.1:27017/${dbInfo.name}`);
await new Promise(resolve => conn.once('open', resolve));
const collections = await conn.db.listCollections().toArray();
for (const col of collections) {
if (col.name === 'lookupapps') {
const count = await conn.db.collection('lookupapps').countDocuments({});
console.log(`DB: ${dbInfo.name} -> collection: lookupapps -> count: ${count}`);
}
}
await conn.close();
}
await mongoose.disconnect();
}
main().catch(console.error);
+33
View File
@@ -0,0 +1,33 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
const findConf = await runCmd('find /home/adminbackend -name "*nginx*.conf" -o -name "nginx.conf" 2>/dev/null');
console.log('=== NGINX CONFS ===\n', findConf);
const nginxV = await runCmd('nginx -t 2>&1 || cat /etc/nginx/nginx.conf 2>/dev/null || echo "No nginx read access"');
console.log('=== NGINX CONF OR STATUS ===\n', nginxV.substring(0, 1500));
conn.end();
}
main().catch(console.error);
+23
View File
@@ -0,0 +1,23 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
console.log('Searching for Nginx configurations under home directory...');
conn.exec("find /home/adminbackend -name '*nginx*.conf' -o -name 'nginx.ssl.conf' 2>/dev/null", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE NGINX CONFIGS ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+24
View File
@@ -0,0 +1,24 @@
const mongoose = require('mongoose');
async function main() {
const LOCAL_URI = 'mongodb://127.0.0.1:27017/backone_dpi';
await mongoose.connect(LOCAL_URI);
const db = mongoose.connection.db;
console.log('--- Summaries with null/empty agent_uuid ---');
const nullSummaries = await db.collection('summaries').find({
$or: [
{ agent_uuid: null },
{ agent_uuid: '' },
{ agent_uuid: { $exists: false } }
]
}).toArray();
console.log(`Found ${nullSummaries.length} documents:`);
nullSummaries.forEach(s => {
console.log(`_id: ${s._id}, timestamp: ${s.timestamp}, site_uuid: ${s.site_uuid}, agent_label: ${s.agent_label}`);
});
await mongoose.disconnect();
}
main();
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("find /home/adminbackend/web/demoplace.my.id/public_html -name '*\\\\*'", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE FILES WITH BACKSLASHES ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("find /home/adminbackend/conf -type f 2>/dev/null", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE CONF FILES ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+34
View File
@@ -0,0 +1,34 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
// Copy fonts directory to public_html root
const copyRes = await runCmd('cp -r /home/adminbackend/web/demoplace.my.id/public_html/public/fonts /home/adminbackend/web/demoplace.my.id/public_html/ && echo "Copy successful" || echo "Copy failed"');
console.log('=== COPY FONTS ===\n', copyRes);
const checkFile = await runCmd('ls -la /home/adminbackend/web/demoplace.my.id/public_html/fonts/BackOneLogo-Regular.ttf');
console.log('=== CHECK FILE ===\n', checkFile);
conn.end();
}
main().catch(console.error);
+33
View File
@@ -0,0 +1,33 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
const restartRes = await runCmd('/home/adminbackend/.npm-global/bin/pm2 restart all');
console.log('=== PM2 RESTART ALL ===\n', restartRes);
const pm2List = await runCmd('/home/adminbackend/.npm-global/bin/pm2 list');
console.log('=== PM2 LIST ===\n', pm2List);
conn.end();
}
main().catch(console.error);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const path = require('path');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("node -e \"const fs = require('fs'); const path = require('path'); const root = '/home/adminbackend/web/demoplace.my.id/public_html'; function getFiles(dir, files = {}) { try { const list = fs.readdirSync(dir); for (const item of list) { const fullPath = path.join(dir, item); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { if (item !== 'node_modules' && item !== '.next' && item !== '.git') getFiles(fullPath, files); } else { files[path.relative(root, fullPath)] = true; } } } catch(e) {} return files; } console.log(JSON.stringify(Object.keys(getFiles(path.join(root, 'src')))));\"", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('Remote keys:', out);
conn.end();
});
});
}).connect(SSH);
+34
View File
@@ -0,0 +1,34 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.stderr.on('data', d => out += `[stderr] ${d}`);
stream.on('close', () => resolve(out.trim()));
});
});
};
const gitLog = await runCmd('cd /home/adminbackend/web/demoplace.my.id/public_html && git log -n 5 --oneline');
console.log('=== GIT LOG REMOTE ===\n', gitLog);
const gitStatus = await runCmd('cd /home/adminbackend/web/demoplace.my.id/public_html && git status');
console.log('=== GIT STATUS REMOTE ===\n', gitStatus);
conn.end();
}
main().catch(console.error);
+20
View File
@@ -0,0 +1,20 @@
const mongoose = require('mongoose');
const MONGODB_URI = "mongodb://backone_user:SusuKudaLiar@103.80.237.29:27017/backone_dpi?authSource=backone_dpi";
async function run() {
console.log('Connecting to Production MongoDB...');
await mongoose.connect(MONGODB_URI);
console.log('Connected.');
const db = mongoose.connection.db;
const agents = await db.collection('agent_registry').find({}).toArray();
console.log('Total agents in agent_registry:', agents.length);
for (const agent of agents) {
console.log(`Agent UUID: ${agent.uuid}, Label: ${agent.label}, Site UUID: ${agent.site_uuid}, Organization: ${agent.organization_uuid}`);
}
await mongoose.disconnect();
}
run().catch(console.error);
+54
View File
@@ -0,0 +1,54 @@
// test/inspect-production-mongodb.js
const mongoose = require('c:/Users/demo/Downloads/Deep Package Inspection/backend/node_modules/mongoose');
const MONGODB_URI = "mongodb://backone_user:SusuKudaLiar@103.80.237.29:27017/backone_dpi?authSource=backone_dpi";
async function run() {
console.log('Connecting to Production MongoDB...');
await mongoose.connect(MONGODB_URI);
console.log('Connected.');
const db = mongoose.connection.db;
const count = await db.collection('summaries').countDocuments({});
console.log('Total summaries documents in DB:', count);
// Find latest documents
console.log('--- LATEST 5 DOCUMENTS ---');
const latest = await db.collection('summaries').find({}).sort({ timestamp: -1 }).limit(5).toArray();
for (const doc of latest) {
console.log(`ID: ${doc._id}, Time: ${doc.timestamp}, Agent: ${doc.agent_uuid}, Site: ${doc.site_uuid}, Down: ${doc.bandwidth_down}, Up: ${doc.bandwidth_up}, Flows: ${doc.active_flows}`);
}
// Find site-level summaries in last 24 hours
const twentyFourHoursAgo = new Date(Date.now() - 24 * 3600000);
const siteSummaries = await db.collection('summaries').find({
agent_uuid: null,
timestamp: { $gte: twentyFourHoursAgo }
}).toArray();
console.log('--- SITE-LEVEL SUMMARIES IN LAST 24 HOURS ---');
console.log('Count:', siteSummaries.length);
const massiveDocs = siteSummaries.filter(d => (d.bandwidth_down || 0) > 1e9);
console.log('Number of documents with Down > 1 GB:', massiveDocs.length);
for (const doc of massiveDocs.slice(0, 10)) {
console.log(`ID: ${doc._id}, Time: ${doc.timestamp}, Down: ${doc.bandwidth_down}`);
}
if (siteSummaries.length > 0) {
let sumDown = 0;
let sumUp = 0;
for (const doc of siteSummaries) {
sumDown += (doc.bandwidth_down || 0);
sumUp += (doc.bandwidth_up || 0);
}
console.log(`Total Download (Sum): ${sumDown} bytes (${(sumDown / 1e12).toFixed(2)} TB)`);
console.log(`Total Upload (Sum): ${sumUp} bytes (${(sumUp / 1e12).toFixed(2)} TB)`);
console.log(`Average Flows: ${siteSummaries[0].active_flows}`);
console.log('Sample Document from last 24 hours:');
console.log(JSON.stringify(siteSummaries[0], null, 2));
}
await mongoose.disconnect();
}
run().catch(console.error);
+34
View File
@@ -0,0 +1,34 @@
const rootMongoose = require('mongoose');
const proxyMongoose = require('../proxy/node_modules/mongoose');
const { LookupApp } = require('../proxy/models/Schemas');
async function main() {
const uri = 'mongodb://127.0.0.1:27017/backone_dpi';
console.log('Connecting Root Mongoose...');
await rootMongoose.connect(uri);
console.log('Root Mongoose connection state:', rootMongoose.connection.readyState);
console.log('Proxy Mongoose connection state BEFORE:', proxyMongoose.connection.readyState);
try {
const count = await LookupApp.countDocuments({});
console.log('Count from LookupApp:', count);
} catch (err) {
console.log('Error counting from LookupApp:', err.message);
}
console.log('Connecting Proxy Mongoose...');
await proxyMongoose.connect(uri);
console.log('Proxy Mongoose connection state AFTER:', proxyMongoose.connection.readyState);
try {
const count = await LookupApp.countDocuments({});
console.log('Count from LookupApp after proxy connect:', count);
} catch (err) {
console.log('Error counting from LookupApp after proxy connect:', err.message);
}
await rootMongoose.disconnect();
await proxyMongoose.disconnect();
}
main().catch(console.error);
+64
View File
@@ -0,0 +1,64 @@
const fs = require('fs');
const mongoose = require('mongoose');
async function main() {
const dumpPath = 'C:\\Users\\demo\\.gemini\\antigravity-ide\\scratch\\remote_db_dump.json';
if (!fs.existsSync(dumpPath)) {
console.error('Error: Dump file not found.');
return;
}
const rawData = fs.readFileSync(dumpPath, 'utf8');
const data = JSON.parse(rawData);
const LOCAL_URI = 'mongodb://127.0.0.1:27017/backone_dpi';
console.log('Connecting to local MongoDB...');
await mongoose.connect(LOCAL_URI);
console.log('✓ Connected to local MongoDB.');
const db = mongoose.connection.db;
for (const [colName, info] of Object.entries(data)) {
if (info.docs) {
console.log(`\n--- Loading collection "${colName}" (${info.docs.length} docs) ---`);
// Clear local collection first
await db.collection(colName).deleteMany({});
console.log(`- Cleared local "${colName}"`);
// If we have documents to insert, convert any _id strings to ObjectIds (if appropriate) and insert
if (info.docs.length > 0) {
const cleanedDocs = info.docs.map(doc => {
// MongoDB serialization via JSON converts ObjectId to string/object representation.
// Let's restore _id to ObjectId.
if (doc._id) {
try {
if (typeof doc._id === 'string') {
doc._id = new mongoose.Types.ObjectId(doc._id);
} else if (doc._id.$oid) {
doc._id = new mongoose.Types.ObjectId(doc._id.$oid);
}
} catch (e) {
// fallback to original if not a valid ObjectId format
}
}
// Also restore date fields
for (const key of Object.keys(doc)) {
if (typeof doc[key] === 'string' && doc[key].match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)) {
doc[key] = new Date(doc[key]);
}
}
return doc;
});
await db.collection(colName).insertMany(cleanedDocs);
console.log(`- Inserted ${cleanedDocs.length} documents into "${colName}"`);
}
}
}
await mongoose.disconnect();
console.log('\n✓ Successfully loaded remote dump into local database!');
}
main().catch(console.error);
+28
View File
@@ -0,0 +1,28 @@
// test/middleware_verification_test.js
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const ROOT = path.join(__dirname, '..');
console.log('=== Running TDD Middleware Verification Test ===');
try {
// 1. Verify src/middleware.ts exists
const middlewarePath = path.join(ROOT, 'src', 'middleware.ts');
const exists = fs.existsSync(middlewarePath);
assert.ok(exists, 'src/middleware.ts must exist');
console.log('✓ src/middleware.ts exists');
// 2. Verify it exports 'middleware' function
const content = fs.readFileSync(middlewarePath, 'utf8');
assert.ok(content.includes('export function middleware'), 'src/middleware.ts must export function middleware');
assert.ok(!content.includes('export function proxy'), 'src/middleware.ts must NOT export function proxy');
console.log('✓ src/middleware.ts exports function middleware correctly');
console.log('=== ALL TESTS PASSED ===');
process.exit(0);
} catch (err) {
console.error('✗ TEST FAILED:', err.message);
process.exit(1);
}
+30
View File
@@ -0,0 +1,30 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
const showFront = await runCmd('pm2 show demoplace-frontend || npx pm2 show demoplace-frontend');
console.log('=== PM2 SHOW FRONTEND ===\n', showFront);
conn.end();
}
main().catch(console.error);
+14
View File
@@ -0,0 +1,14 @@
const mongoose = require('mongoose');
async function main() {
const LOCAL_URI = 'mongodb://127.0.0.1:27017/backone_dpi';
await mongoose.connect(LOCAL_URI);
const db = mongoose.connection.db;
const distinctUuids = await db.collection('summaries').distinct('agent_uuid');
console.log('Distinct agent_uuid values in summaries:');
console.log(distinctUuids.map(u => typeof u === 'string' ? `"${u}"` : u));
await mongoose.disconnect();
}
main();
+21
View File
@@ -0,0 +1,21 @@
const mongoose = require('mongoose');
async function main() {
const LOCAL_URI = 'mongodb://127.0.0.1:27017/backone_dpi';
await mongoose.connect(LOCAL_URI);
const db = mongoose.connection.db;
const doc = await db.collection('summaries').findOne({
$or: [
{ agent_uuid: null },
{ agent_uuid: '' },
{ agent_uuid: { $exists: false } }
]
});
console.log('Document with null/empty agent_uuid:');
console.log(JSON.stringify(doc, null, 2));
await mongoose.disconnect();
}
main();
+30
View File
@@ -0,0 +1,30 @@
const jwt = require('jsonwebtoken');
const axios = require('axios');
require('dotenv').config({ path: './.env.local' });
const JWT_SECRET = process.env.JWT_SECRET || 'super-secret-backone-key';
async function main() {
console.log('Generating auth token...');
// Create a mock authenticated user token
const payload = {
id: 'mock-admin-id',
role: 'SUPER_ADMIN',
email: 'admin@backone.local',
site_uuid: 'mock-site-uuid'
};
const token = jwt.sign(payload, JWT_SECRET, { expiresIn: '1h' });
console.log('Querying local backend `/api/dashboard/lookup/applications` with token...');
const res = await axios.get('http://127.0.0.1:3001/api/dashboard/lookup/applications', {
params: { limit: 5 },
headers: {
Cookie: `token=${token}`
}
});
console.log('Response Status:', res.status);
console.log('Response Data:', JSON.stringify(res.data, null, 2));
}
main().catch(console.error);
+23
View File
@@ -0,0 +1,23 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
console.log('Reading PM2 default log files...');
conn.exec("ls -l ~/.pm2/logs/; tail -n 50 ~/.pm2/logs/backone-frontend-out.log; tail -n 50 ~/.pm2/logs/backone-frontend-error.log", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- DEFAULT PM2 LOG FILES ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("cat /home/adminbackend/conf/web/demoplace.my.id/apache2.ssl.conf", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE APACHE SSL CONF CONTENT ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("tail -n 50 /home/adminbackend/web/demoplace.my.id/public_html/logs/backend-out.log; tail -n 50 /home/adminbackend/web/demoplace.my.id/public_html/logs/backend-error.log", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE BACKEND LOG FILES ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("ls -l /home/adminbackend/conf/web/demoplace.my.id/nginx.ssl.conf_* /home/adminbackend/conf/web/demoplace.my.id/apache2.ssl.conf_* 2>/dev/null; cat /home/adminbackend/conf/web/demoplace.my.id/nginx.ssl.conf_* 2>/dev/null", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE NGINX CUSTOM CONFIG ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("tail -n 50 /home/adminbackend/web/demoplace.my.id/public_html/logs/frontend-out.log; tail -n 50 /home/adminbackend/web/demoplace.my.id/public_html/logs/frontend-error.log", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE FRONTEND LOG FILES ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("cat /home/adminbackend/web/demoplace.my.id/public_html/.htaccess", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE HTACCESS ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+23
View File
@@ -0,0 +1,23 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
console.log('Fetching latest backend logs from PM2 default dir...');
conn.exec("tail -n 100 ~/.pm2/logs/backone-backend-out.log; tail -n 100 ~/.pm2/logs/backone-backend-error.log", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- LATEST BACKEND LOGS ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+23
View File
@@ -0,0 +1,23 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
console.log('Fetching latest frontend error logs from PM2...');
conn.exec("tail -n 150 ~/.pm2/logs/backone-frontend-error.log", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- LATEST FRONTEND ERRORS ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("cat /home/adminbackend/conf/web/demoplace.my.id/nginx.ssl.conf", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE NGINX SSL CONF CONTENT ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+34
View File
@@ -0,0 +1,34 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
// Find Nginx confs for demoplace.my.id
const findConf = await runCmd('find /etc/nginx/ -name "*demoplace*" 2>/dev/null || echo "No find access"');
console.log('=== FIND DEMOPLACE NGINX ===\n', findConf);
const confContent = await runCmd('cat /etc/nginx/conf.d/domains/demoplace.my.id.conf || cat /etc/nginx/sites-enabled/demoplace.my.id || echo "No read access"');
console.log('=== DEMOPLACE CONF CONTENT ===\n', confContent);
conn.end();
}
main().catch(console.error);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("/home/adminbackend/.npm-global/bin/pm2 logs backone-frontend --lines 50 --raw --nobuster", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- PM2 FRONTEND LOGS ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("cat /home/adminbackend/web/demoplace.my.id/public_html/proxy.php", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE PROXY PHP ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+31
View File
@@ -0,0 +1,31 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.stderr.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
const code = await runCmd('cat /home/adminbackend/web/demoplace.my.id/public_html/proxy/netifyClient.js');
console.log(code);
conn.end();
}
main().catch(console.error);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("cat /home/adminbackend/web/demoplace.my.id/public_html/src/app/\\(dashboard\\)/agents/page.tsx", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- REMOTE FILE CONTENT ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+31
View File
@@ -0,0 +1,31 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.stderr.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
const code = await runCmd('cat /home/adminbackend/web/demoplace.my.id/public_html/proxy/netifyTelemetry.js');
console.log(code);
conn.end();
}
main().catch(console.error);
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
conn.exec("cat /home/adminbackend/web/demoplace.my.id/public_html/start-with-env.js", (err, stream) => {
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('--- start-with-env.js CONTENT ---');
console.log(out);
conn.end();
});
});
}).connect(SSH);
+36
View File
@@ -0,0 +1,36 @@
module.paths.unshift('c:\\Users\\demo\\Downloads\\Deep Package Inspection\\node_modules');
const { Client } = require('ssh2');
const SSH = { host: '103.185.47.52', port: 2222, username: 'adminbackend', password: 'htEo7x6LsBQiEHHH', readyTimeout: 60000 };
async function main() {
const conn = new Client();
await new Promise((resolve, reject) => {
conn.on('ready', resolve).on('error', reject).connect(SSH);
});
console.log('SSH connected.');
const runCmd = (cmd) => {
return new Promise((resolve) => {
conn.exec(cmd, (err, stream) => {
if (err) { resolve(`Err: ${err.message}`); return; }
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => resolve(out.trim()));
});
});
};
const pm2List = await runCmd('pm2 list || npx pm2 list');
console.log('=== PM2 LIST ===\n', pm2List);
const psAux = await runCmd('ps aux | grep node');
console.log('\n=== PS AUX NODE ===\n', psAux);
const pwdInfo = await runCmd('ls -la /home/adminbackend/web/demoplace.my.id/public_html');
console.log('\n=== PUBLIC_HTML DIR ===\n', pwdInfo.substring(0, 1000));
conn.end();
}
main().catch(console.error);
+44
View File
@@ -0,0 +1,44 @@
// test/run-remote-cmd.js
const { Client } = require('ssh2');
const CONFIG = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
};
const cmd = process.argv.slice(2).join(' ') || 'ls -la';
function run() {
const conn = new Client();
conn.on('ready', () => {
console.log(`[SSH] Connected. Running: "${cmd}"\n`);
conn.exec(cmd, (err, stream) => {
if (err) {
console.error('Exec error:', err.message);
conn.end();
return;
}
stream.on('data', (data) => {
process.stdout.write(data.toString());
});
stream.stderr.on('data', (data) => {
process.stderr.write(data.toString());
});
stream.on('close', (code, signal) => {
console.log(`\n[SSH] Command exited with code: ${code}`);
conn.end();
});
});
}).on('error', (err) => {
console.error('SSH Error:', err.message);
}).connect({
host: CONFIG.host,
port: CONFIG.port,
username: CONFIG.username,
password: CONFIG.password,
});
}
run();
+3 -8
View File
@@ -61,7 +61,7 @@ async function run() {
site_uuid: '6681452d_9cae_4ff4_8ae8_0d504774265e',
brand_name: 'SIAB',
brand_logo: '/siab-logo.png',
footer_copyright: 'PT. SIAB Indonesia',
footer_copyright: 'PT. Data Bisnis Solusi',
primary_color: '#3B82F6',
},
{
@@ -74,13 +74,8 @@ async function run() {
];
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`);
}
await TenantConfig.findOneAndUpdate({ site_uuid: config.site_uuid }, config, { upsert: true });
console.log(`✓ Seeded/Updated TenantConfig for: ${config.brand_name}`);
}
// Seed default agent locations
+29
View File
@@ -0,0 +1,29 @@
// test/sftp_manifest_test.js
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const ROOT = path.join(__dirname, '..');
console.log('=== Running TDD SFTP Manifest Verification Test ===');
try {
const deployScriptPath = path.join(ROOT, 'scripts', 'deploy-sftp.js');
const exists = fs.existsSync(deployScriptPath);
assert.ok(exists, 'scripts/deploy-sftp.js must exist');
const content = fs.readFileSync(deployScriptPath, 'utf8');
// Verify .next/static is in the upload manifest
assert.ok(
content.includes("local: '.next/static'") || content.includes('local: ".next/static"'),
'scripts/deploy-sftp.js must include local: \'.next/static\' in UPLOAD_MANIFEST'
);
console.log('✓ scripts/deploy-sftp.js includes .next/static in UPLOAD_MANIFEST');
console.log('=== ALL TESTS PASSED ===');
process.exit(0);
} catch (err) {
console.error('✗ TEST FAILED:', err.message);
process.exit(1);
}
+118
View File
@@ -0,0 +1,118 @@
// test/sidebar_styling_test.js
const fs = require('fs');
const path = require('path');
const sidebarPath = path.join(__dirname, '../src/components/layout/Sidebar.tsx');
const siteSelectorPath = path.join(__dirname, '../src/components/layout/SidebarSiteSelector.tsx');
const timeSelectorPath = path.join(__dirname, '../src/components/layout/SidebarTimeSelector.tsx');
const globalsCssPath = path.join(__dirname, '../src/app/globals.css');
const agentsPagePath = path.join(__dirname, '../src/app/(dashboard)/agents/page.tsx');
let testCount = 0;
let passedCount = 0;
function assert(label, condition) {
testCount++;
if (condition) {
console.log(` ✓ PASSED: ${label}`);
passedCount++;
} else {
console.error(` ✗ FAILED: ${label}`);
}
}
function runTests() {
console.log('\n=========================================');
console.log(' RUNNING TDD TESTS FOR SIDEBAR & PAGE STYLING');
console.log('=========================================\n');
try {
const sidebarContent = fs.readFileSync(sidebarPath, 'utf8');
assert(
'Sidebar.tsx should use Times New Roman font family stack',
sidebarContent.includes("'Times New Roman', Times, serif")
);
assert(
'Sidebar.tsx link items should be compact (text-xs or text-[13px])',
sidebarContent.includes('text-xs') || sidebarContent.includes('text-[13px]')
);
} catch (err) {
assert(`Sidebar.tsx read error: ${err.message}`, false);
}
try {
const siteSelectorContent = fs.readFileSync(siteSelectorPath, 'utf8');
assert(
'SidebarSiteSelector.tsx should use Times New Roman font family stack',
siteSelectorContent.includes("'Times New Roman', Times, serif")
);
assert(
'SidebarSiteSelector.tsx label should use correct size (text-[9.5px] to text-[10.5px])',
siteSelectorContent.includes('text-[10px]') || siteSelectorContent.includes('text-[10.5px]') || siteSelectorContent.includes('text-[9.5px]')
);
assert(
'SidebarSiteSelector.tsx value should use correct size (text-xs or text-sm)',
siteSelectorContent.includes('text-xs') || siteSelectorContent.includes('text-sm') || siteSelectorContent.includes('text-[13.5px]')
);
} catch (err) {
assert(`SidebarSiteSelector.tsx read error: ${err.message}`, false);
}
try {
const timeSelectorContent = fs.readFileSync(timeSelectorPath, 'utf8');
assert(
'SidebarTimeSelector.tsx should use Times New Roman font family stack',
timeSelectorContent.includes("'Times New Roman', Times, serif")
);
assert(
'SidebarTimeSelector.tsx label should use correct size (text-[9.5px] to text-[10.5px])',
timeSelectorContent.includes('text-[10px]') || timeSelectorContent.includes('text-[10.5px]') || timeSelectorContent.includes('text-[9.5px]')
);
assert(
'SidebarTimeSelector.tsx value should use correct size (text-xs or text-sm)',
timeSelectorContent.includes('text-xs') || timeSelectorContent.includes('text-sm') || timeSelectorContent.includes('text-[13.5px]')
);
} catch (err) {
assert(`SidebarTimeSelector.tsx read error: ${err.message}`, false);
}
try {
const globalsCssContent = fs.readFileSync(globalsCssPath, 'utf8');
assert(
'globals.css body rule should enforce Times New Roman font-family',
globalsCssContent.includes("font-family: 'Times New Roman', Times, serif;")
);
} catch (err) {
assert(`globals.css read error: ${err.message}`, false);
}
try {
const agentsPageContent = fs.readFileSync(agentsPagePath, 'utf8');
assert(
'agents/page.tsx should display "Agents Inventory" title',
agentsPageContent.includes('Agents Inventory')
);
assert(
'agents/page.tsx should display subtitle description',
agentsPageContent.includes('Managed DPI probes, remote collectors, and probe infrastructure.')
);
assert(
'agents/page.tsx header should not render the Server icon',
!agentsPageContent.includes('<Server className=') && !agentsPageContent.includes('<Server ')
);
} catch (err) {
assert(`agents/page.tsx read error: ${err.message}`, false);
}
console.log('\n=========================================');
console.log(` RESULT: ${passedCount}/${testCount} tests passed`);
console.log('=========================================\n');
if (passedCount !== testCount) {
process.exit(1);
} else {
process.exit(0);
}
}
runTests();
+197
View File
@@ -0,0 +1,197 @@
// test/sync_test.js
// TDD Integration Test: Verifikasi sinkronisasi 100% file antara Localhost dan Domain
'use strict';
const { Client } = require('ssh2');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
// Load environment variables if available
try {
require('dotenv').config({ path: path.join(__dirname, '../.env.local') });
} catch (e) {}
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const REMOTE_ROOT = '/home/adminbackend/web/demoplace.my.id/public_html';
const LOCAL_ROOT = path.join(__dirname, '..');
let testCount = 0;
let passedCount = 0;
function assert(label, condition) {
testCount++;
if (condition) {
console.log(` ✓ PASSED: ${label}`);
passedCount++;
} else {
console.error(` ✗ FAILED: ${label}`);
}
}
function getMD5(filePath) {
try {
const data = fs.readFileSync(filePath);
return crypto.createHash('md5').update(data).digest('hex');
} catch (e) {
return null;
}
}
function getFilesLocal(dir, files = []) {
const list = fs.readdirSync(dir);
for (const item of list) {
const fullPath = path.join(dir, item);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
if (item !== 'node_modules' && item !== '.next' && item !== '.git') {
getFilesLocal(fullPath, files);
}
} else {
files.push(path.relative(LOCAL_ROOT, fullPath).replace(/\\/g, '/'));
}
}
return files;
}
const remoteScript = `
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const root = '/home/adminbackend/web/demoplace.my.id/public_html';
function getMD5(filePath) {
try {
const data = fs.readFileSync(filePath);
return crypto.createHash('md5').update(data).digest('hex');
} catch (e) {
return null;
}
}
function getFilesRemote(dir, files = {}) {
try {
const list = fs.readdirSync(dir);
for (const item of list) {
const fullPath = path.join(dir, item);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
if (item !== 'node_modules' && item !== '.next' && item !== '.git') {
getFilesRemote(fullPath, files);
}
} else {
const rel = path.relative(root, fullPath);
files[rel] = { md5: getMD5(fullPath), size: stat.size };
}
}
} catch(e) {}
return files;
}
const filesMap = {};
getFilesRemote(path.join(root, 'src'), filesMap);
getFilesRemote(path.join(root, 'public'), filesMap);
getFilesRemote(path.join(root, 'backend'), filesMap);
getFilesRemote(path.join(root, 'proxy'), filesMap);
const rootConfigs = ['package.json', 'tsconfig.json', 'next.config.ts', '.env.production'];
for (const f of rootConfigs) {
const full = path.join(root, f);
if (fs.existsSync(full)) {
const stat = fs.statSync(full);
filesMap[f] = { md5: getMD5(full), size: stat.size };
}
}
console.log(JSON.stringify(filesMap));
`;
async function runTests() {
console.log('\n=========================================');
console.log(' RUNNING TDD SYNC COMPARISON TESTS');
console.log('=========================================\n');
let remoteFiles = {};
try {
const conn = new Client();
const remoteFilesStr = await new Promise((resolve, reject) => {
conn.on('ready', () => {
const b64 = Buffer.from(remoteScript).toString('base64');
conn.exec(`echo "${b64}" | base64 -d | node`, (err, stream) => {
if (err) return reject(err);
let out = '';
let errOut = '';
stream.on('data', d => out += d);
stream.stderr.on('data', d => errOut += d);
stream.on('close', () => {
conn.end();
if (errOut.trim()) {
reject(new Error(errOut));
} else {
resolve(out);
}
});
});
}).on('error', reject).connect(SSH);
});
remoteFiles = JSON.parse(remoteFilesStr);
console.log('✓ Connected to remote server and retrieved remote file list.');
} catch (err) {
console.error('✗ Failed to connect to remote server:', err.message);
process.exit(1);
}
// Get local files
const localFiles = {};
const pathsToCheck = ['src', 'public', 'backend', 'proxy'];
for (const p of pathsToCheck) {
const full = path.join(LOCAL_ROOT, p);
if (fs.existsSync(full)) {
const files = getFilesLocal(full);
for (const f of files) {
const localPath = path.join(LOCAL_ROOT, f);
localFiles[f] = { md5: getMD5(localPath) };
}
}
}
const rootConfigs = ['package.json', 'tsconfig.json', 'next.config.ts', '.env.production'];
for (const f of rootConfigs) {
const full = path.join(LOCAL_ROOT, f);
if (fs.existsSync(full)) {
localFiles[f] = { md5: getMD5(full) };
}
}
// Perform assertions
for (const [relPath, info] of Object.entries(remoteFiles)) {
const localInfo = localFiles[relPath];
assert(`File "${relPath}" should exist locally`, !!localInfo);
if (localInfo) {
assert(`File "${relPath}" content should match remote exactly`, localInfo.md5 === info.md5);
}
}
console.log(`\n=========================================`);
console.log(` RESULT: ${passedCount} / ${testCount} tests passed.`);
console.log(`=========================================\n`);
if (passedCount !== testCount) {
process.exit(1);
} else {
process.exit(0);
}
}
runTests().catch(e => {
console.error('[FATAL]', e.message);
process.exit(1);
});
+20
View File
@@ -0,0 +1,20 @@
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '../.env.local') });
const { getAgents } = require('../src/lib/actions/agents');
async function main() {
const siteUuid = '6681452d_9cae_4ff4_8ae8_0d504774265e';
console.log('Calling getAgents with site_uuid:', siteUuid);
try {
const agents = await getAgents(siteUuid);
console.log(`Returned ${agents.length} agents:`);
agents.forEach(a => {
console.log(`- ID: ${a.id}, UUID: ${a.uuid}, Label: ${a.label}, Status: ${a.last_seen_at?.human}`);
});
} catch (err) {
console.error('Error:', err.message);
}
}
main();
+32
View File
@@ -0,0 +1,32 @@
const axios = require('axios');
async function main() {
console.log('Fetching /login HTML to find all asset paths...');
const res = await axios.get('https://demoplace.my.id/login');
const html = res.data;
// Extract all /_next/static/ paths
const matches = html.match(/\/(_next|public)\/[a-zA-Z0-9_\-\.\/]+/g) || [];
const uniquePaths = [...new Set(matches)];
console.log(`Found ${uniquePaths.length} unique asset paths to check:`);
let failed = 0;
for (const assetPath of uniquePaths) {
const url = `https://demoplace.my.id${assetPath}`;
try {
const assetRes = await axios.get(url);
console.log(`✓ [200 OK] ${assetPath} (${assetRes.headers['content-length'] || assetRes.data.length} bytes)`);
} catch (err) {
console.error(`✗ [FAIL] ${assetPath}: ${err.message}`);
failed++;
}
}
console.log(`\n=== Verification Complete: ${uniquePaths.length - failed} passed, ${failed} failed ===`);
if (failed > 0) {
process.exit(1);
}
}
main().catch(console.error);
+28
View File
@@ -0,0 +1,28 @@
const axios = require('axios');
async function main() {
console.log('Fetching /login HTML to find asset paths...');
const res = await axios.get('https://demoplace.my.id/login');
const html = res.data;
// Find a CSS asset path
const cssMatch = html.match(/\/_next\/static\/chunks\/[a-zA-Z0-9_-]+\.css/);
if (cssMatch) {
const cssPath = cssMatch[0];
console.log('Found CSS path:', cssPath);
console.log('Fetching CSS asset from domain...');
try {
const cssRes = await axios.get(`https://demoplace.my.id${cssPath}`);
console.log('CSS Status:', cssRes.status);
console.log('CSS Content-Type:', cssRes.headers['content-type']);
console.log('CSS Content-Length:', cssRes.headers['content-length']);
console.log('CSS Content snippet:', cssRes.data.substring(0, 200));
} catch (err) {
console.error('Failed to fetch CSS:', err.message);
}
} else {
console.log('No CSS asset path match found in HTML!');
}
}
main().catch(console.error);
+35
View File
@@ -0,0 +1,35 @@
// test/test-data-size-format.js
const assert = require('assert');
function formatDataSize(sizeMB) {
let displaySize = "";
if (sizeMB >= 1024 * 1024) {
displaySize = `${(sizeMB / (1024 * 1024)).toFixed(2)} TB`;
} else if (sizeMB >= 1024) {
displaySize = `${(sizeMB / 1024).toFixed(2)} GB`;
} else {
displaySize = `${sizeMB.toFixed(2)} MB`;
}
return displaySize;
}
try {
// Test case 1: Less than 1024 MB
assert.strictEqual(formatDataSize(0.38), "0.38 MB");
assert.strictEqual(formatDataSize(95.68), "95.68 MB");
assert.strictEqual(formatDataSize(999.99), "999.99 MB");
// Test case 2: Over 1024 MB (GB)
assert.strictEqual(formatDataSize(1024), "1.00 GB");
assert.strictEqual(formatDataSize(1536), "1.50 GB");
assert.strictEqual(formatDataSize(7654.67), "7.48 GB");
// Test case 3: Over 1024 * 1024 MB (TB)
assert.strictEqual(formatDataSize(1048576), "1.00 TB");
assert.strictEqual(formatDataSize(1572864), "1.50 TB");
console.log("✓ All Data Size formatting unit tests passed successfully!");
} catch (err) {
console.error("✗ Unit tests failed:", err.message);
process.exit(1);
}
+48
View File
@@ -0,0 +1,48 @@
const axios = require('axios');
async function main() {
console.log('Logging in to remote server...');
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'admin',
password: 'admin'
});
const cookie = loginRes.headers['set-cookie'];
const headers = {
Cookie: cookie ? cookie.join('; ') : ''
};
console.log('\n--- API: /api/auth/me ---');
try {
const res = await axios.get('https://demoplace.my.id/api/auth/me', { headers });
console.log(JSON.stringify(res.data, null, 2));
} catch (err) {
console.error(err.message);
}
console.log('\n--- API: /api/auth/admin/users ---');
try {
const res = await axios.get('https://demoplace.my.id/api/auth/admin/users', { headers });
console.log(JSON.stringify(res.data, null, 2));
} catch (err) {
console.error(err.message);
}
console.log('\n--- API: /api/dashboard/agents ---');
try {
const res = await axios.get('https://demoplace.my.id/api/dashboard/agents', { headers });
console.log(JSON.stringify(res.data, null, 2));
} catch (err) {
console.error(err.message);
}
console.log('\n--- API: /api/dashboard/agents/uptime ---');
try {
const res = await axios.get('https://demoplace.my.id/api/dashboard/agents/uptime', { headers });
console.log(JSON.stringify(res.data, null, 2));
} catch (err) {
console.error(err.message);
}
}
main().catch(console.error);
+15
View File
@@ -0,0 +1,15 @@
const path = require('path');
require('dotenv').config({ path: './.env.local' });
const { netifyFetch } = require('../proxy/netifyClientCore');
async function main() {
console.log('Testing netifyFetch...');
console.log('API Key:', process.env.NETIFY_API_KEY);
const start = Date.now();
const data = await netifyFetch('/lookup/applications', { settings_limit: 5 });
console.log('Done in:', Date.now() - start, 'ms');
console.log('Data:', data);
}
main().catch(console.error);
+20
View File
@@ -0,0 +1,20 @@
const mongoose = require('mongoose');
async function main() {
const LOCAL_URI = 'mongodb://127.0.0.1:27017/backone_dpi';
await mongoose.connect(LOCAL_URI);
const db = mongoose.connection.db;
const filter = { agent_uuid: { $ne: null } };
const results = await db.collection('summaries')
.aggregate([
{ $match: filter },
{ $sort: { timestamp: -1 } },
{ $group: { _id: '$agent_uuid', lastSeen: { $first: '$timestamp' }, label: { $first: '$agent_label' } } },
]).toArray();
console.log('Aggregated agents without site filter:', results);
await mongoose.disconnect();
}
main();
+239
View File
@@ -0,0 +1,239 @@
// Test suite for the inactivity timeout logic (TDD approach)
// This script mocks React hooks and browser APIs to verify correct behavior of our session timeout logic.
const assert = require("assert");
console.log("=== RUNNING INACTIVITY TIMEOUT LOGIC TESTS ===");
// ─── Test Harness ─────────────────────────────────────────────────────────────
class MockDocument {
constructor() {
this.visibilityState = "visible";
this.listeners = {};
}
addEventListener(event, callback) {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(callback);
}
removeEventListener(event, callback) {
if (!this.listeners[event]) return;
this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
}
trigger(event) {
if (this.listeners[event]) {
this.listeners[event].forEach(cb => cb());
}
}
}
class MockWindow {
constructor() {
this.listeners = {};
this.location = { href: "" };
}
addEventListener(event, callback) {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(callback);
}
removeEventListener(event, callback) {
if (!this.listeners[event]) return;
this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
}
trigger(event) {
if (this.listeners[event]) {
this.listeners[event].forEach(cb => cb());
}
}
}
// ─── Test Inactivity Logic Class ──────────────────────────────────────────────
class InactivityTimeoutTester {
constructor(options = {}) {
this.timeoutSeconds = options.timeoutSeconds || 3600; // 1 hour
this.warningSeconds = options.warningSeconds || 120; // 2 minutes
this.showWarning = false;
this.timeLeft = this.warningSeconds;
this.isLoggedOut = false;
this.lastActivity = Date.now();
this.visibilityState = "visible";
}
// Simulate user activity event
onUserActivity(currentTime) {
if (this.visibilityState === "visible") {
this.lastActivity = currentTime || Date.now();
this.showWarning = false;
}
}
// Simulate tick (every second or arbitrary delay)
tick(currentTime) {
const elapsed = Math.floor((currentTime - this.lastActivity) / 1000);
const remaining = this.timeoutSeconds - elapsed;
if (remaining <= 0) {
this.isLoggedOut = true;
this.showWarning = false;
} else if (remaining <= this.warningSeconds) {
this.timeLeft = remaining;
this.showWarning = true;
} else {
this.showWarning = false;
}
}
// Simulate returning to the tab
onVisibilityChange(newVisibilityState, currentTime) {
this.visibilityState = newVisibilityState;
if (newVisibilityState === "visible") {
const elapsed = Math.floor((currentTime - this.lastActivity) / 1000);
const remaining = this.timeoutSeconds - elapsed;
if (remaining <= 0) {
this.isLoggedOut = true;
this.showWarning = false;
} else if (remaining <= this.warningSeconds) {
this.timeLeft = remaining;
this.showWarning = true;
}
}
}
}
// ─── TEST CASES ───────────────────────────────────────────────────────────────
function testResetActivityWhenVisible() {
console.log("- Test: Reset activity timer when tab is visible");
const tester = new InactivityTimeoutTester();
const initialActivity = tester.lastActivity;
// Wait 10 seconds
const timeAfter10s = initialActivity + 10000;
tester.onUserActivity(timeAfter10s);
// Last activity should be updated
assert.ok(tester.lastActivity >= initialActivity);
}
function testNoResetActivityWhenHidden() {
console.log("- Test: Do NOT reset activity timer when tab is hidden");
const tester = new InactivityTimeoutTester();
const initialActivity = tester.lastActivity;
// Change tab status to hidden
tester.visibilityState = "hidden";
// User activity should be ignored for reset
tester.onUserActivity(initialActivity + 10000);
assert.strictEqual(tester.lastActivity, initialActivity);
}
function testWarningThreshold() {
console.log("- Test: Trigger warning at 2 minutes remaining");
const tester = new InactivityTimeoutTester({ timeoutSeconds: 3600, warningSeconds: 120 });
const start = Date.now();
// Tick at 59 minutes (3540 seconds elapsed, 60 seconds remaining)
const warnTime = start + (3540 * 1000);
tester.tick(warnTime);
assert.strictEqual(tester.showWarning, true);
assert.strictEqual(tester.timeLeft, 60);
}
function testSafeZoneAfterActivity() {
console.log("- Test: Warning goes away when user becomes active");
const tester = new InactivityTimeoutTester({ timeoutSeconds: 3600, warningSeconds: 120 });
const start = Date.now();
// Tick at 3540 seconds (warning is shown)
const warnTime = start + (3540 * 1000);
tester.tick(warnTime);
assert.strictEqual(tester.showWarning, true);
// User performs activity at warnTime
tester.onUserActivity(warnTime);
// Tick immediately after activity (should be in safe zone)
tester.tick(warnTime);
assert.strictEqual(tester.showWarning, false);
}
function testAutoLogout() {
console.log("- Test: Auto-logout after 1 hour of total inactivity");
const tester = new InactivityTimeoutTester({ timeoutSeconds: 3600, warningSeconds: 120 });
const start = Date.now();
// Tick after 3601 seconds
const expireTime = start + (3601 * 1000);
tester.tick(expireTime);
assert.strictEqual(tester.isLoggedOut, true);
assert.strictEqual(tester.showWarning, false);
}
function testTabSwitchSilentlyTicks() {
console.log("- Test: Switching tabs continues counting down silently");
const tester = new InactivityTimeoutTester({ timeoutSeconds: 3600, warningSeconds: 120 });
const start = Date.now();
// Switch tab away to hidden
tester.onVisibilityChange("hidden", start);
// Tick 10 minutes (600s) later while hidden
const tenMinsLater = start + (600 * 1000);
tester.tick(tenMinsLater);
// Should still be in safe zone (no warning yet, no logout)
assert.strictEqual(tester.showWarning, false);
assert.strictEqual(tester.isLoggedOut, false);
}
function testTabReturnImmediateCheck() {
console.log("- Test: Tab return triggers immediate state check");
const tester = new InactivityTimeoutTester({ timeoutSeconds: 3600, warningSeconds: 120 });
const start = Date.now();
// User switches tab away
tester.onVisibilityChange("hidden", start);
// User is away for 59 minutes (3540s), then returns
const returnTime = start + (3540 * 1000);
tester.onVisibilityChange("visible", returnTime);
// Should immediately show warning with remaining time of 60 seconds
assert.strictEqual(tester.showWarning, true);
assert.strictEqual(tester.timeLeft, 60);
}
function testTabReturnExpiredLogout() {
console.log("- Test: Tab return logs out immediately if expired while away");
const tester = new InactivityTimeoutTester({ timeoutSeconds: 3600, warningSeconds: 120 });
const start = Date.now();
// User switches tab away
tester.onVisibilityChange("hidden", start);
// User is away for 61 minutes (3660s), then returns
const returnTime = start + (3660 * 1000);
tester.onVisibilityChange("visible", returnTime);
// Should immediately trigger logout
assert.strictEqual(tester.isLoggedOut, true);
}
// Execute tests
try {
testResetActivityWhenVisible();
testNoResetActivityWhenHidden();
testWarningThreshold();
testSafeZoneAfterActivity();
testAutoLogout();
testTabSwitchSilentlyTicks();
testTabReturnImmediateCheck();
testTabReturnExpiredLogout();
console.log("✓ ALL TESTS PASSED SUCCESSFULLY!");
} catch (error) {
console.error("❌ TEST FAILURE:", error);
process.exit(1);
}
+16
View File
@@ -0,0 +1,16 @@
const { netifyFetch } = require('../proxy/netifyClientCore');
require('dotenv').config({ path: './.env.local' });
async function main() {
console.log('Fetching with limit 5000...');
const start = Date.now();
const data = await netifyFetch('/lookup/applications', { settings_limit: 5000 });
console.log('Done in:', Date.now() - start, 'ms');
console.log('Returned items count:', data?.length);
if (data && data.length > 0) {
console.log('First item:', data[0].id, data[0].name);
console.log('Last item:', data[data.length - 1].id, data[data.length - 1].name);
}
}
main().catch(console.error);
+30
View File
@@ -0,0 +1,30 @@
const axios = require('axios');
async function main() {
console.log('Logging in to localhost...');
const loginRes = await axios.post('http://localhost:3001/api/auth/login', {
username: 'admin',
password: 'admin'
});
const cookie = loginRes.headers['set-cookie'];
console.log('Login successful. Cookies:', cookie);
console.log('Fetching /api/auth/me...');
const meRes = await axios.get('http://localhost:3001/api/auth/me', {
headers: {
Cookie: cookie ? cookie.join('; ') : ''
}
});
console.log('/api/auth/me response:', meRes.data);
console.log('Fetching /api/auth/admin/users...');
const usersRes = await axios.get('http://localhost:3001/api/auth/admin/users', {
headers: {
Cookie: cookie ? cookie.join('; ') : ''
}
});
console.log('/api/auth/admin/users response:', usersRes.data);
}
main().catch(console.error);
+24
View File
@@ -0,0 +1,24 @@
const axios = require('axios');
async function main() {
console.log('Logging in to localhost Next.js server on port 3000...');
const loginRes = await axios.post('http://localhost:3000/api/auth/login', {
username: 'admin',
password: 'admin'
});
const cookie = loginRes.headers['set-cookie'];
const headers = {
Cookie: cookie ? cookie.join('; ') : ''
};
console.log('Fetching localhost /api/auth/admin/users...');
const res = await axios.get('http://localhost:3000/api/auth/admin/users', { headers });
console.log('Total users returned:', res.data.data.length);
console.log('Users list:');
res.data.data.forEach(u => {
console.log(`- Username: ${u.username}, Role: ${u.role}, Site: ${u.site_uuid}`);
});
}
main().catch(console.error);
+6
View File
@@ -0,0 +1,6 @@
const rootMongoose = require('mongoose');
const proxyMongoose = require('../proxy/node_modules/mongoose');
console.log('Root Mongoose === Proxy Mongoose:', rootMongoose === proxyMongoose);
console.log('Root Mongoose version:', rootMongoose.version);
console.log('Proxy Mongoose version:', proxyMongoose.version);
+12
View File
@@ -0,0 +1,12 @@
const { netifyFetch } = require('../proxy/netifyClientCore');
require('dotenv').config({ path: './.env.local' });
async function main() {
const p1 = await netifyFetch('/lookup/applications', { settings_limit: 5, settings_page: 1 });
const p2 = await netifyFetch('/lookup/applications', { settings_limit: 5, settings_page: 2 });
console.log('Page 1 items:', p1.map(x => ({ id: x.id, name: x.name })));
console.log('Page 2 items:', p2.map(x => ({ id: x.id, name: x.name })));
}
main().catch(console.error);
+18
View File
@@ -0,0 +1,18 @@
const { netifyFetch } = require('../proxy/netifyClientCore');
require('dotenv').config({ path: './.env.local' });
async function main() {
const p1 = await netifyFetch('/lookup/applications', { settings_limit: 5, settings_page: 1 });
const p2 = await netifyFetch('/lookup/applications', { settings_limit: 5, settings_page: 2 });
console.log('Page 1 length:', p1?.length);
console.log('Page 2 length:', p2?.length);
if (p1 && p1.length > 0) {
console.log('Page 1 first item:', p1[0].id, p1[0].name);
}
if (p2 && p2.length > 0) {
console.log('Page 2 first item:', p2[0].id, p2[0].name);
}
}
main().catch(console.error);
+16
View File
@@ -0,0 +1,16 @@
const mongoose = require('mongoose');
async function main() {
const uri = 'mongodb://127.0.0.1:27017/backone_dpi';
await mongoose.connect(uri);
const count = await mongoose.connection.db.collection('lookupapps').countDocuments({});
console.log('Count inside reader:', count);
const doc = await mongoose.connection.db.collection('lookupapps').findOne({ id: 99999 });
console.log('Found document:', doc);
await mongoose.disconnect();
}
main().catch(console.error);
+38
View File
@@ -0,0 +1,38 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const remoteJs = `
const net = require('net');
const s = net.createConnection(27017, 'mongodb.prod.proit.id', () => {
console.log('SUCCESS: Connected to mongodb.prod.proit.id from remote server!');
s.destroy();
}).on('error', e => {
console.error('FAILED: ' + e.message);
});
`;
const conn = new Client();
conn.on('ready', () => {
const b64 = Buffer.from(remoteJs).toString('base64');
conn.exec(`echo "${b64}" | base64 -d | node`, (err, stream) => {
if (err) {
console.error(err);
conn.end();
return;
}
let out = '';
stream.on('data', d => out += d);
stream.on('close', () => {
console.log('Result from remote:');
console.log(out.trim());
conn.end();
});
});
}).on('error', console.error).connect(SSH);
+61
View File
@@ -0,0 +1,61 @@
const { Client } = require('ssh2');
const net = require('net');
const { MongoClient } = require('mongodb');
const sshConfig = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const LOCAL_PORT = 27019;
const REMOTE_MONGO_HOST = 'mongodb.prod.proit.id';
const REMOTE_MONGO_PORT = 27017;
const conn = new Client();
const server = net.createServer((sock) => {
conn.forwardOut(
'127.0.0.1',
sock.remotePort,
REMOTE_MONGO_HOST,
REMOTE_MONGO_PORT,
(err, stream) => {
if (err) {
sock.destroy();
return;
}
sock.pipe(stream);
stream.pipe(sock);
}
);
});
conn.on('ready', () => {
server.listen(LOCAL_PORT, '127.0.0.1', async () => {
console.log(`SSH Tunnel established on port ${LOCAL_PORT}`);
try {
const REMOTE_URI = `mongodb://backone_user:SusuKudaLiar@127.0.0.1:${LOCAL_PORT}/backone_dpi?authSource=backone_dpi&directConnection=true`;
const client = new MongoClient(REMOTE_URI, { serverSelectionTimeoutMS: 5000 });
await client.connect();
const db = client.db('backone_dpi');
console.log('Connected to remote database.');
const collections = await db.listCollections().toArray();
console.log('\nCollections and document counts:');
for (const col of collections) {
const count = await db.collection(col.name).countDocuments({});
console.log(`- ${col.name}: ${count} documents`);
}
await client.close();
} catch (e) {
console.error('Error:', e.message);
} finally {
server.close();
conn.end();
console.log('Tunnel closed.');
}
});
}).on('error', (err) => {
console.error('SSH Error:', err.message);
}).connect(sshConfig);
+61
View File
@@ -0,0 +1,61 @@
const { Client } = require('ssh2');
const net = require('net');
const { MongoClient } = require('mongodb');
const sshConfig = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const LOCAL_PORT = 27019; // use 27019 to avoid conflicts
const REMOTE_MONGO_HOST = 'mongodb.prod.proit.id';
const REMOTE_MONGO_PORT = 27017;
const conn = new Client();
const server = net.createServer((sock) => {
conn.forwardOut(
'127.0.0.1',
sock.remotePort,
REMOTE_MONGO_HOST,
REMOTE_MONGO_PORT,
(err, stream) => {
if (err) {
sock.destroy();
return;
}
sock.pipe(stream);
stream.pipe(sock);
}
);
});
conn.on('ready', () => {
server.listen(LOCAL_PORT, '127.0.0.1', async () => {
console.log(`SSH Tunnel established on port ${LOCAL_PORT}`);
try {
const REMOTE_URI = `mongodb://backone_user:SusuKudaLiar@127.0.0.1:${LOCAL_PORT}/backone_dpi?authSource=backone_dpi`;
const client = new MongoClient(REMOTE_URI, { serverSelectionTimeoutMS: 5000 });
await client.connect();
const db = client.db('backone_dpi');
console.log('Connected to remote database.');
const collections = await db.listCollections().toArray();
console.log('\nCollections and document counts:');
for (const col of collections) {
const count = await db.collection(col.name).countDocuments({});
console.log(`- ${col.name}: ${count} documents`);
}
await client.close();
} catch (e) {
console.error('Error:', e.message);
} finally {
server.close();
conn.end();
console.log('Tunnel closed.');
}
});
}).on('error', (err) => {
console.error('SSH Error:', err.message);
}).connect(sshConfig);
+31
View File
@@ -0,0 +1,31 @@
const axios = require('axios');
async function main() {
console.log('Logging in to remote server...');
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'admin',
password: 'admin'
});
const cookie = loginRes.headers['set-cookie'];
console.log('Login successful. Cookies:', cookie);
console.log('Fetching /api/auth/me ...');
try {
const meRes = await axios.get('https://demoplace.my.id/api/auth/me', {
headers: {
Cookie: cookie ? cookie.join('; ') : ''
}
});
console.log('Me status:', meRes.status);
console.log('Me response:', meRes.data);
} catch (err) {
if (err.response) {
console.error('Me failed. Status:', err.response.status, 'Response:', err.response.data);
} else {
console.error('Me failed. Error:', err.message);
}
}
}
main().catch(console.error);
+32
View File
@@ -0,0 +1,32 @@
const axios = require('axios');
async function main() {
console.log('Logging in to remote server...');
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'admin',
password: 'admin'
});
const cookie = loginRes.headers['set-cookie'];
const headers = {
Cookie: cookie ? cookie.join('; ') : ''
};
console.log('\n--- API: /api/dashboard/summary ---');
try {
const res = await axios.get('https://demoplace.my.id/api/dashboard/summary', { headers });
console.log(JSON.stringify(res.data, null, 2));
} catch (err) {
console.error(err.message);
}
console.log('\n--- API: /api/dashboard/timeline ---');
try {
const res = await axios.get('https://demoplace.my.id/api/dashboard/timeline?points=5', { headers });
console.log(JSON.stringify(res.data, null, 2));
} catch (err) {
console.error(err.message);
}
}
main().catch(console.error);
+32
View File
@@ -0,0 +1,32 @@
const axios = require('axios');
async function main() {
console.log('Logging in to remote server...');
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'admin',
password: 'admin'
});
const cookie = loginRes.headers['set-cookie'];
const headers = {
Cookie: cookie ? cookie.join('; ') : ''
};
console.log('\n--- API: /api/dashboard/threats?timeRange=1d ---');
try {
const res = await axios.get('https://demoplace.my.id/api/dashboard/threats?timeRange=1d', { headers });
console.log(JSON.stringify(res.data, null, 2));
} catch (err) {
console.error(err.message);
}
console.log('\n--- API: /api/dashboard/threats?timeRange=all ---');
try {
const res = await axios.get('https://demoplace.my.id/api/dashboard/threats?timeRange=all', { headers });
console.log(JSON.stringify(res.data, null, 2));
} catch (err) {
console.error(err.message);
}
}
main().catch(console.error);
+19
View File
@@ -0,0 +1,19 @@
const proxyMongoose = require('../proxy/node_modules/mongoose');
require('dotenv').config({ path: './.env.local' });
const { LookupApp } = require('../proxy/models/Schemas');
async function main() {
const uri = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
await proxyMongoose.connect(uri);
console.log('Count at start:', await LookupApp.countDocuments({}));
console.log('Sleeping for 10 seconds...');
await new Promise(resolve => setTimeout(resolve, 10000));
console.log('Count after 10 seconds:', await LookupApp.countDocuments({}));
await proxyMongoose.disconnect();
}
main().catch(console.error);
+53
View File
@@ -0,0 +1,53 @@
// test/test-site-isolation.js
const axios = require('axios');
const assert = require('assert');
async function main() {
console.log('=== Running Site Isolation Integration Test ===');
console.log('1. Logging in as Nexus Tenant Admin...');
const loginRes = await axios.post('https://demoplace.my.id/api/auth/login', {
username: 'nexus',
password: 'nexus'
});
const cookie = loginRes.headers['set-cookie'];
const headers = { Cookie: cookie ? cookie.join('; ') : '' };
console.log('2. Fetching /api/dashboard/agents/uptime...');
const uptimeRes = await axios.get('https://demoplace.my.id/api/dashboard/agents/uptime?timeRange=1d', { headers });
assert.ok(uptimeRes.data.ok, 'Uptime response must be ok');
const uptimeKeys = Object.keys(uptimeRes.data.uptime);
console.log('Uptime keys returned:', uptimeKeys);
const siabAgentUuids = ['F6-2V-DT-8A', '2F-TF-1D-GK', 'YW-6I-61-LL', '8A-V3-PB-85', '1R-79-J9-YE'];
const nexusAgentUuids = ['1T-5Q-RC-AS', '2N-ID-VQ-AL'];
for (const uuid of uptimeKeys) {
assert.ok(!siabAgentUuids.includes(uuid), `Security violation: SIAB agent ${uuid} leaked to Nexus admin!`);
}
console.log('✓ No SIAB agent uptimes leaked to Nexus.');
console.log('3. Fetching /api/dashboard/agents/storage...');
const storageRes = await axios.get('https://demoplace.my.id/api/dashboard/agents/storage', { headers });
assert.ok(storageRes.data.ok, 'Storage response must be ok');
const storageKeys = Object.keys(storageRes.data.storage);
console.log('Storage keys returned:', storageKeys);
for (const uuid of storageKeys) {
assert.ok(!siabAgentUuids.includes(uuid), `Security violation: SIAB agent storage ${uuid} leaked to Nexus admin!`);
}
console.log('✓ No SIAB agent storage sizes leaked to Nexus.');
console.log('=== SITE ISOLATION TEST PASSED SUCCESSFULY ===');
}
main().catch(err => {
console.error('✗ TEST FAILED:', err.message);
if (err.response) {
console.error('Response data:', err.response.data);
}
process.exit(1);
});
+32
View File
@@ -0,0 +1,32 @@
const { Client } = require('ssh2');
const SSH = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const conn = new Client();
conn.on('ready', () => {
console.log('SSH Connection ready.');
conn.exec('node -v && which node && pwd', (err, stream) => {
if (err) {
console.error('Exec error:', err.message);
conn.end();
return;
}
let out = '';
let errOut = '';
stream.on('data', d => out += d);
stream.stderr.on('data', d => errOut += d);
stream.on('close', () => {
console.log('Stdout:', out);
console.log('Stderr:', errOut);
conn.end();
});
});
}).on('error', (err) => {
console.error('SSH Error:', err.message);
}).connect(SSH);
+22
View File
@@ -0,0 +1,22 @@
const proxyMongoose = require('../proxy/node_modules/mongoose');
require('dotenv').config({ path: './.env.local' });
const { syncApplicationDictionary } = require('../proxy/netifyClient');
const { LookupApp } = require('../proxy/models/Schemas');
async function test() {
const uri = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
console.log('Connecting Proxy Mongoose to:', uri);
await proxyMongoose.connect(uri);
console.log('Connected to DB:', proxyMongoose.connection.name);
await syncApplicationDictionary();
const count = await LookupApp.countDocuments();
console.log('Total LookupApps in DB inside test:', count);
const sample = await LookupApp.findOne({}).lean();
console.log('Sample LookupApp document:', sample);
await proxyMongoose.disconnect();
}
test().catch(console.error);
+71
View File
@@ -0,0 +1,71 @@
const { Client } = require('ssh2');
const net = require('net');
const sshConfig = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const LOCAL_PORT = 27020;
const REMOTE_MONGO_HOST = 'mongodb.prod.proit.id';
const REMOTE_MONGO_PORT = 27017;
const conn = new Client();
const server = net.createServer((sock) => {
console.log('Local client connected to tunnel.');
conn.forwardOut(
'127.0.0.1',
sock.remotePort,
REMOTE_MONGO_HOST,
REMOTE_MONGO_PORT,
(err, stream) => {
if (err) {
console.error('forwardOut error:', err.message);
sock.destroy();
return;
}
console.log('forwardOut stream opened successfully.');
sock.pipe(stream);
stream.pipe(sock);
}
);
});
conn.on('ready', () => {
server.listen(LOCAL_PORT, '127.0.0.1', () => {
console.log(`Tunnel listening on port ${LOCAL_PORT}`);
// Connect a raw net socket to test it
console.log('Connecting test client to local port...');
const client = net.createConnection(LOCAL_PORT, '127.0.0.1', () => {
console.log('Test client connected locally.');
// Send a dummy byte to trigger forwarding
client.write('hello');
});
client.on('data', (d) => {
console.log('Received data from tunnel:', d.toString());
client.destroy();
server.close();
conn.end();
});
client.on('error', (e) => {
console.error('Test client error:', e.message);
server.close();
conn.end();
});
setTimeout(() => {
console.log('Timeout reached, closing.');
client.destroy();
server.close();
conn.end();
}, 10000);
});
}).on('error', (err) => {
console.error('SSH Error:', err.message);
}).connect(sshConfig);
+26
View File
@@ -0,0 +1,26 @@
const proxyMongoose = require('../proxy/node_modules/mongoose');
const { LookupApp } = require('../proxy/models/Schemas');
async function main() {
const uri = 'mongodb://127.0.0.1:27017/backone_dpi';
await proxyMongoose.connect(uri);
console.log('Inserting dummy LookupApp...');
await LookupApp.deleteMany({});
const doc = await LookupApp.create({
id: 99999,
tag: 'netify.dummytest',
label: 'Dummy Test App',
name: 'Dummy Test App',
description: 'A test document to verify write persistence',
application_category: { id: 1, name: 'test', label: 'Test', tag: 'test' }
});
console.log('Created document id:', doc._id);
const count = await LookupApp.countDocuments({});
console.log('Count inside writer:', count);
await proxyMongoose.disconnect();
}
main().catch(console.error);
+153
View File
@@ -0,0 +1,153 @@
// test/tunnel_migrate.js
const { Client } = require('ssh2');
const net = require('net');
const { MongoClient } = require('mongodb');
const sshConfig = {
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH',
readyTimeout: 60000
};
const LOCAL_PORT = 27018;
const REMOTE_MONGO_HOST = 'mongodb.prod.proit.id';
const REMOTE_MONGO_PORT = 27017;
const conn = new Client();
const server = net.createServer((sock) => {
conn.forwardOut(
'127.0.0.1',
sock.remotePort,
REMOTE_MONGO_HOST,
REMOTE_MONGO_PORT,
(err, stream) => {
if (err) {
sock.destroy();
return;
}
sock.pipe(stream);
stream.pipe(sock);
}
);
});
conn.on('ready', () => {
server.listen(LOCAL_PORT, '127.0.0.1', async () => {
console.log(`✓ SSH Tunnel established: 127.0.0.1:${LOCAL_PORT} -> ${REMOTE_MONGO_HOST}:${REMOTE_MONGO_PORT}`);
try {
await runMigration();
} catch (e) {
console.error("✗ Migration failed:", e);
} finally {
server.close();
conn.end();
console.log("Tunnel closed.");
}
});
}).on('error', (err) => {
console.error("SSH Connection error:", err.message);
}).connect(sshConfig);
async function runMigration() {
const LOCAL_URI = 'mongodb://127.0.0.1:27017';
const REMOTE_URI = `mongodb://backone_user:SusuKudaLiar@127.0.0.1:${LOCAL_PORT}/backone_dpi?authSource=backone_dpi`;
const DB_NAME = 'backone_dpi';
console.log("Connecting to local MongoDB...");
const localClient = new MongoClient(LOCAL_URI);
await localClient.connect();
const localDb = localClient.db(DB_NAME);
console.log("✓ Connected to local MongoDB.");
console.log("Connecting to production MongoDB via tunnel...");
const remoteClient = new MongoClient(REMOTE_URI, { serverSelectionTimeoutMS: 5000 });
await remoteClient.connect();
const remoteDb = remoteClient.db(DB_NAME);
console.log("✓ Connected to production MongoDB.\n");
// 1. Sync users
console.log("--- Syncing 'users' collection ---");
const localUsersColl = localDb.collection('users');
const remoteUsersColl = remoteDb.collection('users');
const localUsers = await localUsersColl.find({}).toArray();
console.log(`Found ${localUsers.length} users in local database.`);
let userUpsertCount = 0;
for (const user of localUsers) {
const { _id, ...userData } = user;
const res = await remoteUsersColl.updateOne(
{ username: user.username },
{ $set: userData },
{ upsert: true }
);
if (res.upsertedCount > 0 || res.modifiedCount > 0) {
userUpsertCount++;
}
}
console.log(`✓ Synchronized ${userUpsertCount} users to production MongoDB.`);
// 2. Sync tenantconfigs
console.log("\n--- Syncing 'tenantconfigs' collection ---");
const localConfigColl = localDb.collection('tenantconfigs');
const remoteConfigColl = remoteDb.collection('tenantconfigs');
const localConfigs = await localConfigColl.find({}).toArray();
console.log(`Found ${localConfigs.length} tenant configurations locally.`);
if (localConfigs.length > 0) {
await remoteConfigColl.deleteMany({});
const cleanedConfigs = localConfigs.map(c => {
const { _id, ...rest } = c;
return rest;
});
await remoteConfigColl.insertMany(cleanedConfigs);
console.log(`✓ Synchronized ${localConfigs.length} configurations to production.`);
}
// 3. Sync customagentlocations
console.log("\n--- Syncing 'customagentlocations' collection ---");
const localLocColl = localDb.collection('customagentlocations');
const remoteLocColl = remoteDb.collection('customagentlocations');
const localLocs = await localLocColl.find({}).toArray();
console.log(`Found ${localLocs.length} agent locations locally.`);
if (localLocs.length > 0) {
await remoteLocColl.deleteMany({});
const cleanedLocs = localLocs.map(l => {
const { _id, ...rest } = l;
return rest;
});
await remoteLocColl.insertMany(cleanedLocs);
console.log(`✓ Synchronized ${localLocs.length} agent locations to production.`);
}
// 4. Sync blacklistrules
console.log("\n--- Syncing 'blacklistrules' collection ---");
const localRulesColl = localDb.collection('blacklistrules');
const remoteRulesColl = remoteDb.collection('blacklistrules');
const localColls = await localDb.listCollections({ name: 'blacklistrules' }).toArray();
if (localColls.length > 0) {
const localRules = await localRulesColl.find({}).toArray();
console.log(`Found ${localRules.length} blacklist rules locally.`);
if (localRules.length > 0) {
await remoteRulesColl.deleteMany({});
const cleanedRules = localRules.map(r => {
const { _id, ...rest } = r;
return rest;
});
await remoteRulesColl.insertMany(cleanedRules);
console.log(`✓ Synchronized ${localRules.length} blacklist rules to production.`);
}
} else {
console.log("No blacklist rules found locally.");
}
await localClient.close();
await remoteClient.close();
console.log("\n✓ Database configuration migration completed successfully!");
}