handle_get(), 'POST' => handle_post(), default => error_out('Method not allowed', 405), }; } catch (PDOException $e) { error_out('Database error: ' . $e->getMessage(), 500); } // ─── GET /api/admin.php ─────────────────────────────────────────────────────── function handle_get(): never { $db = db(); // migrations run inside db() $sandbox_mode = (bool) (int) ($db->query( "SELECT setting_value FROM `system` WHERE setting_name = 'sandbox_mode'" )->fetchColumn()); $counts = $db->query( "SELECT COUNT(*) AS total, SUM(is_sandbox = 1) AS sandbox_count, SUM(is_sandbox = 0 AND status IN ('sent','delivered')) AS real_sent, SUM(is_sandbox = 0 AND status = 'failed') AS real_failed FROM delivery_log" )->fetch(); $groups_raw = $_SERVER['HTTP_X_AUTHENTIK_GROUPS'] ?? ''; $groups = ($groups_raw !== '') ? explode('|', $groups_raw) : []; $is_admin = in_array('imf_sms_admin', $groups, true); $username = $_SERVER['HTTP_X_AUTHENTIK_USERNAME'] ?? ''; $name = $_SERVER['HTTP_X_AUTHENTIK_NAME'] ?? $username; json_out([ 'sandbox_mode' => $sandbox_mode, 'is_admin' => $is_admin, 'username' => $username, 'name' => $name, 'delivery_log_total' => (int) ($counts['total'] ?? 0), 'delivery_log_sandbox' => (int) ($counts['sandbox_count'] ?? 0), 'delivery_log_real_sent' => (int) ($counts['real_sent'] ?? 0), 'delivery_log_real_failed' => (int) ($counts['real_failed'] ?? 0), 'attendees' => (int) $db->query('SELECT COUNT(*) FROM attendees')->fetchColumn(), 'templates' => (int) $db->query('SELECT COUNT(*) FROM sms_templates')->fetchColumn(), 'schedules' => (int) $db->query('SELECT COUNT(*) FROM scheduled_rules')->fetchColumn(), ]); } // ─── Admin guard ───────────────────────────────────────────────────────────── function require_admin(): void { $groups_raw = $_SERVER['HTTP_X_AUTHENTIK_GROUPS'] ?? ''; $groups = ($groups_raw !== '') ? explode('|', $groups_raw) : []; if (!in_array('imf_sms_admin', $groups, true)) { error_out('Forbidden — requires imf_sms_admin group', 403); } } // ─── POST /api/admin.php ────────────────────────────────────────────────────── function handle_post(): never { require_admin(); $body = json_body(); $action = (string) ($body['action'] ?? ''); match ($action) { 'toggle_sandbox' => action_toggle_sandbox(), 'mark_all_sandbox' => action_mark_all_sandbox(), 'purge' => action_purge($body), default => error_out('Unknown action'), }; } function action_toggle_sandbox(): never { $db = db(); $current = (int) $db->query( "SELECT setting_value FROM `system` WHERE setting_name = 'sandbox_mode'" )->fetchColumn(); $new = $current ? '0' : '1'; $db->prepare( "UPDATE `system` SET setting_value = :v WHERE setting_name = 'sandbox_mode'" )->execute([':v' => $new]); json_out(['sandbox_mode' => (bool) (int) $new]); } function action_mark_all_sandbox(): never { db()->exec('UPDATE delivery_log SET is_sandbox = 1'); json_out(['updated' => true]); } function action_purge(array $body): never { $target = (string) ($body['target'] ?? ''); $db = db(); match ($target) { 'delivery_log' => purge_delivery_log($db, $body), 'attendees' => purge_attendees($db), 'templates' => purge_templates($db), 'schedules' => purge_schedules($db), default => error_out('Unknown purge target'), }; } function purge_delivery_log(PDO $db, array $body): never { $before = isset($body['before']) ? trim((string) $body['before']) : ''; if ($before !== '') { if (strtotime($before) === false) { error_out('Invalid date'); } $stmt = $db->prepare('DELETE FROM delivery_log WHERE sent_at < :before'); $stmt->execute([':before' => $before]); json_out(['purged' => $stmt->rowCount()]); } $db->exec('DELETE FROM delivery_log'); json_out(['purged' => true]); } function purge_attendees(PDO $db): never { $db->exec('DELETE FROM registrations'); $db->exec('DELETE FROM attendees'); $db->exec('DELETE FROM workshop_sessions'); json_out(['purged' => true]); } function purge_templates(PDO $db): never { $db->exec('DELETE FROM sms_templates'); json_out(['purged' => true]); } function purge_schedules(PDO $db): never { $db->exec('DELETE FROM scheduled_rules'); json_out(['purged' => true]); }