"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:
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:
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]);