Files
2026-11-05 21:21:27 +00:00

105 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/common.php';
api_require_method('GET', 'POST');
$staff = api_require_staff();
api_require_admin_or_permission($staff, 'manage_banlist');
$pdo = get_db();
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$entries = $pdo->query(
'SELECT b.*, s.name AS added_by_name FROM banlist b LEFT JOIN staff s ON s.id = b.created_by ORDER BY b.created_at DESC'
)->fetchAll();
api_json([
'items' => array_map(fn(array $b) => [
'id' => (int) $b['id'],
'matchType' => $b['match_type'],
'value' => $b['value'],
'reason' => $b['reason'],
'addedByName' => $b['added_by_name'],
'createdAt' => $b['created_at'],
], $entries),
]);
}
$body = api_request_body();
$action = $body['action'] ?? '';
/** Schließt alle offenen Tickets, die zur gerade gesperrten E-Mail/Domain passen. */
function api_close_banned_tickets(PDO $pdo, string $matchType, string $value): void
{
$col = $matchType === 'email' ? 'requester_email' : sql_email_domain('requester_email');
$before = $pdo->prepare("SELECT id,status FROM tickets WHERE $col=? AND status NOT IN ('closed')");
$before->execute([$value]);
$rows = $before->fetchAll();
$pdo->prepare("UPDATE tickets SET status='closed',resolution_code='spam',resolution_note='Im Rahmen einer Sperre geschlossen',closed_at=?,updated_at=? WHERE $col=? AND status NOT IN ('closed')")
->execute([db_now(), db_now(), $value]);
ticket_sla_transition_rows($pdo, $rows, 'closed', (int) ($GLOBALS['__api_staff']['id'] ?? 0) ?: null);
}
if ($action === 'create') {
$matchType = ($body['matchType'] ?? 'email') === 'domain' ? 'domain' : 'email';
$value = trim(strtolower((string) ($body['value'] ?? '')));
$reason = trim((string) ($body['reason'] ?? ''));
if ($value === '') {
api_error(422, 'VALUE_REQUIRED', 'Bitte einen Wert angeben.');
}
if ($matchType === 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
api_error(422, 'INVALID_EMAIL', 'Ungültige E-Mail-Adresse.');
}
if ($matchType === 'domain' && (!str_contains($value, '.') || str_contains($value, '@'))) {
api_error(422, 'INVALID_DOMAIN', 'Nur Domain angeben, z.B. spam.de (ohne @).');
}
$chk = $pdo->prepare('SELECT id FROM banlist WHERE value=?');
$chk->execute([$value]);
if (!$chk->fetchColumn()) {
$pdo->prepare('INSERT INTO banlist (match_type,value,reason,created_by,created_at) VALUES (?,?,?,?,?)')
->execute([$matchType, $value, $reason ?: null, $staff['id'], db_now()]);
api_close_banned_tickets($pdo, $matchType, $value);
audit_log($staff['id'], "Sperrliste: {$value} hinzugefügt ({$matchType}, Mobile App)");
}
api_json(['ok' => true]);
}
if ($action === 'bulk_add') {
$raw = trim((string) ($body['values'] ?? ''));
$reason = trim((string) ($body['reason'] ?? ''));
$lines = array_filter(array_map('trim', preg_split('/[\r\n,;]+/', $raw)));
$added = 0;
$skipped = 0;
foreach ($lines as $val) {
$val = strtolower($val);
$type = str_contains($val, '@') ? 'email' : 'domain';
if ($type === 'email' && !filter_var($val, FILTER_VALIDATE_EMAIL)) { $skipped++; continue; }
if ($type === 'domain' && !str_contains($val, '.')) { $skipped++; continue; }
$chk = $pdo->prepare('SELECT id FROM banlist WHERE value=?');
$chk->execute([$val]);
if ($chk->fetchColumn()) { $skipped++; continue; }
$pdo->prepare('INSERT INTO banlist (match_type,value,reason,created_by,created_at) VALUES (?,?,?,?,?)')
->execute([$type, $val, $reason ?: null, $staff['id'], db_now()]);
api_close_banned_tickets($pdo, $type, $val);
$added++;
}
audit_log($staff['id'], "Sperrliste Massen-Import: {$added} hinzugefügt, {$skipped} übersprungen (Mobile App)");
api_json(['added' => $added, 'skipped' => $skipped]);
}
if ($action === 'delete') {
$id = (int) ($body['id'] ?? 0);
$val = $pdo->prepare('SELECT value FROM banlist WHERE id=?');
$val->execute([$id]);
$v = $val->fetchColumn();
if ($v === false) {
api_error(404, 'ENTRY_NOT_FOUND', 'Der Eintrag wurde nicht gefunden.');
}
$pdo->prepare('DELETE FROM banlist WHERE id=?')->execute([$id]);
audit_log($staff['id'], "Sperrliste: {$v} entfernt (Mobile App)");
api_json(['ok' => true]);
}
api_error(422, 'INVALID_ACTION', 'Unbekannte Aktion.');