Upload via GUI (364 Dateien)

This commit is contained in:
2026-11-01 11:16:05 +00:00
parent 4319ceec47
commit 323d49e13e
6 changed files with 83 additions and 6 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ RewriteRule ^ - [F,L]
# RewriteRule ^ - [F,L]
# Clickjacking-Schutz
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
# Schützt interne Verzeichnisse vor direktem Web-Zugriff.
+1 -1
View File
@@ -248,7 +248,7 @@ if ($action !== 'typing') {
if ($action === 'typing') {
if ($activeTicket && $activeTicket['status'] !== 'closed') {
$pdo->prepare('UPDATE tickets SET typing_customer_until = ? WHERE id = ?')
$pdo->prepare('UPDATE tickets SET typing_customer_until = ?, updated_at = updated_at WHERE id = ?')
->execute([date('Y-m-d H:i:s', time() + 6), $activeTicket['id']]);
}
chat_json(['ok' => true]);
@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
/**
* Prüft die Überwachung der Plugin-Webseite auf der Statusseite: Prüfadresse aus dem offiziellen Katalog, Standarddienst,
* automatische Erkennung am Namen und dass ohne offiziellen Katalog nichts angelegt wird.
*/
putenv('DESKHUB_TESTING=1');
putenv('DESKHUB_CATALOG_DEFAULTS=' . __DIR__ . '/fixtures/no-catalog.php');
putenv('DESKHUB_SQLITE_PATH=:memory:');
require_once dirname(__DIR__) . '/includes/bootstrap.php';
$failures = [];
$check = function (bool $ok, string $what) use (&$failures): void {
if (!$ok) $failures[] = $what;
};
$pdo = get_db();
$byName = fn(string $name) => $pdo->query("SELECT * FROM status_components WHERE name = " . $pdo->quote($name))->fetch(PDO::FETCH_ASSOC);
// Ohne offiziellen Katalog gibt es nichts zu prüfen
$check(status_plugin_site_url() === '', 'ohne Katalog keine Prüfadresse');
status_restore_core_components($pdo);
$check(!$byName('Plugin-Webseite'), 'ohne Katalog wird kein Dienst "Plugin-Webseite" angelegt');
// Mit offiziellem Katalog
$GLOBALS['deskhub_catalog_defaults'] = ['plugins_url' => 'https://plugins.example.test/seite/catalog.php?type=plugins', 'themes_url' => '', 'publisher_key' => 'x'];
$check(status_plugin_site_url() === 'https://plugins.example.test/seite/health.php', 'Prüfadresse liegt neben dem Katalog: ' . status_plugin_site_url());
$check(status_restore_core_components($pdo) >= 1, 'Standarddienste ergänzen den fehlenden Dienst');
$c = $byName('Plugin-Webseite');
$check((bool) $c && $c['monitor_type'] === 'plugin_site' && (int) ($c['is_enabled'] ?? 1) === 1, 'Dienst "Plugin-Webseite" ist angelegt und aktiv');
$t = status_component_monitor_target($pdo, $c);
$check($t && $t['type'] === 'plugin_site' && $t['target'] === 'https://plugins.example.test/seite/health.php', 'Prüfziel ist das health.php der Plugin-Webseite');
$check(status_restore_core_components($pdo) === 0, 'ein zweiter Durchlauf legt nichts doppelt an');
$check(isset(status_monitor_types()['plugin_site']) && status_set_component_monitor($pdo, (int) $c['id'], 'plugin_site', ''), 'Prüfart "Plugin-Webseite" lässt sich wählen');
// Automatische Erkennung am Namen (Dienst mit anderem Namen, Prüfart "auto")
$id = status_save_component($pdo, null, 'Pluginseite von DeskHub', '', 900, null);
$row = $pdo->query('SELECT * FROM status_components WHERE id = ' . (int) $id)->fetch(PDO::FETCH_ASSOC);
$t = status_component_monitor_target($pdo, $row);
$check($t && $t['type'] === 'plugin_site', 'Name mit "Plugin" und "seite" wird automatisch erkannt');
$id2 = status_save_component($pdo, null, 'Plugin-Hersteller', '', 910, null);
$row2 = $pdo->query('SELECT * FROM status_components WHERE id = ' . (int) $id2)->fetch(PDO::FETCH_ASSOC);
$check(status_component_monitor_target($pdo, $row2) === null, 'ein anderer Name mit "Plugin" wird nicht fälschlich geprüft');
// Intern: wird geprüft, steht aber nicht öffentlich
$check(status_has_internal($pdo), 'Spalte is_internal ist vorhanden');
$check((int) $byName('Plugin-Webseite')['is_internal'] === 1, 'Plugin-Webseite ist standardmäßig intern');
$cat = $pdo->query('SELECT name FROM status_categories WHERE id = ' . (int) $byName('Plugin-Webseite')['category_id'])->fetchColumn();
$check($cat === 'Server & Datenbank', 'Kategorie ist "Server & Datenbank", nicht "Webseite": ' . var_export($cat, true));
$pub = array_column(status_components($pdo, false, true), 'name');
$all = array_column(status_components($pdo), 'name');
$check(!in_array('Plugin-Webseite', $pub, true) && in_array('Plugin-Webseite', $all, true), 'öffentliche Liste ohne den internen Dienst, Mitarbeiterliste mit ihm');
$check(in_array('plugin_site', array_map(fn($c) => (status_component_monitor_target($pdo, $c)['type'] ?? ''), status_components($pdo)), true), 'interner Dienst wird weiter geprüft');
// Ausfall eines internen Dienstes ändert den öffentlichen Gesamtzustand nicht
status_set_component($pdo, (int) $byName('Plugin-Webseite')['id'], 'outage');
$check(status_overall($pdo)['key'] === 'operational', 'Ausfall eines internen Dienstes ändert den öffentlichen Gesamtzustand nicht: ' . status_overall($pdo)['key']);
$check(status_set_component_internal($pdo, (int) $byName('Plugin-Webseite')['id'], false) && in_array('Plugin-Webseite', array_column(status_components($pdo, false, true), 'name'), true), 'als öffentlich markiert erscheint er wieder');
$check(status_overall($pdo)['key'] === 'outage', 'öffentlich: der Ausfall zählt');
status_set_component_internal($pdo, (int) $byName('Plugin-Webseite')['id'], true);
status_set_component($pdo, (int) $byName('Plugin-Webseite')['id'], 'operational');
// Störung an einem internen Dienst erscheint nicht öffentlich
$inc = status_create_incident($pdo, 'Plugin-Webseite langsam', 'x', 'investigating', (int) $byName('Plugin-Webseite')['id'], null, null);
$check(!empty($inc['ok']) && count(status_incidents($pdo, 14)) === 0 && count(status_incidents($pdo, 14, false, true)) === 1, 'Störung an einem internen Dienst steht nicht öffentlich, Mitarbeiter sehen sie');
// Eine http-Adresse (ohne https) wird nicht als Prüfadresse verwendet
$GLOBALS['deskhub_catalog_defaults'] = ['plugins_url' => 'http://plugins.example.test/catalog.php', 'themes_url' => '', 'publisher_key' => 'x'];
$check(status_plugin_site_url() === '', 'nur https wird verwendet');
unset($GLOBALS['deskhub_catalog_defaults']);
if ($failures) {
fwrite(STDERR, "Fehlgeschlagen:\n - " . implode("\n - ", $failures) . "\n");
exit(1);
}
echo "Status plugin site checks passed.\n";
+2 -2
View File
@@ -216,10 +216,10 @@ try {
[$s] = $call('GET', '/staff/ticket_view.php?n=T-OPEN-5', null, null, [], $jarChef, ['Sec-Fetch-Mode: navigate']);
$check($s === 200 && (int) $assignee('T-OPEN-5') === $ids['Chef'], 'Auch im Browser: Öffnen weist das Ticket zu (HTTP ' . $s . ')');
// Ticketliste: Spalte mit dem Eingangsdatum
// Ticketliste: Spalte mit der letzten Aktivität (Eingang im Tooltip)
[$s, $list] = $call('GET', '/staff/tickets.php', null, null, [], $jarChef, ['Sec-Fetch-Mode: navigate']);
$list = is_string($list) ? $list : '';
$check($s === 200 && str_contains($list, '<th>Eingang</th>') && str_contains($list, date('d.m.Y ')), 'Ticketliste zeigt die Spalte „Eingang“ mit Datum und Uhrzeit (HTTP ' . $s . ', ' . strlen($list) . ' Zeichen, Tabelle: ' . (str_contains($list, '<table') ? 'ja' : 'nein') . ', leer: ' . (str_contains($list, 'Keine Tickets') ? 'ja' : 'nein') . ')');
$check($s === 200 && str_contains($list, '<th>Letzte Aktivität</th>') && str_contains($list, date('d.m.Y ')), 'Ticketliste zeigt die Spalte „Letzte Aktivität“ mit Datum und Uhrzeit (HTTP ' . $s . ', ' . strlen($list) . ' Zeichen, Tabelle: ' . (str_contains($list, '<table') ? 'ja' : 'nein') . ', leer: ' . (str_contains($list, 'Keine Tickets') ? 'ja' : 'nein') . ')');
@unlink($jarChef);
@unlink($jarOther);
@@ -132,7 +132,9 @@ $pdo->prepare('UPDATE staff SET is_on_vacation = 1, vacation_substitute_id = NUL
[$h] = vacation_apply_change($pdo, $ben, [0, null], [1, null], true);
$check($h === 0 && $owner($t6) === $ben, 'Ohne Vertretung bleibt alles beim Abwesenden');
// Das Plugin „Urlaub und Vertretung“ hat Vorrang
$pdo->exec('CREATE TABLE IF NOT EXISTS plugin_vertretung_absences (id INTEGER PRIMARY KEY AUTOINCREMENT, staff_id INTEGER, substitute_id INTEGER, start_date TEXT, end_date TEXT, note TEXT, status TEXT, created_by INTEGER, created_at TEXT)');
$pdo->exec($pdo->getAttribute(PDO::ATTR_DRIVER_NAME) === 'sqlite'
? 'CREATE TABLE IF NOT EXISTS plugin_vertretung_absences (id INTEGER PRIMARY KEY AUTOINCREMENT, staff_id INTEGER, substitute_id INTEGER, start_date TEXT, end_date TEXT, note TEXT, status TEXT, created_by INTEGER, created_at TEXT)'
: 'CREATE TABLE IF NOT EXISTS plugin_vertretung_absences (id INT AUTO_INCREMENT PRIMARY KEY, staff_id INT, substitute_id INT, start_date VARCHAR(20), end_date VARCHAR(20), note TEXT, status VARCHAR(20), created_by INT, created_at VARCHAR(20))');
$pdo->prepare("INSERT INTO plugin_vertretung_absences (staff_id, substitute_id, start_date, end_date, note, status, created_at) VALUES (?,?,?,?,?,?,?)")->execute([$ben, $anna, '2026-01-01', '2026-12-31', '', 'active', $now]);
$pdo->prepare('UPDATE staff SET is_on_vacation = 1, vacation_substitute_id = ? WHERE id = ?')->execute([$anna, $ben]);
[$h] = vacation_apply_change($pdo, $ben, [0, null], [1, $anna], true);
@@ -150,7 +150,7 @@ try {
'/staff/custom_lists.php' => 'Listen', '/staff/custom_lists.php?new=1' => 'Einträge',
'/staff/site_pages.php' => 'Seiten', '/staff/site_pages.php?new=1' => 'Seiteninformationen',
'/staff/business_hours.php' => 'Feiertage', '/staff/business_hours.php?tab=holidays' => 'Feiertage',
'/staff/update.php' => 'Datenbank aktualisieren', '/staff/plugins.php' => 'Plugin-Katalog', '/staff/login_log.php' => 'Anmelde-Wächter', '/staff/login_alert.php?t=abc' => 'ungültig, abgelaufen', '/staff/backup.php' => 'Vorhandene Backups', '/staff/security_check.php' => 'Sicherheitsprüfung', '/staff/import_osticket.php' => 'osTicket Import', '/staff/ticket_rules.php' => 'Ticket-Regeln', '/staff/ticket_rules.php?new=1' => 'Regelinformationen',
'/staff/update.php' => 'Datenbank aktualisieren', '/staff/plugins.php' => 'Plugin-Katalog', '/staff/login_log.php' => 'Anmelde-Wächter', '/staff/problems.php' => 'Neues Problem', '/staff/reports.php' => 'Jetzt zu tun', '/staff/reports.php?tab=activity' => 'Ticketaktivität', '/staff/reports.php?tab=analysis' => 'Statistiken', '/staff/problems.php?tab=create' => 'Neues Problem erfassen', '/staff/login_alert.php?t=abc' => 'ungültig, abgelaufen', '/staff/backup.php' => 'Vorhandene Backups', '/staff/security_check.php' => 'Sicherheitsprüfung', '/staff/import_osticket.php' => 'osTicket Import', '/staff/ticket_rules.php' => 'Ticket-Regeln', '/staff/ticket_rules.php?new=1' => 'Regelinformationen',
] as $path => $marker) {
$response = browser_request($port, 'GET', $path, $cookies);
assert_page($response, $marker);