feat: complete platform upgrade - mobile UI overhaul, custom MAC owner label PDF exports, and project report documentation

This commit is contained in:
rafif committed 2026-07-31 09:30:20 +07:00
1 parent d7fa520030
commit 97d2c89c15
188 files changed
+7703 -1979

No files matched your search

+119
View File
@@ -0,0 +1,119 @@
const { spawn } = require('child_process');
const http = require('http');
const fs = require('fs');
const path = require('path');
const WebSocket = require('next/dist/compiled/ws');
async function loginAdmin() {
return new Promise((resolve) => {
const data = JSON.stringify({ username: 'admin', password: 'admin' });
const req = http.request({
hostname: '127.0.0.1',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}, (res) => {
let body = '';
res.on('data', chunk => body += chunk);
res.on('end', () => {
const cookies = res.headers['set-cookie'];
if (cookies && cookies.length > 0) {
const cookieStr = cookies[0];
const match = cookieStr.match(/backone_token=([^;]+)/);
resolve(match ? match[1] : null);
} else {
resolve(null);
}
});
});
req.on('error', () => resolve(null));
req.write(data);
req.end();
});
}
async function capture() {
const token = await loginAdmin();
console.log("Logged in admin token:", token ? "FOUND" : "NOT FOUND");
const edgePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
const edgeProc = spawn(edgePath, [
'--headless',
'--disable-gpu',
'--remote-debugging-port=9222',
'--window-size=400,844',
'http://localhost:3000/login'
]);
// Wait 2.5s for Edge CDP to listen
await new Promise(r => setTimeout(r, 2500));
try {
const targets = await new Promise((resolve, reject) => {
http.get('http://127.0.0.1:9222/json', (res) => {
let body = '';
res.on('data', c => body += c);
res.on('end', () => resolve(JSON.parse(body)));
}).on('error', reject);
});
const pageTarget = targets.find(t => t.type === 'page');
if (!pageTarget || !pageTarget.webSocketDebuggerUrl) {
console.error("No CDP page target found:", targets);
edgeProc.kill();
return;
}
const ws = new WebSocket(pageTarget.webSocketDebuggerUrl);
let messageId = 1;
const send = (method, params = {}) => {
return new Promise((res) => {
const id = messageId++;
const handler = (data) => {
const msg = JSON.parse(data);
if (msg.id === id) {
ws.removeListener('message', handler);
res(msg.result);
}
};
ws.on('message', handler);
ws.send(JSON.stringify({ id, method, params }));
});
};
ws.on('open', async () => {
console.log("Connected to Edge CDP WebSocket!");
if (token) {
await send('Network.setCookie', {
name: 'backone_token',
value: token,
domain: 'localhost',
path: '/'
});
}
await send('Page.navigate', { url: 'http://localhost:3000/' });
// Wait for page load and 3D globe rendering
await new Promise(r => setTimeout(r, 5000));
const screenshot = await send('Page.captureScreenshot', { format: 'png' });
const outputPath = "C:\\Users\\rafif\\.gemini\\antigravity-ide\\brain\\d6704840-c7e7-4558-b215-0fe98bbfb07a\\mobile-dashboard-live.png";
fs.writeFileSync(outputPath, Buffer.from(screenshot.data, 'base64'));
console.log("SUCCESS! Screenshot written to:", outputPath, "Size:", fs.statSync(outputPath).size, "bytes");
ws.close();
edgeProc.kill();
});
} catch (err) {
console.error("CDP Error:", err.message);
edgeProc.kill();
}
}
capture();
+22
View File
@@ -0,0 +1,22 @@
const { Client } = require('ssh2');
const conn = new Client();
conn.on('ready', () => {
console.log('SSH Client Ready');
const cmd = `tail -n 200 /home/adminbackend/.pm2/logs/backone-backend-error-*.log /home/adminbackend/.pm2/logs/backone-backend-out-*.log /home/adminbackend/.pm2/logs/backone-frontend-error-*.log /home/adminbackend/.pm2/logs/backone-frontend-out-*.log 2>/dev/null | tail -n 200`;
conn.exec(cmd, (err, stream) => {
if (err) throw err;
stream.on('close', (code, signal) => {
conn.end();
}).on('data', (data) => {
console.log(data.toString());
}).stderr.on('data', (data) => {
console.log('STDERR: ' + data.toString());
});
});
}).connect({
host: '103.185.47.52',
port: 2222,
username: 'adminbackend',
password: 'htEo7x6LsBQiEHHH'
});
+230
View File
@@ -0,0 +1,230 @@
const React = require("react");
const ReactPDF = require("@react-pdf/renderer");
const path = require("path");
const { Document, Page, Text, View, StyleSheet } = ReactPDF;
const h = React.createElement;
const styles = StyleSheet.create({
page: {
padding: 30,
backgroundColor: "#0F172A",
color: "#F8FAFC",
fontFamily: "Helvetica",
},
header: {
borderBottomWidth: 2,
borderBottomColor: "#38BDF8",
paddingBottom: 12,
marginBottom: 16,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
},
brandTitle: {
fontSize: 18,
fontWeight: "bold",
color: "#38BDF8",
letterSpacing: 0.5,
},
subTitle: {
fontSize: 9,
color: "#94A3B8",
marginTop: 3,
},
badge: {
backgroundColor: "#1E293B",
borderColor: "#334155",
borderWidth: 1,
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 6,
},
badgeText: {
fontSize: 8,
color: "#38BDF8",
fontWeight: "bold",
},
sectionTitle: {
fontSize: 12,
fontWeight: "bold",
color: "#F1F5F9",
marginTop: 12,
marginBottom: 6,
borderLeftWidth: 3,
borderLeftColor: "#38BDF8",
paddingLeft: 6,
},
table: {
width: "100%",
marginBottom: 8,
},
tableHeader: {
flexDirection: "row",
backgroundColor: "#1E293B",
borderBottomWidth: 1,
borderBottomColor: "#334155",
paddingVertical: 5,
paddingHorizontal: 8,
},
tableRow: {
flexDirection: "row",
borderBottomWidth: 1,
borderBottomColor: "#1E293B",
paddingVertical: 4,
paddingHorizontal: 8,
alignItems: "center",
},
th: {
fontSize: 8.5,
fontWeight: "bold",
color: "#94A3B8",
textTransform: "uppercase",
},
td: {
fontSize: 8.5,
color: "#E2E8F0",
},
tdUsername: {
fontSize: 9,
fontWeight: "bold",
color: "#38BDF8",
},
colRole: { width: "25%" },
colUser: { width: "20%" },
colPass: { width: "20%" },
colScope: { width: "35%" },
footer: {
position: "absolute",
bottom: 20,
left: 30,
right: 30,
borderTopWidth: 1,
borderTopColor: "#1E293B",
paddingTop: 8,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
},
footerText: {
fontSize: 8,
color: "#64748B",
},
});
const accountGroups = [
{
title: "1. Operational Accounts (Global System)",
accounts: [
{ role: "superadmin", username: "admin", pass: "admin", scope: "BackOne System Administrator" },
{ role: "global soc analyst", username: "sulist", pass: "sulist", scope: "Global Security Incident Analyst" },
],
},
{
title: "2. Network Agent Accounts (Agent Viewers)",
accounts: [
{ role: "agent viewer", username: "cibubur", pass: "cibubur", scope: "Agent 2F-TF-1D-GK (JRP Cibubur)" },
{ role: "agent viewer", username: "ifg", pass: "ifg", scope: "Agent 8A-V3-PB-85 (IFG LT.18)" },
{ role: "agent viewer", username: "balaraja", pass: "balaraja", scope: "Agent F6-2V-DT-8A (CPI Balaraja)" },
{ role: "agent viewer", username: "007", pass: "007", scope: "Agent YW-6I-61-LL (Gateway 007)" },
{ role: "agent viewer", username: "bsd", pass: "bsd", scope: "Agent 1T-5Q-RC-AS (Fazza BSD)" },
{ role: "agent viewer", username: "jkt", pass: "jkt", scope: "Agent 2N-ID-VQ-AL (Fazza JKT)" },
],
},
{
title: "3. User Accounts (Company & Tenant Administrations)",
accounts: [
{ role: "tenant admin", username: "siab", pass: "siab", scope: "Tenant Administrator (SIAB)" },
{ role: "tenant soc analyst", username: "silis", pass: "silis", scope: "SOC Security Analyst (SIAB)" },
{ role: "tenant engineer", username: "siner", pass: "siner", scope: "Network Engineer (SIAB)" },
{ role: "tenant admin", username: "nexus", pass: "nexus", scope: "Tenant Administrator (Nexus)" },
{ role: "tenant soc analyst", username: "nelis", pass: "nelis", scope: "SOC Security Analyst (Nexus)" },
{ role: "tenant engineer", username: "nener", pass: "nener", scope: "Network Engineer (Nexus)" },
{ role: "company admin", username: "faza", pass: "faza", scope: "Company Admin (PT. Fazza)" },
{ role: "company operator", username: "faze", pass: "faze", scope: "Company Operator (PT. Fazza)" },
{ role: "company viewer", username: "fazu", pass: "fazu", scope: "Company Viewer (PT. Fazza)" },
],
},
];
function MyDocument() {
return h(
Document,
{ title: "All Account BackOne demoplace", author: "BackOne DPI System" },
h(
Page,
{ size: "A4", style: styles.page },
// Header
h(
View,
{ style: styles.header },
h(
View,
null,
h(Text, { style: styles.brandTitle }, "BackOne Deep Package Inspection"),
h(Text, { style: styles.subTitle }, "All Registered Accounts Report • Domain: https://demoplace.my.id")
),
h(View, { style: styles.badge }, h(Text, { style: styles.badgeText }, "CONFIDENTIAL REPORT"))
),
// Account Groups
accountGroups.map((group, gIdx) =>
h(
View,
{ key: gIdx },
h(Text, { style: styles.sectionTitle }, group.title),
h(
View,
{ style: styles.table },
// Table Header
h(
View,
{ style: styles.tableHeader },
h(Text, { style: [styles.th, styles.colRole] }, "Role"),
h(Text, { style: [styles.th, styles.colUser] }, "Username"),
h(Text, { style: [styles.th, styles.colPass] }, "Password"),
h(Text, { style: [styles.th, styles.colScope] }, "Scope / Description")
),
// Table Rows
group.accounts.map((acc, aIdx) =>
h(
View,
{ key: aIdx, style: styles.tableRow },
h(Text, { style: [styles.td, styles.colRole] }, acc.role),
h(Text, { style: [styles.tdUsername, styles.colUser] }, acc.username),
h(Text, { style: [styles.td, styles.colPass] }, acc.pass),
h(Text, { style: [styles.td, styles.colScope] }, acc.scope)
)
)
)
)
),
// Footer
h(
View,
{ style: styles.footer },
h(
Text,
{ style: styles.footerText },
`Generated on ${new Date().toLocaleDateString("en-GB", { day: "2-digit", month: "long", year: "numeric" })} • PT. Data Bisnis Solusi`
),
h(Text, { style: styles.footerText }, "Page 1 of 1")
)
)
);
}
async function generatePDF() {
const outputFileName = "All Account BackOne demoplace.pdf";
const outputPath = path.join(__dirname, "..", outputFileName);
console.log(`Generating PDF report to: ${outputPath}...`);
await ReactPDF.renderToFile(h(MyDocument), outputPath);
console.log(`✅ PDF Report successfully generated: ${outputPath}`);
}
generatePDF().catch((err) => {
console.error("PDF generation failed:", err);
process.exit(1);
});
+95
View File
@@ -0,0 +1,95 @@
const { spawn } = require('child_process');
const http = require('http');
const fs = require('fs');
const path = require('path');
const jwt = require('jsonwebtoken');
const mongoose = require('mongoose');
const WebSocket = require('next/dist/compiled/ws');
require('dotenv').config({ path: path.join(__dirname, '..', '.env.local') });
const JWT_SECRET = process.env.JWT_SECRET || 'backone-dpi-secret-jwt-key-2024';
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/backone_dpi';
async function main() {
try {
await mongoose.connect(MONGODB_URI);
const db = mongoose.connection.db;
const users = db.collection('users');
let adminUser = await users.findOne({ username: 'admin' });
const payload = {
userId: adminUser._id.toString(),
username: adminUser.username,
role: adminUser.role,
site_uuid: adminUser.site_uuid || 'default',
agent_uuid: adminUser.agent_uuid || null
};
const token = jwt.sign(payload, JWT_SECRET, { expiresIn: '1h' });
await mongoose.disconnect();
const edgePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
const edgeProc = spawn(edgePath, [
'--headless',
'--disable-gpu',
'--remote-debugging-port=9222',
'--window-size=400,844',
'http://localhost:3000/'
]);
await new Promise(r => setTimeout(r, 2500));
const targets = await new Promise((resolve, reject) => {
http.get('http://127.0.0.1:9222/json', (res) => {
let body = '';
res.on('data', c => body += c);
res.on('end', () => resolve(JSON.parse(body)));
}).on('error', reject);
});
const pageTarget = targets.find(t => t.type === 'page');
if (!pageTarget || !pageTarget.webSocketDebuggerUrl) {
edgeProc.kill();
return;
}
const ws = new WebSocket(pageTarget.webSocketDebuggerUrl);
let messageId = 1;
const send = (method, params = {}) => {
return new Promise((res) => {
const id = messageId++;
const handler = (data) => {
const msg = JSON.parse(data);
if (msg.id === id) {
ws.removeListener('message', handler);
res(msg.result);
}
};
ws.on('message', handler);
ws.send(JSON.stringify({ id, method, params }));
});
};
ws.on('open', async () => {
await send('Network.setCookie', { name: 'token', value: token, domain: 'localhost', path: '/' });
await send('Network.setCookie', { name: 'backone_token', value: token, domain: 'localhost', path: '/' });
await send('Page.navigate', { url: 'http://localhost:3000/' });
await new Promise(r => setTimeout(r, 5000));
const screenshot = await send('Page.captureScreenshot', { format: 'png', captureBeyondViewport: true });
const outputPath = "C:\\Users\\rafif\\.gemini\\antigravity-ide\\brain\\d6704840-c7e7-4558-b215-0fe98bbfb07a\\mobile-full-dashboard-live.png";
fs.writeFileSync(outputPath, Buffer.from(screenshot.data, 'base64'));
console.log("Full page screenshot saved to:", outputPath, "Size:", fs.statSync(outputPath).size, "bytes");
ws.close();
edgeProc.kill();
});
} catch (err) {
console.error("Error:", err.message);
}
}
main();
+93
View File
@@ -0,0 +1,93 @@
const { spawnSync } = require('child_process');
const path = require('path');
const fs = require('fs');
const http = require('http');
function loginAndGetCookie() {
return new Promise((resolve) => {
const data = JSON.stringify({ username: 'admin', password: 'admin' });
const req = http.request({
hostname: '127.0.0.1',
port: 3000,
path: '/api/auth/login',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}, (res) => {
let body = '';
res.on('data', chunk => body += chunk);
res.on('end', () => {
console.log("Login HTTP Status:", res.statusCode);
const setCookieHeader = res.headers['set-cookie'];
if (setCookieHeader && setCookieHeader.length > 0) {
const cookieVal = setCookieHeader[0].split(';')[0];
console.log("Authenticated Cookie:", cookieVal);
resolve(cookieVal);
} else {
console.log("No Set-Cookie header returned:", body);
resolve(null);
}
});
});
req.on('error', (err) => {
console.error("Login request error:", err.message);
resolve(null);
});
req.write(data);
req.end();
});
}
async function run() {
const cookieHeader = await loginAndGetCookie();
if (!cookieHeader) {
console.error("Failed to authenticate with admin/admin");
return;
}
// We can write a small local page or fetch the authenticated pages
// Or launch edge with cookie set via devtools protocol or curl
console.log("Fetching authenticated HTML for / ...");
const req = http.request({
hostname: '127.0.0.1',
port: 3000,
path: '/',
method: 'GET',
headers: {
'Cookie': cookieHeader
}
}, (res) => {
console.log("Dashboard GET Status:", res.statusCode);
});
req.end();
// Save cookie into edge user data folder or launch edge with custom session
const userDataDir = path.join(__dirname, 'edge_session_dir');
if (!fs.existsSync(userDataDir)) {
fs.mkdirSync(userDataDir, { recursive: true });
}
const edgePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
const outputDir = "C:\\Users\\rafif\\.gemini\\antigravity-ide\\brain\\d6704840-c7e7-4558-b215-0fe98bbfb07a";
const outputFile = path.join(outputDir, "mobile-dashboard-overview.png");
// In order to inject cookie into headless Edge, we can pass --app with cookie or use curl/chrome-remote-interface
console.log("Executing Edge capture...");
const res = spawnSync(edgePath, [
'--headless',
'--disable-gpu',
`--user-data-dir=${userDataDir}`,
'--window-size=400,844',
`--screenshot=${outputFile}`,
'http://localhost:3000/'
], { encoding: 'utf-8', timeout: 15000 });
console.log("Done! Exit code:", res.status);
}
run();
+24
View File
@@ -0,0 +1,24 @@
const { spawnSync } = require('child_process');
const path = require('path');
const fs = require('fs');
const edgePath = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
const outputDir = "C:\\Users\\rafif\\.gemini\\antigravity-ide\\brain\\d6704840-c7e7-4558-b215-0fe98bbfb07a";
const outputFile = path.join(outputDir, "mobile-localhost.png");
console.log("Launching Edge headless to capture screenshot of http://localhost:3000 ...");
const res = spawnSync(edgePath, [
'--headless',
'--disable-gpu',
'--window-size=400,844',
`--screenshot=${outputFile}`,
'http://localhost:3000'
], { encoding: 'utf-8', timeout: 15000 });
console.log("Exit code:", res.status);
if (fs.existsSync(outputFile)) {
console.log("Screenshot successfully saved to:", outputFile, "Size:", fs.statSync(outputFile).size, "bytes");
} else {
console.log("Screenshot file not found.");
}
+37
View File
@@ -0,0 +1,37 @@
const http = require('http');
function testUrl(url) {
return new Promise((resolve) => {
const start = Date.now();
console.log(`[TEST] Fetching ${url}...`);
const req = http.get(url, { timeout: 5000 }, (res) => {
let data = '';
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => {
const duration = Date.now() - start;
console.log(`[TEST] ${url} -> Status: ${res.statusCode}, Time: ${duration}ms, Bytes: ${data.length}`);
resolve({ url, status: res.statusCode, duration, bytes: data.length });
});
});
req.on('error', (err) => {
const duration = Date.now() - start;
console.log(`[TEST] ${url} -> ERROR: ${err.message}, Time: ${duration}ms`);
resolve({ url, error: err.message, duration });
});
req.on('timeout', () => {
req.destroy();
const duration = Date.now() - start;
console.log(`[TEST] ${url} -> TIMEOUT after ${duration}ms`);
resolve({ url, timeout: true, duration });
});
});
}
async function run() {
console.log('=== STARTING DASHBOARD ROUTE SPEED TEST ===');
await testUrl('http://127.0.0.1:3001/api/dashboard/devices');
await testUrl('http://127.0.0.1:3001/api/dashboard/summary');
console.log('=== TEST COMPLETE ===');
}
run();