Upload via GUI (335 Dateien)

This commit is contained in:
2026-10-24 20:14:39 +00:00
parent b347bd8405
commit f189918dc4
8 changed files with 239 additions and 27 deletions
+16 -8
View File
@@ -44,8 +44,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$errors[] = $res['error'];
} else {
audit_log($staff['id'], ($res['updated'] ? 'Plugin aktualisiert: ' : 'Plugin installiert: ') . "{$res['slug']} {$res['version']} (SHA-256 {$res['hash']}" . ($res['signed'] ? ', signiert' : ', nicht signiert') . ')');
flash('success', ($res['updated'] ? 'Plugin aktualisiert' : 'Plugin installiert') . ": {$res['name']} {$res['version']} (" . ($res['signed'] ? 'Signatur geprüft' : 'nicht signiert') . '). Es ist noch nicht aktiv.'
. ($res['needs_reapproval'] ? ' Die neue Version fordert zusätzliche Berechtigungen an und wurde angehalten.' : ''));
flash('success', plugin_install_message($res, plugins_installed($pdo)[$res['slug']] ?? []));
redirect('/staff/plugins.php');
}
}
@@ -54,8 +53,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($action === 'catalog_install' && plugin_valid_slug($slug)) {
$res = plugin_catalog_install($pdo, $slug);
if ($res['ok']) {
audit_log($staff['id'], "Plugin aus dem Katalog installiert: {$res['slug']} {$res['version']} (SHA-256 {$res['hash']}" . ($res['signed'] ? ', signiert' : ', nicht signiert') . ')');
flash('success', "{$res['name']} {$res['version']} installiert (" . ($res['signed'] ? 'Signatur geprüft' : 'nicht signiert') . '). Es ist noch nicht aktiv.');
audit_log($staff['id'], ($res['updated'] ? 'Plugin aus dem Katalog aktualisiert: ' : 'Plugin aus dem Katalog installiert: ') . "{$res['slug']} {$res['version']} (SHA-256 {$res['hash']}" . ($res['signed'] ? ', signiert' : ', nicht signiert') . ')');
flash('success', plugin_install_message($res, plugins_installed($pdo)[$res['slug']] ?? []));
redirect('/staff/plugins.php');
}
$errors[] = $res['error'];
@@ -68,7 +67,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if (!$errors) {
$manifest = plugin_read_manifest(plugins_dir() . '/' . $slug)[0];
$approve = !empty($_POST['confirm_permissions']) && $manifest ? $manifest['permissions'] : null;
// Signierte Plugins aus dem Katalog des Herausgebers brauchen keine zusätzliche Bestätigung; manuell hochgeladene schon
$row = plugins_installed($pdo)[$slug] ?? [];
$fromCatalog = ($row['source'] ?? '') === 'catalog' && !empty($row['signature_ok']);
$approve = (!empty($_POST['confirm_permissions']) || $fromCatalog) && $manifest ? $manifest['permissions'] : null;
$res = plugin_set_active($pdo, $slug, $action === 'activate', $approve);
if ($res['ok']) {
audit_log($staff['id'], ($action === 'activate' ? 'Plugin aktiviert: ' : 'Plugin deaktiviert: ') . $slug);
@@ -96,7 +98,10 @@ foreach ($installed as $slug => $row) $manifests[$slug] = plugin_read_manifest(p
$disabled = plugins_globally_disabled();
$strict = plugin_strict_mode();
$official = plugin_official_configured();
$catalog = plugin_catalog_url() !== '' ? plugin_catalog_cached(isset($_GET['refresh'])) : null;
$catalog = plugin_catalog_url() !== '' ? plugin_catalog_cached(isset($_GET['refresh']), 60) : null;
// Katalogeinträge je Plugin (für die Vorschaubilder der installierten Plugins)
$catBySlug = [];
if ($catalog && !empty($catalog['ok'])) foreach ($catalog['plugins'] as $__c) $catBySlug[$__c['slug']] = $__c;
$hasKey = plugin_publisher_key() !== '';
$catalogHost = (string) (parse_url(plugin_catalog_url(), PHP_URL_HOST) ?: '');
@@ -121,6 +126,7 @@ require __DIR__ . '/_header.php';
<?php foreach ($installed as $slug => $p): $m = $manifests[$slug]; $perms = $m['permissions'] ?? []; ?>
<tr>
<td>
<div style="display:flex;gap:12px;align-items:flex-start"><?= catalog_thumb('plugin', $catBySlug[$slug] ?? ['slug' => $slug, 'name' => $p['name']]) ?><div style="min-width:0">
<strong><?= e($p['name']) ?></strong> <span class="muted" style="font-size:.78rem"><?= e($slug) ?></span>
<?php if ($m && $m['description'] !== ''): ?><div class="muted" style="font-size:.82rem"><?= e($m['description']) ?></div><?php endif; ?>
<?php if ($m && $m['author'] !== ''): ?><div class="muted" style="font-size:.78rem">von <?= e($m['author']) ?></div><?php endif; ?>
@@ -130,12 +136,14 @@ require __DIR__ . '/_header.php';
</details>
<?php elseif ($m): ?><div class="muted" style="font-size:.78rem">Fordert keine Berechtigungen an.</div><?php endif; ?>
<?php if (!$m): ?><div style="color:#dc2626;font-size:.82rem">plugin.json fehlt oder ist ungültig – das Plugin kann nicht geladen werden.</div><?php endif; ?>
</div></div>
</td>
<td><?= e($p['version']) ?></td>
<td>
<?php if ($p['is_active']): ?><span style="color:#15803d;font-weight:600">Aktiv</span>
<?php elseif ((int) $p['fail_count'] >= PLUGIN_FAIL_LIMIT): ?><span style="color:#dc2626;font-weight:600">Wegen Fehlern deaktiviert</span>
<?php else: ?><span class="muted">Inaktiv</span><?php endif; ?>
<?php if (!empty($p['last_error'])): ?><div style="color:#b45309;font-size:.74rem;margin-top:4px;max-width:260px;white-space:normal;word-break:break-word"><?= e(mb_strimwidth((string) $p['last_error'], 0, 300, '…')) ?></div><?php endif; ?>
</td>
<td style="font-size:.82rem">
<?php if (!empty($p['signature_ok'])): ?><span style="color:#15803d;font-weight:600">✓ Signiert</span>
@@ -148,7 +156,7 @@ require __DIR__ . '/_header.php';
<?php else: ?>
<form method="post" style="display:inline-block;text-align:left" onsubmit="return confirm('Plugin aktivieren? Vorher wird ein Backup erstellt und evtl. Datenbank-Änderungen des Plugins eingespielt.')">
<?= csrf_field() ?><input type="hidden" name="slug" value="<?= e($slug) ?>"><input type="hidden" name="action" value="activate">
<?php if ($perms): ?><label style="font-size:.76rem;display:block"><input type="checkbox" name="confirm_permissions" value="1" required> Berechtigungen bestätigen</label><?php endif; ?>
<?php if ($perms && !(($p['source'] ?? '') === 'catalog' && !empty($p['signature_ok']))): ?><label style="font-size:.76rem;display:block"><input type="checkbox" name="confirm_permissions" value="1" required> Berechtigungen bestätigen</label><?php endif; ?>
<button class="btn" type="submit" <?= $m ? '' : 'disabled' ?>>Aktivieren</button>
</form>
<?php endif; ?>
@@ -182,7 +190,7 @@ require __DIR__ . '/_header.php';
<?php foreach ($catalog['plugins'] as $c): $have = $installed[$c['slug']] ?? null; $newer = $have && version_compare($c['version'], $have['version'], '>'); ?>
<tr>
<td><div style="display:flex;gap:12px;align-items:flex-start"><?= catalog_thumb('plugin', $c) ?><div style="min-width:0">
<strong><?= e($c['name']) ?></strong> <span class="muted" style="font-size:.78rem"><?= e($c['slug']) ?></span>
<strong><?= e($c['name']) ?></strong> <?php if (!empty($c['language'])): ?><span title="Sprachpaket: nach der Aktivierung erscheint die Flagge zum Umschalten" style="background:#e8f1ff;color:#1d4ed8;border:1px solid #bcd3f7;border-radius:20px;padding:1px 9px;font-size:.72rem;font-weight:700">🌐 Sprache: <?= e($c['language']['name']) ?></span> <?php endif; ?><?php if (!empty($c['featured'])): ?><span title="Vom Herausgeber empfohlen" style="background:#fff4d6;color:#92600a;border:1px solid #f1d38a;border-radius:20px;padding:1px 9px;font-size:.72rem;font-weight:700">★ Empfohlen</span><?php endif; ?> <span class="muted" style="font-size:.78rem"><?= e($c['slug']) ?></span>
<div class="muted" style="font-size:.82rem"><?= e($c['description']) ?></div>
<?php if ($c['author'] !== ''): ?><div class="muted" style="font-size:.78rem">von <?= e($c['author']) ?></div><?php endif; ?>
<?php if ($c['permissions']): ?><div class="muted" style="font-size:.76rem">Fordert an: <?= e(implode(', ', array_map(fn($p) => $permLabels[$p] ?? $p, $c['permissions']))) ?></div><?php endif; ?>