diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bcd07e..7725432 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ Format mengikuti [Keep a Changelog](https://keepachangelog.com/) dan [Semantic Versioning](https://semver.org/). +## [Unreleased] — setelah v0.5.1 + +### Diperbaiki +- Kolom **IP Address** di **GenieACS Pro** kini tampil saat **mode pencarian** (sebelumnya kosong). +- Menu **Update GitHub** otomatis disembunyikan pada instalasi **tanpa `.git`** (container/Docker), tetap tampil pada instalasi git. + +### Ditambahkan +- **Badge kelengkapan data** di daftar pelanggan: centang hijau = **nomor HP + koordinat + ACS** lengkap; silang merah = ada yang kurang (tooltip menyebut yang belum). +- **Backend speedtest bawaan** (`/speedtest/*`) kini aktif (LibreSpeed self-hosted, same-origin). +- `isolir-redirect-server` dapat dijalankan **embedded** dalam proses app (opt-out via `ISOLIR_REDIRECT_EMBEDDED=0`). + ## [0.5.1] — 2026-10-13 — "pickle-lime" ### Diubah diff --git a/app-customer.js b/app-customer.js index 0740472..204cec7 100644 --- a/app-customer.js +++ b/app-customer.js @@ -67,6 +67,7 @@ const app = express(); // Kompresi gzip (performa: respons HTML/CSS/JS lebih kecil) app.use(compression()); +app.use('/speedtest', require('./routes/speedtest')); const isProduction = process.env.NODE_ENV === 'production'; const cookieSecure = getSetting('cookie_secure', isProduction); @@ -2242,3 +2243,8 @@ app.use(errorHandler); // Export app untuk testing module.exports = app; + +// isolir redirect server embedded (port 8099) — untuk container/reverse-proxy; opt-out: ISOLIR_REDIRECT_EMBEDDED=0 +if (String(process.env.ISOLIR_REDIRECT_EMBEDDED || '1') !== '0') { + try { require('./isolir-redirect-server.js'); } catch (e) { console.error('[isolir-redirect]', e.message); } +} diff --git a/config/database.js b/config/database.js index b154a24..ea9c2a9 100644 --- a/config/database.js +++ b/config/database.js @@ -546,7 +546,9 @@ function forceUnlockCoreMenus() { let states = rowStates ? JSON.parse(rowStates.value) : {}; let keys = rowKeys ? JSON.parse(rowKeys.value) : {}; - const coreMenus = ['mikrotik', 'radius_server', 'whatsapp', 'broadcast', 'update', 'settings', 'backup', 'monitoring', 'audit_logs']; + const hasGit = fs.existsSync(path.join(__dirname, '..', '.git')); + const coreMenus = ['mikrotik', 'radius_server', 'whatsapp', 'broadcast', 'settings', 'backup', 'monitoring', 'audit_logs']; + if (hasGit) coreMenus.push('update'); const passwordHash = 'af03458614be223016c5bc1c0788eaefc6a6bfd0c11cdcd4bc520f49d0cb474a'; // hash kode aktivasi default — plaintext hanya di settings.json (activation_code) const crypto = require('crypto'); @@ -569,6 +571,8 @@ function forceUnlockCoreMenus() { } } + if (!hasGit && states['update'] !== 'hidden') { states['update'] = 'hidden'; changed = true; } + if (changed) { const now = new Date().toISOString(); db.prepare('INSERT OR REPLACE INTO app_settings (key, value, updated_at) VALUES (?, ?, ?)').run(SETTINGS_KEY, JSON.stringify(states), now); diff --git a/isolir-redirect-server.js b/isolir-redirect-server.js index 798b063..e6969bb 100644 --- a/isolir-redirect-server.js +++ b/isolir-redirect-server.js @@ -37,6 +37,8 @@ const server = http.createServer((req, res) => { ); }); +server.on('error', (e) => console.error('[isolir-redirect] listen error:', e.message)); + server.listen(PORT, '0.0.0.0', () => { console.log(`[isolir-redirect] listening on 0.0.0.0:${PORT} -> ${TARGET}`); }); diff --git a/routes/acsPortal.js b/routes/acsPortal.js index 2e4fe76..e7b0b5e 100644 --- a/routes/acsPortal.js +++ b/routes/acsPortal.js @@ -1052,6 +1052,7 @@ router.get('/', async (req, res) => { model: d._deviceId?._ProductClass || '-', rx_power: rxPower, pppoe_ip: ip, + ip: ip, pppoe_user: pppoeUser, customer_name: customerName, acs_server_id: server.id, diff --git a/views/admin/acs.ejs b/views/admin/acs.ejs index 8fc8f31..558c6bc 100644 --- a/views/admin/acs.ejs +++ b/views/admin/acs.ejs @@ -174,7 +174,7 @@ - <% } %> -
<%= d.ip %><%= d.ip || d.pppoe_ip || '-' %>