fix: recover full admin.js from server, fix port redirects and account create validation

- admin.js: 1292 lines of features were on server but not in repo — recovered and committed
- admin.js: impersonation redirect now uses location.origin instead of hardcoded :8880 port
- accounts.php: pre-validate email uniqueness and username before INSERT to prevent SQLSTATE 23000
- accounts.php: wrap user INSERT + AccountManager::create() in single transaction for full rollback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LP9Q4kfCAYAjJnsbHBrViZ
This commit is contained in:
2026-06-20 05:33:31 +00:00
parent 7185fcca5f
commit b077226581
2 changed files with 1489 additions and 186 deletions
+13 -2
View File
@@ -69,7 +69,13 @@ match ($action) {
$required = ['username','domain','email','password']; $required = ['username','domain','email','password'];
foreach ($required as $f) { if (empty($body[$f])) Response::error("$f is required"); } foreach ($required as $f) { if (empty($body[$f])) Response::error("$f is required"); }
// Create user account if (!filter_var($body['email'], FILTER_VALIDATE_EMAIL)) Response::error("Invalid email address");
if ($db->fetchOne("SELECT id FROM users WHERE email = ?", [$body['email']])) Response::error("Email already in use by another account");
if ($db->fetchOne("SELECT id FROM users WHERE username = ?", [$body['username']])) Response::error("Username already taken");
// Wrap user creation + account provisioning in a single transaction
$db->beginTransaction();
try {
$userId = (int)$db->insert( $userId = (int)$db->insert(
"INSERT INTO users (username, password, email, role, status, reseller_id) VALUES (?,?,?,?,?,?)", "INSERT INTO users (username, password, email, role, status, reseller_id) VALUES (?,?,?,?,?,?)",
[ [
@@ -84,8 +90,13 @@ match ($action) {
$body['user_id'] = $userId; $body['user_id'] = $userId;
$result = AccountManager::create($body); $result = AccountManager::create($body);
$db->commit();
} catch (Throwable $e) {
$db->rollBack();
throw $e;
}
audit('account.create', $body['domain'], $result); audit('account.create', $body['domain'], $result);
// Send welcome email to user + admin notification
Notifier::accountCreated(array_merge($body, ['email' => $body['email']]), $body['password']); Notifier::accountCreated(array_merge($body, ['email' => $body['email']]), $body['password']);
Response::success($result, 'Account created successfully'); Response::success($result, 'Account created successfully');
})(), })(),
+1452 -160
View File
File diff suppressed because it is too large Load Diff