prepare('SELECT id FROM users WHERE username=? OR email=?'); $chk->execute([$new_username, $new_email]); if ($chk->fetch()) { $errors[] = 'Username or email already in use.'; } else { $hash = password_hash($new_password, PASSWORD_BCRYPT); $pdo->prepare(" INSERT INTO users (username,email,password_hash,display_name,role,rosary_limit,email_confirmed) VALUES (?,?,?,?,?,?,1) ")->execute([$new_username, $new_email, $hash, $new_display_name ?: $new_username, $new_role, $new_limit]); $messages[] = "User '{$new_username}' created."; } } } // ── Update user ────────────────────────────────────────────────────────── if ($action === 'update_user') { $target_id = (int)($_POST['target_id'] ?? 0); $upd_display = trim($_POST['upd_display_name'] ?? ''); $upd_email = trim($_POST['upd_email'] ?? ''); $upd_role = $_POST['upd_role'] ?? ''; $upd_limit = (int)($_POST['upd_rosary_limit'] ?? 1); // Fetch target to check if superadmin $tgt = $pdo->prepare('SELECT * FROM users WHERE id=?'); $tgt->execute([$target_id]); $tgt = $tgt->fetch(); if (!$tgt) { $errors[] = 'User not found.'; } else { // Role protection $allowed_roles = $is_super ? ['user','superuser','admin','superadmin'] : ['user','superuser']; if (!in_array($upd_role, $allowed_roles, true)) $upd_role = $tgt['role']; // Non-superadmin cannot change superadmin's role if (!$is_super && $tgt['role'] === 'superadmin') { $errors[] = 'Cannot modify a superadmin account.'; } else { if (!filter_var($upd_email, FILTER_VALIDATE_EMAIL)) { $errors[] = 'Invalid email.'; } else { $chk = $pdo->prepare('SELECT id FROM users WHERE email=? AND id!=?'); $chk->execute([$upd_email, $target_id]); if ($chk->fetch()) { $errors[] = 'Email already in use by another account.'; } else { $pdo->prepare('UPDATE users SET display_name=?,email=?,role=?,rosary_limit=? WHERE id=?') ->execute([$upd_display, $upd_email, $upd_role, $upd_limit, $target_id]); $messages[] = "User '{$tgt['username']}' updated."; } } } } } // ── Reset password ─────────────────────────────────────────────────────── if ($action === 'reset_password') { $target_id = (int)($_POST['target_id'] ?? 0); $new_pass = $_POST['new_pass'] ?? ''; if (strlen($new_pass) < 8) { $errors[] = 'New password must be at least 8 characters.'; } else { $hash = password_hash($new_pass, PASSWORD_BCRYPT); $pdo->prepare('UPDATE users SET password_hash=? WHERE id=?')->execute([$hash, $target_id]); $messages[] = 'Password reset successfully.'; } } // ── Resend confirmation email ───────────────────────────────────────────── if ($action === 'resend_confirmation') { $target_id = (int)($_POST['target_id'] ?? 0); $tgt = $pdo->prepare('SELECT * FROM users WHERE id = ? AND email_confirmed = 0'); $tgt->execute([$target_id]); $tgt = $tgt->fetch(); if (!$tgt) { $errors[] = 'User not found or already confirmed.'; } else { $smtp_host = get_setting('smtp_host'); if ($smtp_host === '') { // No SMTP — confirm directly $pdo->prepare('UPDATE users SET email_confirmed = 1, confirm_token = NULL WHERE id = ?') ->execute([$target_id]); $messages[] = "No SMTP configured — {$tgt['username']} has been confirmed directly."; } else { $token = bin2hex(random_bytes(32)); $site_url = rtrim(get_setting('site_url'), '/'); $site_name = get_setting('site_name', APP_NAME); $link = $site_url . '/confirm?token=' . urlencode($token); $disp = $tgt['display_name'] ?: $tgt['username']; $pdo->prepare('UPDATE users SET confirm_token = ? WHERE id = ?') ->execute([$token, $target_id]); $body_html = "

Confirm your email

Hello, " . htmlspecialchars($disp) . "!

An administrator has resent your confirmation email for {$site_name}. Click the button below to confirm your email address and activate your account:

Confirm Email

Or copy this link: " . htmlspecialchars($link) . "

If you did not register, ignore this email.

"; $html = email_template('Confirm your email — ' . $site_name, $body_html); $ok = send_email($tgt['email'], $disp, 'Confirm your email — ' . $site_name, $html); if ($ok) { $messages[] = "Confirmation email resent to {$tgt['email']}."; } else { $errors[] = 'Failed to send email. Check your SMTP settings.'; } } } } // ── Delete user ────────────────────────────────────────────────────────── if ($action === 'delete_user') { $target_id = (int)($_POST['target_id'] ?? 0); if ($target_id === $uid) { $errors[] = 'You cannot delete your own account.'; } else { $tgt = $pdo->prepare('SELECT role,username FROM users WHERE id=?'); $tgt->execute([$target_id]); $tgt = $tgt->fetch(); if ($tgt && $tgt['role'] === 'superadmin' && !$is_super) { $errors[] = 'Cannot delete a superadmin account.'; } elseif ($tgt) { $pdo->prepare('DELETE FROM users WHERE id=?')->execute([$target_id]); $messages[] = "User '{$tgt['username']}' deleted."; } } } } // ── Load all users with rosary counts ──────────────────────────────────────── $users = $pdo->query(" SELECT u.*, (SELECT COUNT(*) FROM sessions WHERE user_id=u.id AND occasion != 'novena_deceased') + (SELECT COUNT(*) FROM novena_groups WHERE user_id=u.id) AS rosary_count FROM users u ORDER BY u.created_at DESC ")->fetchAll(); $role_labels = ['superadmin'=>'Superadmin','admin'=>'Admin','superuser'=>'Superuser','user'=>'User']; $role_colors = [ 'superadmin' => '#dc2626', 'admin' => '#ea580c', 'superuser' => '#2563eb', 'user' => '#6b7280', ]; ?> Users — <?= htmlspecialchars($site_name) ?>

Users ()

Create New User

Username Display Name Email Role Limit Rosaries Joined Actions
Unconfirmed' : '' ?>