diff --git a/panel/api/endpoints/accounts.php b/panel/api/endpoints/accounts.php index 131ff69..ae06383 100644 --- a/panel/api/endpoints/accounts.php +++ b/panel/api/endpoints/accounts.php @@ -88,6 +88,46 @@ match ($action) { Response::success($result, 'Account created successfully'); })(), + 'update' => (function() use ($db, $body, $user, $ownerClause) { + $id = (int)($body['id'] ?? 0); + $acct = $db->fetchOne( + "SELECT a.*, u.email FROM accounts a JOIN users u ON u.id=a.user_id WHERE a.id=? $ownerClause", + [$id] + ); + if (!$acct) Response::error("Account not found", 404); + + $allowed = ['php_version', 'package_id', 'notes']; + $sets = []; $params = []; + foreach ($allowed as $col) { + if (array_key_exists($col, $body)) { + $sets[] = "`$col` = ?"; + $params[] = $body[$col] === '' ? null : $body[$col]; + } + } + // Email lives on users table + if (array_key_exists('email', $body) && filter_var($body['email'], FILTER_VALIDATE_EMAIL)) { + $db->execute("UPDATE users SET email=? WHERE id=?", [$body['email'], $acct['user_id']]); + } + if ($sets) { + $params[] = $id; + $db->execute("UPDATE accounts SET " . implode(', ', $sets) . " WHERE id=?", $params); + } + + // If PHP version changed, update the FPM pool + if (!empty($body['php_version']) && $body['php_version'] !== $acct['php_version']) { + require_once NOVACPX_LIB . '/PHPManager.php'; + try { + PHPManager::removePool($acct['username']); + PHPManager::createPool($acct['username'], $body['php_version']); + } catch (Throwable $e) { + novacpx_log('warn', "PHP pool update failed for {$acct['username']}: " . $e->getMessage()); + } + } + + audit('account.update', "account:$id", array_intersect_key($body, array_flip([...$allowed, 'email']))); + Response::success(null, 'Account updated'); + })(), + 'suspend' => (function() use ($db, $body, $ownerClause) { $id = (int)($body['id'] ?? 0); $acct = $db->fetchOne( diff --git a/panel/assets/js/admin.js b/panel/assets/js/admin.js index aca1082..237656c 100644 --- a/panel/assets/js/admin.js +++ b/panel/assets/js/admin.js @@ -743,16 +743,16 @@ function renderAccountTable(accts) { if (!accts.length) return '
| Username | Domain | Reseller | Package | Disk | Status | Created | Actions |
|---|
| Username | Domain | Package | PHP | Status | Created | Actions | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ${a.username} | ${a.domain} | -${a.reseller_username || 'admin'} | -${a.package_name || '—'} | -${a.disk_usage_mb || 0} MB | +${a.package_name || '—'} | +${a.php_version || '—'} | ${Nova.badge(a.status, a.status==='active'?'green':a.status==='suspended'?'yellow':'red')} | ${Nova.relTime(a.created_at)} | -+ |
+
${a.status==='active'
? ``
: ``}
@@ -792,6 +792,54 @@
}, true);
};
+ window.adminEditAccount = async (id) => {
+ const [acctRes, pkgRes] = await Promise.all([
+ Nova.api('accounts', 'get', { params: { id } }),
+ Nova.api('packages', 'list'),
+ ]);
+ if (!acctRes?.success) { Nova.toast(acctRes?.message || 'Failed to load account', 'error'); return; }
+ const a = acctRes.data;
+ const pkgs = pkgRes?.data || [];
+ const pkgOpts = `` +
+ pkgs.map(p => ``).join('');
+ const phpOpts = ['8.3','8.2','8.1','7.4'].map(v =>
+ ``).join('');
+
+ Nova.modal(`Edit Account — ${Nova.escHtml(a.username)}`,
+ `
+ `,
+ `
+ `
+ );
+ };
+
+ window.adminEditAccountSave = async (id) => {
+ const body = {
+ id,
+ email: document.getElementById('ae-email')?.value?.trim(),
+ package_id: document.getElementById('ae-pkg')?.value || null,
+ php_version: document.getElementById('ae-php')?.value,
+ };
+ Nova.loading('Saving…');
+ const res = await Nova.api('accounts', 'update', { method: 'POST', body });
+ Nova.loadingDone();
+ if (res?.success) {
+ document.querySelector('.modal-overlay')?.remove();
+ Nova.toast('Account updated', 'success');
+ adminPage('accounts');
+ } else {
+ Nova.toast(res?.message || 'Update failed', 'error');
+ }
+ };
+
// ── Create Account ─────────────────────────────────────────────────────────
async function createAccount() {
const pkgRes = await Nova.api('packages', 'list');
diff --git a/panel/public/assets/js/admin.js b/panel/public/assets/js/admin.js
index aca1082..237656c 100644
--- a/panel/public/assets/js/admin.js
+++ b/panel/public/assets/js/admin.js
@@ -743,16 +743,16 @@
function renderAccountTable(accts) {
if (!accts.length) return '
+
+
+
+
+
+
+
+ No accounts found. ';
- return `
|