"ALTER TABLE users ADD COLUMN suspension_reason VARCHAR(500) NULL AFTER account_suspended", 'suspended_until' => "ALTER TABLE users ADD COLUMN suspended_until DATETIME NULL AFTER suspension_reason", 'suspended_by' => "ALTER TABLE users ADD COLUMN suspended_by INT UNSIGNED NULL AFTER suspended_until", ]; $db = (string)$pdo->query('SELECT DATABASE()')->fetchColumn(); foreach ($columnsToAdd as $col => $sql) { $check = $pdo->prepare('SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = ? AND table_name = ? AND column_name = ?'); $check->execute([$db, 'users', $col]); if ((int)$check->fetchColumn() === 0) { try { $pdo->exec($sql); } catch (Throwable $e) { } } } // Ensure history table exists. try { $pdo->exec("CREATE TABLE IF NOT EXISTS user_account_history ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id INT UNSIGNED NOT NULL, action ENUM('suspend', 'unsuspend') NOT NULL, reason TEXT NULL, suspended_until DATETIME NULL, performed_by INT UNSIGNED NULL, performed_by_username VARCHAR(50) NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY idx_uah_user_id (user_id), KEY idx_uah_created_at (created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"); } catch (Throwable $e) { } $body = admin_read_json_body(); $action = isset($body['action']) ? (string)$body['action'] : ''; $userId = isset($body['user_id']) ? (int)$body['user_id'] : 0; if ($userId <= 0) { admin_json_error('Nieprawidłowy user_id'); } if (!in_array($action, ['suspend', 'unsuspend'], true)) { admin_json_error('Nieprawidłowa akcja'); } // Fetch target user $stmtUser = $pdo->prepare("SELECT id, username, email, role, account_suspended FROM users WHERE id = ? LIMIT 1"); $stmtUser->execute([$userId]); $targetUser = $stmtUser->fetch(PDO::FETCH_ASSOC); if (!$targetUser) { admin_json_error('Użytkownik nie istnieje', 404); } $targetRole = strtolower((string)($targetUser['role'] ?? 'user')); if ((int)$targetUser['id'] === (int)$adminId) { admin_json_error('Nie możesz zarządzać swoim kontem w tym widoku.', 403); } if ($targetRole === 'admin') { admin_json_error('Nie można zarządzać kontami administratorów w tym widoku.', 403); } $targetEmail = trim((string)($targetUser['email'] ?? '')); if ($action === 'suspend') { $reason = trim((string)($body['reason'] ?? '')); if ($reason === '') { admin_json_error('Powód zawieszenia jest wymagany'); } $suspendedUntilRaw = (string)($body['suspended_until'] ?? 'permanent'); $suspendedUntil = null; $suspendedUntilDisplay = 'bezterminowo'; if ($suspendedUntilRaw !== 'permanent') { $ts = strtotime($suspendedUntilRaw); if ($ts === false || $ts <= time()) { admin_json_error('Nieprawidłowa data zawieszenia - musi być w przyszłości'); } $suspendedUntil = date('Y-m-d H:i:s', $ts); $suspendedUntilDisplay = date('d.m.Y H:i', $ts); } try { $pdo->prepare("UPDATE users SET account_suspended = 1, suspension_reason = ?, suspended_until = ?, suspended_by = ?, wallet_status = 'suspended' WHERE id = ?") ->execute([$reason, $suspendedUntil, $adminId, $userId]); } catch (Throwable $e) { try { $pdo->prepare("UPDATE users SET account_suspended = 1 WHERE id = ?")->execute([$userId]); } catch (Throwable $e2) { admin_json_error('Błąd aktualizacji bazy danych: ' . $e2->getMessage(), 500); } } try { $pdo->prepare("INSERT INTO user_account_history (user_id, action, reason, suspended_until, performed_by, performed_by_username) VALUES (?, 'suspend', ?, ?, ?, ?)") ->execute([$userId, $reason, $suspendedUntil, $adminId, $adminUsername]); } catch (Throwable $e) { } $emailSent = false; $emailError = ''; try { $untilHtml = $suspendedUntil ? '' . htmlspecialchars($suspendedUntilDisplay, ENT_QUOTES, 'UTF-8') . '' : 'bezterminowo'; $safeUsernameSuspend = htmlspecialchars((string)$targetUser['username'], ENT_QUOTES, 'UTF-8'); $safeReasonSuspend = nl2br(htmlspecialchars($reason, ENT_QUOTES, 'UTF-8')); $safeSupportEmailSuspend = htmlspecialchars($supportEmail, ENT_QUOTES, 'UTF-8'); $safeSupportUrlSuspend = htmlspecialchars($supportUrl, ENT_QUOTES, 'UTF-8'); $emailBody = 'Konto zawieszone

⚠ Konto zawieszone

Powiadomienie dotyczące Twojego konta TOGETHERE

Cześć ' . $safeUsernameSuspend . ',

Informujemy, że Twoje konto w serwisie TOGETHERE GAMES zostało zawieszone przez administrację serwisu.

Powód zawieszenia
' . $safeReasonSuspend . '
Zawieszone do
' . $untilHtml . '

Co to oznacza?

  • Nie możesz się zalogować na swoje konto.
  • Dostęp do funkcji serwisu jest zablokowany do czasu odwieszenia.
  • Twoje dane i historia są bezpiecznie przechowywane.
  • ' . ($suspendedUntil ? '
  • Po upłynięciu terminu (' . htmlspecialchars($suspendedUntilDisplay, ENT_QUOTES, 'UTF-8') . ') konto zostanie automatycznie odwieszone.
  • ' : '') . '

