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:
1 parent
a403f752f3
commit
dd4c8f6876
385 files changed
+31016
-8268
No files matched your search
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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));
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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
@@ -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); });
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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
@@ -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 ───────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -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`);
|
||||
});
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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!");
|
||||
}
|
||||
Reference in new issue
Block a user