/** * NovaCPX Admin Panel — page controllers */ (async () => { // ── Auth guard ───────────────────────────────────────────────────────────── const me = await Nova.api('auth', 'me'); if (!me?.success || me.data.role !== 'admin') { location.href = '/?redirect=/admin/'; return; } document.getElementById('auth-check').style.display = 'none'; document.getElementById('app').style.display = ''; document.getElementById('user-name').textContent = me.data.username; document.getElementById('user-avatar').textContent = me.data.username[0].toUpperCase(); // ── Logout ───────────────────────────────────────────────────────────────── document.getElementById('logout-btn').addEventListener('click', async e => { e.preventDefault(); await Nova.api('auth', 'logout', { method: 'POST' }); location.href = '/'; }); // ── Page definitions ─────────────────────────────────────────────────────── const pages = { dashboard, 'server-status': serverStatus, accounts, resellers, packages, 'create-account': createAccount, 'dns-zones': dnsZones, nameservers, 'web-server': webServer, 'php-manager': phpManager, 'mysql-manager': mysqlManager, 'mail-server': mailServer, 'ftp-server': ftpServer, 'ssl-manager': sslManager, firewall, 'audit-log': auditLog, updates, backups, settings, }; Nova.initNav(pages); await Nova.loadPage('dashboard', pages); checkUpdates(); // ── Dashboard ────────────────────────────────────────────────────────────── async function dashboard() { const [stats, version] = await Promise.all([ Nova.api('system', 'stats'), Nova.api('system', 'version'), ]); const s = stats?.data || {}; const v = version?.data || {}; document.getElementById('server-ip').textContent = ''; return `
CPU Usage
${s.cpu?.pct ?? 0}%
Load: ${(s.cpu?.load || [0,0,0]).join(' / ')}
${Nova.progressBar(s.cpu?.pct || 0)}
Memory
${s.ram?.pct ?? 0}%
${Nova.bytes((s.ram?.used_kb||0)*1024)} / ${Nova.bytes((s.ram?.total_kb||0)*1024)}
${Nova.progressBar(s.ram?.pct || 0)}
Disk
${s.disk?.pct ?? 0}%
${Nova.bytes(s.disk?.total - s.disk?.free || 0)} used
${Nova.progressBar(s.disk?.pct || 0)}
Uptime
${s.uptime || '—'}
PHP ${v.php_version || '—'}
Services
${Object.entries(s.services || {}).map(([svc, status]) => ` `).join('')}
${Nova.serviceDot(status)} ${svc} ${Nova.badge(status, status === 'active' ? 'green' : 'red')}
NovaCPX Version
Installed${v.installed_version || '—'}
Branch${v.git_branch || 'main'}
Commit${v.git_commit || '—'}${v.git_dirty ? ' dirty' : ''}
PHP${v.php_version || '—'}
OS${v.os || '—'}
`; } // ── Server Status ────────────────────────────────────────────────────────── async function serverStatus() { const res = await Nova.api('system', 'stats'); const s = res?.data || {}; return `
Real-Time Server Status

CPU

${s.cpu?.pct}%

${Nova.progressBar(s.cpu?.pct||0)}

RAM

${s.ram?.pct}%

${Nova.progressBar(s.ram?.pct||0)}

Disk

${s.disk?.pct}%

${Nova.progressBar(s.disk?.pct||0)}

Load Average

${(s.cpu?.load||[]).join(' / ')}

Uptime

${s.uptime}

`; } // ── Updates ──────────────────────────────────────────────────────────────── async function updates() { const [ver, check] = await Promise.all([ Nova.api('system', 'version'), Nova.api('system', 'check-update'), ]); const v = ver?.data || {}; const upd = check?.data || {}; const count = upd.updates_available || 0; return `
NovaCPX Updates ${count > 0 ? Nova.badge(count + ' update' + (count > 1 ? 's' : '') + ' available', 'yellow') : Nova.badge('Up to date', 'green')}

Installed Version

${v.installed_version}

Git Commit

${v.git_commit || '—'}

Branch

${v.git_branch || 'main'}

Dirty Working Tree

${v.git_dirty ? Nova.badge('Yes','yellow') : Nova.badge('No','green')}

${count > 0 ? `
Pending Commits
${upd.commits?.map(c => `
${c}
`).join('') || 'None'}
` : `

NovaCPX is up to date.

`}
`; } // ── Audit Log ────────────────────────────────────────────────────────────── async function auditLog() { const res = await Nova.api('system', 'audit-log', { params: { per_page: 50 } }); const rows = res?.data || []; return `
Audit Log
${rows.map(r => ` `).join('')}
TimeUserActionResourceIP
${Nova.relTime(r.created_at)} ${r.username || '—'} ${r.action} ${r.resource || '—'} ${r.ip_address || '—'}
`; } // ── PHP Manager ──────────────────────────────────────────────────────────── async function phpManager() { return `
PHP Version Manager

Manage installed PHP versions and global extensions.

${['7.4','8.1','8.2','8.3'].map(v => `
PHP ${v}
${Nova.badge('Active','green')}
`).join('')}

Global PHP Extensions

Extensions installed across all PHP versions: mbstring, curl, gd, xml, zip, opcache, redis, imagick, pdo, pdo_mysql, pdo_pgsql

`; } // ── Settings ─────────────────────────────────────────────────────────────── async function settings() { return `
Panel Settings
`; } // ── Stub pages ───────────────────────────────────────────────────────────── function stubPage(title, desc) { return `
${title}

${desc}

${Nova.badge('Coming Soon','yellow')}
`; } function accounts() { return stubPage('All Accounts', 'View and manage all hosting accounts on this server.'); } function resellers() { return stubPage('Resellers', 'Create and manage reseller accounts with custom packages and resource limits.'); } function packages() { return stubPage('Packages', 'Define hosting packages with disk, bandwidth, email, FTP, and database limits.'); } function createAccount() { return stubPage('Create Account', 'Create a new hosting account and assign it a package.'); } function dnsZones() { return stubPage('DNS Zones', 'View, add, and edit all DNS zones on this nameserver.'); } function nameservers() { return stubPage('Nameservers', 'Configure primary and secondary nameservers for all hosted domains.'); } function webServer() { return stubPage('Web Server', 'Manage Apache2 / nginx virtual hosts, modules, and configuration.'); } function mysqlManager() { return stubPage('MySQL / PostgreSQL', 'Create databases, users, and manage remote access.'); } function mailServer() { return stubPage('Mail Server', 'Manage Postfix/Dovecot configuration, spam filters, and mail queues.'); } function ftpServer() { return stubPage('FTP Server', 'Configure ProFTPD, manage FTP accounts and access rules.'); } function sslManager() { return stubPage('SSL Manager', 'Issue, install, and auto-renew Let\'s Encrypt SSL certificates for all domains.'); } function firewall() { return stubPage('Firewall / Fail2Ban', 'Manage UFW rules and review Fail2Ban bans.'); } function backups() { return stubPage('Backups', 'Configure automated backups, restore accounts, and manage backup storage.'); } // ── Global action helpers ────────────────────────────────────────────────── window.adminPage = (page) => Nova.loadPage(page, pages); window.applyUpdate = async () => { Nova.confirm('Apply all pending updates? The panel may restart.', async () => { Nova.toast('Applying update…', 'info', 8000); const res = await Nova.api('system', 'apply-update', { method: 'POST' }); if (res?.data?.updated) { Nova.toast(`Updated to ${res.data.to_commit}`, 'success'); Nova.loadPage('updates', pages); } else { Nova.toast(res?.data?.pull_output || 'Already up to date', 'info'); } }); }; window.adminServiceAction = async (svc, cmd) => { const res = await Nova.api('system', 'service', { method: 'POST', body: { service: svc, command: cmd } }); Nova.toast(`${svc}: ${cmd} → ${res?.success ? 'OK' : res?.message}`, res?.success ? 'success' : 'error'); }; window.phpAction = async (ver, cmd) => { const svc = `php${ver}-fpm`; await window.adminServiceAction(svc, 'restart'); }; // ── Check for updates badge ──────────────────────────────────────────────── async function checkUpdates() { const res = await Nova.api('system', 'check-update'); const n = res?.data?.updates_available || 0; const badge = document.getElementById('update-badge'); if (badge && n > 0) { badge.textContent = n; badge.style.display = ''; } } })();