Chcesz złożyć odwołanie?

Jeżeli uważasz, że decyzja została podjęta błędnie, możesz skontaktować się z naszym Biurem Obsługi Klienta:

📧 E-mail: ' . $safeSupportEmailSuspend . '
🌐 BOK online: ' . $safeSupportUrlSuspend . '

W wiadomości podaj swój login oraz opisz sytuację — postaramy się odpowiedzieć możliwie szybko.


Wiadomość wygenerowana automatycznie — prosimy nie odpowiadać bezpośrednio na ten e-mail.
TOGETHERE GAMES • togethere.cloud

'; $emailSent = (bool)sendEmailSMTP($targetEmail, 'Twoje konto zostało zawieszone - Wspólnie', $emailBody); if (!$emailSent) { // Fallback przez mail() jeśli SMTP nie zadziałał $mHeaders = "MIME-Version: 1.0\r\n"; $mHeaders .= "Content-Type: text/html; charset=UTF-8\r\n"; $mHeaders .= "From: TOGETHERE GAMES \r\n"; $mHeaders .= "Reply-To: " . $supportEmail . "\r\n"; $emailSent = @mail($targetEmail, '=?UTF-8?B?' . base64_encode('Twoje konto zostało zawieszone - Wspólnie') . '?=', $emailBody, $mHeaders); if (!$emailSent) { $emailError = 'Wysyłka nie powiodła się (SMTP + mail). Sprawdź smtp_debug.log.'; } } } catch (Throwable $e) { $emailError = $e->getMessage(); } $msg = 'Konto użytkownika zostało zawieszone.'; if (!$emailSent) { $msg .= ' ⚠️ Email NIE został wysłany: ' . $emailError; } admin_json_response(['success' => true, 'message' => $msg, 'email_sent' => $emailSent]); } // unsuspend $unsuspendReason = trim((string)($body['reason'] ?? '')); if ($unsuspendReason === '') { $unsuspendReason = 'Decyzja administracyjna po weryfikacji sytuacji.'; } try { $pdo->prepare("UPDATE users SET account_suspended = 0, suspension_reason = NULL, suspended_until = NULL, suspended_by = NULL, wallet_status = 'active' WHERE id = ?") ->execute([$userId]); } catch (Throwable $e) { try { $pdo->prepare("UPDATE users SET account_suspended = 0 WHERE id = ?")->execute([$userId]); } catch (Throwable $e2) { admin_json_error('Błąd aktualizacji bazy danych: ' . $e2->getMessage(), 500); } } try { $pdo->prepare("INSERT INTO user_account_history (user_id, action, reason, suspended_until, performed_by, performed_by_username) VALUES (?, 'unsuspend', ?, NULL, ?, ?)") ->execute([$userId, $unsuspendReason, $adminId, $adminUsername]); } catch (Throwable $e) { } $emailSent = false; $emailError = ''; try { $safeUsername = htmlspecialchars((string)$targetUser['username'], ENT_QUOTES, 'UTF-8'); $safeReason = nl2br(htmlspecialchars($unsuspendReason, ENT_QUOTES, 'UTF-8')); $safeSupportEmail = htmlspecialchars($supportEmail, ENT_QUOTES, 'UTF-8'); $safeSupportUrl = htmlspecialchars($supportUrl, ENT_QUOTES, 'UTF-8'); $emailBody = 'Konto aktywne

✓ Konto odwieszone

Twoje konto TOGETHERE jest ponownie aktywne

Cześć ' . $safeUsername . ',

Mamy dla Ciebie dobrą wiadomość — Twoje konto w serwisie TOGETHERE GAMES zostało odwieszone i jest w pełni aktywne.

Powód odwieszenia
' . $safeReason . '
Status konta
● Aktywne — dostęp w pełni przywrócony

Co zostało przywrócone?

  • Możliwość logowania na konto.
  • Pełny dostęp do funkcji serwisu (turnieje, mecze, profil).
  • Historia i dane konta zostały zachowane bez zmian.

Pamiętaj o zasadach

Prosimy o zapoznanie się z regulaminem serwisu i przestrzeganie zasad społeczności TOGETHERE GAMES. Kolejne naruszenie może skutkować stałym zablokowaniem konta.

Jeżeli masz pytania lub potrzebujesz pomocy:

📧 E-mail: ' . $safeSupportEmail . '
🌐 BOK online: ' . $safeSupportUrl . '

Witamy ponownie w serwisie i życzymy udanej gry! 🏆


Wiadomość wygenerowana automatycznie — prosimy nie odpowiadać bezpośrednio na ten e-mail.
TOGETHERE GAMES • togethere.cloud

'; $emailSent = (bool)sendEmailSMTP($targetEmail, 'Status konta - Wspolnie', $emailBody); if (!$emailSent) { // Awaryjnie wyślij przez mail() niezależnie od helpera SMTP. $headers = "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: text/html; charset=UTF-8\r\n"; $headers .= "From: TOGETHERE GAMES \r\n"; $headers .= "Reply-To: " . $supportEmail . "\r\n"; $emailSent = @mail($targetEmail, 'Status konta - Wspolnie', $emailBody, $headers); if (!$emailSent) { $emailError = 'Wysyłka nie powiodła się (SMTP + mail). Sprawdź smtp_debug.log i konfigurację serwera poczty.'; } } } catch (Throwable $e) { $emailError = $e->getMessage(); } $msg = 'Konto użytkownika zostało odwieszone.'; if (!$emailSent) { $msg .= ' ⚠️ Email NIE został wysłany: ' . $emailError; } admin_json_response(['success' => true, 'message' => $msg, 'email_sent' => $emailSent]);