Updater-System (OpenNIT-Modell) im isolierten updater/-Ordner

Zieht Quellcode + DB-Migrationen über einen HTTP-Update-Proxy nach.
Vollständig isoliert: eigener Namespace Updater\, eigener Autoloader,
eigene Settings (updater/storage/updater-settings.json), eigenes
Migrations-System (_updater_migrations), eigener AuditLogger.

Komponenten (alle in updater/):
- UpdateManager: Version/.version, Maintenance, Progress, checkForUpdates,
  installUpdate (Staging + PROTECTED_PATHS + Migrationen + opcache + finally)
- MigrationRunner: MySQL-Tracking, string-/kommentar-bewusster SQL-Splitter,
  isIgnorableSqlError, 60s-Lockfile-Cache
- UpdateController + admin/update.php (dünner Entry-Shim), Inline-Admin-UI
  mit Channel-Selector, Update-Check, Progress-Bar, Migrations-Tab
- UpdaterFactory (zentraler Channel-Fallback), AuditLogger (audit_log)
- Templates: maintenance.html, update.php; routes.php (Doku)
- README.md mit vollständiger Rückbau-Anleitung

Einzige Bestandscode-Änderung: 4-Zeilen-Maintenance-Hook in index.php
(markiert mit "// Updater maintenance hook").

Proxy: update.loheide.eu/openvouchertool[-development]
This commit is contained in:
Claude 2026-06-05 18:51:51 +00:00
parent 3483da274f
commit 43149074c9
No known key found for this signature in database
14 changed files with 1374 additions and 0 deletions

42
updater/AuditLogger.php Normal file
View file

@ -0,0 +1,42 @@
<?php
namespace Updater;
/**
* Minimaler AuditLogger fuer den Updater.
*
* Das Projekt besitzt KEINE eigene AuditLogger-Klasse, aber eine vorhandene
* Tabelle `audit_log`. Dieser Logger schreibt dort hinein, ohne eine
* Projekt-Klasse zu erweitern. Faellt das Schreiben fehl (z.B. Tabelle fehlt),
* wird der Fehler still ignoriert Logging darf ein Update nie blockieren.
*
* Wird dem UpdateManager optional injiziert; ist er null, wird Logging
* komplett uebersprungen.
*/
class AuditLogger
{
/** @var \Database */
private $db;
public function __construct(\Database $db)
{
$this->db = $db;
}
public function log($action, $details = null, $userId = null)
{
try {
$this->db->query(
"INSERT INTO audit_log (user_id, action, entity_type, details, ip_address)
VALUES (?, ?, 'updater', ?, ?)",
[
$userId,
$action,
is_string($details) ? $details : json_encode($details, JSON_UNESCAPED_UNICODE),
$_SERVER['REMOTE_ADDR'] ?? null,
]
);
} catch (\Throwable $e) {
// Logging darf nie ein Update verhindern.
}
}
}