feat(prod): production deployment fixes - env loader, mongoose module, CSS static files, security hardening, PDF export, new UI components
This commit is contained in:
1 parent
a403f752f3
commit
46f33eb088
69 files changed
+7367
-744
No files matched your search
@@ -0,0 +1,121 @@
|
||||
// scripts/final-check.js
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// BackOne DPI — Final production health check
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
'use strict';
|
||||
|
||||
const { Client: SshClient } = require('ssh2');
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
|
||||
const CONFIG = {
|
||||
host: '103.185.47.52',
|
||||
port: 2222,
|
||||
username: 'adminbackend',
|
||||
password: 'htEo7x6LsBQiEHHH',
|
||||
};
|
||||
|
||||
const PM2 = '/home/adminbackend/.npm-global/bin/pm2';
|
||||
const ROOT = '/home/adminbackend/web/demoplace.my.id/public_html';
|
||||
|
||||
function fetch(url, followRedirects = false) {
|
||||
return new Promise(resolve => {
|
||||
const mod = url.startsWith('https') ? https : http;
|
||||
const opts = { timeout: 12000, rejectUnauthorized: false };
|
||||
if (!followRedirects) opts.agent = false;
|
||||
const req = mod.get(url, opts, res => {
|
||||
let body = '';
|
||||
res.on('data', d => body += d);
|
||||
res.on('end', () => resolve({ status: res.statusCode, headers: res.headers, body: body.substring(0, 300) }));
|
||||
});
|
||||
req.on('error', e => resolve({ status: 0, error: e.message }));
|
||||
req.on('timeout', () => { req.destroy(); resolve({ status: 0, error: 'timeout' }); });
|
||||
});
|
||||
}
|
||||
|
||||
function runSsh(commands) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const ssh = new SshClient();
|
||||
ssh.on('ready', () => {
|
||||
let i = 0;
|
||||
function next() {
|
||||
if (i >= commands.length) { ssh.end(); return; }
|
||||
const cmd = commands[i++];
|
||||
console.log(`\n$ ${cmd}`);
|
||||
ssh.exec(cmd, (err, stream) => {
|
||||
if (err) { console.error('[ERR]', err.message); next(); return; }
|
||||
stream.on('data', d => process.stdout.write(d.toString()));
|
||||
stream.stderr.on('data', d => { const t = d.toString(); if (!t.includes('npm warn') && !t.includes('notice')) process.stdout.write(t); });
|
||||
stream.on('close', next);
|
||||
});
|
||||
}
|
||||
next();
|
||||
ssh.on('end', resolve);
|
||||
});
|
||||
ssh.on('error', reject);
|
||||
ssh.connect({ ...CONFIG, readyTimeout: 30000 });
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('\n╔══════════════════════════════════════════════════════════════╗');
|
||||
console.log('║ BackOne DPI — Final Production Verification ║');
|
||||
console.log('╚══════════════════════════════════════════════════════════════╝\n');
|
||||
|
||||
// SSH internal checks
|
||||
await runSsh([
|
||||
`${PM2} list`,
|
||||
`echo "=== FRONTEND ===" && curl -s -o /dev/null -w "HTTP %{http_code}" http://127.0.0.1:3000/`,
|
||||
`echo "=== LOGIN PAGE ===" && curl -s -o /dev/null -w "HTTP %{http_code}" http://127.0.0.1:3000/login`,
|
||||
`echo "=== BACKEND ===" && curl -s http://127.0.0.1:3001/api/health`,
|
||||
// Test full login flow
|
||||
`echo "=== LOGIN API ===" && curl -s -X POST http://127.0.0.1:3001/api/auth/login -H "Content-Type: application/json" -d '{"username":"admin","password":"admin"}' | python3 -c "import sys,json; d=json.load(sys.stdin); print('Login OK - Role:', d.get('user',{}).get('role','?'))" 2>/dev/null || curl -s -X POST http://127.0.0.1:3001/api/auth/login -H "Content-Type: application/json" -d '{"username":"admin","password":"admin"}'`,
|
||||
// Security checks
|
||||
`echo "=== SECURITY: Port 3001 ===" && ss -tlnp | grep 3001`,
|
||||
`echo "=== SECURITY: Port 4000 ===" && ss -tlnp | grep 4000`,
|
||||
`echo "=== SECURITY: No .env in standalone ===" && find ${ROOT}/.next/standalone -name ".env*" 2>/dev/null || echo "CLEAN"`,
|
||||
// Proxy MongoDB
|
||||
`echo "=== PROXY MONGO ===" && ${PM2} logs backone-proxy --lines 5 --nostream 2>&1 | grep -E "(MongoDB|Scheduler|Connected|Capacity)" | tail -5`,
|
||||
// Domain via HTTP (should 301 → HTTPS)
|
||||
`echo "=== DOMAIN HTTP ===" && curl -s -o /dev/null -w "HTTP %{http_code}" http://demoplace.my.id/`,
|
||||
// Domain via HTTPS from server itself
|
||||
`echo "=== DOMAIN HTTPS ===" && curl -sk -o /dev/null -w "HTTP %{http_code}" https://demoplace.my.id/ 2>&1`,
|
||||
]);
|
||||
|
||||
// External checks from local machine
|
||||
console.log('\n\n══ External checks from local machine ══\n');
|
||||
|
||||
const tests = [
|
||||
{ url: 'https://demoplace.my.id/', label: 'Root (expect 307 redirect to /login)' },
|
||||
{ url: 'https://demoplace.my.id/login', label: 'Login page (expect 200)' },
|
||||
{ url: 'https://demoplace.my.id/api/health', label: 'Backend health via domain (expect 200)' },
|
||||
{ url: 'http://demoplace.my.id/', label: 'HTTP root (expect 301 HTTPS redirect)' },
|
||||
];
|
||||
|
||||
for (const { url, label } of tests) {
|
||||
const r = await fetch(url);
|
||||
const ok = r.status >= 200 && r.status < 400;
|
||||
const icon = ok ? '✅' : r.status === 0 ? '⚠️ ' : '❌';
|
||||
console.log(` ${icon} [${String(r.status).padEnd(3)}] ${label}`);
|
||||
if (r.headers?.location) console.log(` → Redirect: ${r.headers.location}`);
|
||||
if (r.error) console.log(` → Error: ${r.error}`);
|
||||
if (r.status === 200 && r.body) {
|
||||
const preview = r.body.replace(/\s+/g, ' ').substring(0, 80);
|
||||
console.log(` → Body: ${preview}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n══════════════════════════════════════════════════════════════');
|
||||
console.log(' Deployment Summary:');
|
||||
console.log(' ┌─────────────────────────────────────────────────────┐');
|
||||
console.log(' │ 🌐 Dashboard URL : https://demoplace.my.id │');
|
||||
console.log(' │ 🔒 Backend : 127.0.0.1:3001 (internal only) │');
|
||||
console.log(' │ 🔒 Proxy : 127.0.0.1:4000 (internal only) │');
|
||||
console.log(' │ 🗄️ MongoDB : mongodb.prod.proit.id:27017 │');
|
||||
console.log(' │ 🚀 Node.js : v18.19.1 │');
|
||||
console.log(' │ ⚙️ PM2 : 3 processes (all online) │');
|
||||
console.log(' └─────────────────────────────────────────────────────┘');
|
||||
console.log('══════════════════════════════════════════════════════════\n');
|
||||
}
|
||||
|
||||
main().catch(err => { console.error('[FATAL]', err); process.exit(1); });
|
||||
Reference in new issue
Block a user