Quelltext des aktuellen Standes
<?php
$this->layout('layouts/main', [
'page_title' => $page_title,
'current_route' => $current_route,
'full_width' => true,
'extra_css' => ['/assets/css/ssl.css?v=' . filemtime(dirname(__DIR__, 2) . '/public/assets/css/ssl.css')],
'extra_js' => ['/assets/js/ssl.js?v=' . filemtime(dirname(__DIR__, 2) . '/public/assets/js/ssl.js')],
]);
$e = $entry;
$history = $history ?? [];
$users = $users ?? [];
$transports = $transports ?? ['tls'];
$canManage = $can_manage ?? false;
$view = $this;
$g = $e['grade'] ?? null;
$gCls = in_array($g, ['A', 'B', 'C', 'F'], true) ? $g : 'na';
$days = $e['cert_days_left'];
$transportLabel = ['tls' => 'TLS (direkt)', 'smtp' => 'SMTP STARTTLS', 'imap' => 'IMAP STARTTLS', 'pop3' => 'POP3 STARTTLS'];
// Sparkline: Verlauf chronologisch, Balkenhöhe ~ Restlaufzeit
$chrono = array_reverse($history);
$maxDays = 1;
foreach ($chrono as $h) { $maxDays = max($maxDays, (int)($h['days_left'] ?? 0)); }
$yesno = function ($v, string $okText, string $badText) use ($view): string {
if ($v === null) { return '<span class="ssl-muted">—</span>'; }
$ok = (int)$v === 1;
return '<span class="status-pill ' . ($ok ? 'status-pill--success' : 'status-pill--danger') . '">' . ($ok ? $okText : $badText) . '</span>';
};
?>
<div class="ssl-wrap">
<div class="content-header">
<div>
<h1><?= $view->e($e['label'] ?: $e['host']) ?></h1>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/"><?= $this->te('Home') ?></a></li>
<li class="breadcrumb-item"><a href="/ssl"><?= $this->te('SSL-Zertifikate') ?></a></li>
<li class="breadcrumb-item active"><?= $view->e($e['host']) ?></li>
</ol>
</div>
<div class="content-header-actions">
<button class="btn btn-default btn-sm ssl-check-btn" data-id="<?= (int)$e['id'] ?>" title="<?= $this->te('Jetzt prüfen') ?>"><?= $this->te('↻ Prüfen') ?></button>
<?php if ($canManage): ?>
<button class="btn btn-default btn-sm" type="button" onclick="document.getElementById('sslEditModal').classList.add('open')"><?= $this->te('Bearbeiten') ?></button>
<button class="btn btn-default btn-sm ssl-delete-btn" data-id="<?= (int)$e['id'] ?>" data-host="<?= $view->e($e['host']) ?>" data-redirect="/ssl"><?= $this->te('Entfernen') ?></button>
<?php endif; ?>
</div>
</div>
<div class="page-body">
<?php if (!empty($e['check_error'])): ?>
<div class="ssl-card" style="border-left:4px solid var(--red-600);">
<strong style="color:var(--red-700);"><?= $this->te('Letzte Prüfung fehlgeschlagen:') ?></strong>
<span><?= $view->e($e['check_error']) ?></span>
</div>
<?php endif; ?>
<div class="ssl-detail-grid">
<!-- Linke Spalte: Bewertung -->
<div>
<div class="ssl-card" style="text-align:center;">
<div class="ssl-grade-big ssl-grade-<?= $gCls ?>" style="margin:0 auto 0.75rem;"><?= $view->e($g ?: '–') ?></div>
<div style="font-size:0.8rem;color:var(--gray-500);"><?= $this->te('Gesamtbewertung') ?></div>
<?php if ($days !== null): ?>
<div style="margin-top:0.75rem;font-size:1.4rem;font-weight:700;<?= $days <= 30 ? 'color:var(--red-700);' : 'color:var(--gray-900);' ?>"><?= (int)$days ?> Tage</div>
<div style="font-size:0.8rem;color:var(--gray-500);">bis <?= $e['cert_valid_to'] ? date('d.m.Y', strtotime($e['cert_valid_to'])) : '—' ?></div>
<?php endif; ?>
</div>
<div class="ssl-card">
<h3><?= $this->te('Sicherheit') ?></h3>
<dl class="ssl-kv">
<dt><?= $this->te('Vertrauenskette') ?></dt><dd><?= $yesno($e['trust_valid'] ?? null, '✓ Vertrauenswürdig', '✗ Nicht vertrauenswürdig') ?>
<?php if (!empty($e['trust_error'])): ?><div class="ssl-host-sub"><?= $view->e($e['trust_error']) ?></div><?php endif; ?></dd>
<dt><?= $this->te('Hostname-Match') ?></dt><dd><?= $yesno($e['hostname_match'] ?? null, '✓ Passt', '✗ Mismatch') ?></dd>
<dt><?= $this->te('Selbstsigniert') ?></dt><dd><?= ($e['is_self_signed'] ?? null) === null ? '<span class="ssl-muted">—</span>' : ((int)$e['is_self_signed'] === 1 ? 'Ja' : 'Nein') ?></dd>
<dt><?= $this->te('TLS-Version') ?></dt><dd><?= $view->e($e['tls_version'] ?: '—') ?></dd>
<dt><?= $this->te('Cipher') ?></dt><dd style="word-break:break-all;"><?= $view->e($e['tls_cipher'] ?: '—') ?></dd>
</dl>
</div>
<div class="ssl-card">
<h3><?= $this->te('Verwaltung') ?></h3>
<dl class="ssl-kv">
<dt><?= $this->te('Owner') ?></dt><dd><?= $view->e($e['owner_name'] ?: '—') ?></dd>
<dt><?= $this->te('Tags') ?></dt><dd><?= $view->e($e['tags'] ?: '—') ?></dd>
<dt><?= $this->te('Warnschwelle') ?></dt><dd><?= $e['warn_days'] ? (int)$e['warn_days'] . ' Tage' : 'Standard (30/14/7/1)' ?></dd>
<dt><?= $this->te('Transport') ?></dt><dd><?= $view->e($transportLabel[$e['transport'] ?? 'tls'] ?? 'TLS') ?></dd>
<dt><?= $this->te('Angelegt von') ?></dt><dd><?= $view->e($e['creator_name'] ?: '—') ?></dd>
</dl>
</div>
</div>
<!-- Rechte Spalte: Zertifikat + Verlauf -->
<div>
<div class="ssl-card">
<h3><?= $this->te('Zertifikat') ?></h3>
<dl class="ssl-kv">
<dt><?= $this->te('Common Name') ?></dt><dd><?= $view->e($e['cert_cn'] ?: '—') ?><?= !empty($e['cert_is_wildcard']) ? ' <span class="status-pill status-pill--purple">Wildcard</span>' : '' ?></dd>
<dt><?= $this->te('Organisation') ?></dt><dd><?= $view->e($e['cert_org'] ?: '—') ?></dd>
<dt><?= $this->te('Aussteller') ?></dt><dd><?= $view->e($e['cert_issuer_cn'] ?: '—') ?><?= $e['cert_issuer_org'] ? ' <span class="ssl-host-sub">(' . $view->e($e['cert_issuer_org']) . ')</span>' : '' ?></dd>
<dt><?= $this->te('Gültig von – bis') ?></dt><dd><?= $e['cert_valid_from'] ? date('d.m.Y', strtotime($e['cert_valid_from'])) : '—' ?> – <?= $e['cert_valid_to'] ? date('d.m.Y', strtotime($e['cert_valid_to'])) : '—' ?></dd>
<dt><?= $this->te('Schlüssel') ?></dt><dd><?= $view->e($e['cert_key_type'] ?: '—') ?><?= $e['cert_key_bits'] ? ' · ' . (int)$e['cert_key_bits'] . ' bit' : '' ?></dd>
<dt><?= $this->te('Signatur') ?></dt><dd><?= $view->e($e['cert_sig_algo'] ?: '—') ?></dd>
<dt><?= $this->te('Seriennummer') ?></dt><dd style="word-break:break-all;font-family:ui-monospace,monospace;font-size:0.8rem;"><?= $view->e($e['cert_serial'] ?: '—') ?></dd>
<dt><?= $this->te('Chain-Tiefe') ?></dt><dd><?= $e['cert_chain_depth'] !== null ? (int)$e['cert_chain_depth'] : '—' ?></dd>
<?php if (!empty($e['cert_sans'])): ?>
<dt><?= $this->te('SANs') ?></dt><dd class="ssl-sans"><?= $view->e($e['cert_sans']) ?></dd>
<?php endif; ?>
<?php if (!empty($e['cert_ocsp_url'])): ?><dt><?= $this->t('OCSP') ?></dt><dd style="word-break:break-all;"><?= $view->e($e['cert_ocsp_url']) ?></dd><?php endif; ?>
<?php if (!empty($e['cert_crl_url'])): ?><dt>CRL</dt><dd style="word-break:break-all;"><?= $view->e($e['cert_crl_url']) ?></dd><?php endif; ?>
</dl>
</div>
<div class="ssl-card">
<h3><?= $this->t('Verlauf') ?> (<?= count($history) ?> Prüfungen)</h3>
<?php if (empty($history)): ?>
<p class="ssl-muted" style="font-size:0.85rem;"><?= $this->te('Noch keine Historie.') ?></p>
<?php else: ?>
<div class="ssl-spark">
<?php foreach ($chrono as $h):
$d = $h['days_left'];
if (!$h['ok'] || $d === null) { $cls = 'err'; $ht = 8; }
else {
$cls = (int)$d <= 14 ? 'crit' : ((int)$d <= 30 ? 'warn' : '');
$ht = max(4, (int)round(((int)$d / $maxDays) * 100));
}
?>
<div class="ssl-spark-bar <?= $cls ?>" style="height:<?= $ht ?>%;" title="<?= date('d.m.Y H:i', strtotime($h['checked_at'])) ?> · <?= $h['ok'] ? ((int)($h['days_left'] ?? 0) . ' Tage') : 'Fehler' ?>"></div>
<?php endforeach; ?>
</div>
<table class="ssl-hist-table" style="margin-top:0.75rem;">
<thead><tr><th scope="col"><?= $this->te('Zeitpunkt') ?></th><th scope="col"><?= $this->te('Status') ?></th><th scope="col"><?= $this->te('Tage') ?></th><th scope="col"><?= $this->te('Grade') ?></th><th scope="col"><?= $this->t('TLS') ?></th></tr></thead>
<tbody>
<?php foreach (array_slice($history, 0, 20) as $h): ?>
<tr>
<td><?= date('d.m.Y H:i', strtotime($h['checked_at'])) ?></td>
<td><?= $h['ok'] ? '<span class="status-pill status-pill--success">OK</span>' : '<span class="status-pill status-pill--danger" title="' . $view->e((string)$h['error']) . '">Fehler</span>' ?></td>
<td><?= $h['days_left'] !== null ? (int)$h['days_left'] : '—' ?></td>
<td><?= $view->e($h['grade'] ?: '—') ?></td>
<td><?= $view->e($h['tls_version'] ?: '—') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<?php if ($canManage): ?>
<!-- Bearbeiten-Modal -->
<div class="ssl-modal-overlay" id="sslEditModal">
<div class="ssl-modal">
<div class="ssl-modal-header">
<h2 class="ssl-modal-title"><?= $this->te('Eintrag bearbeiten') ?></h2>
<button aria-label="<?= $this->te('Schließen') ?>" class="ssl-modal-close" type="button" onclick="document.getElementById('sslEditModal').classList.remove('open')">×</button>
</div>
<div class="ssl-modal-body">
<form method="POST" action="/ssl/entries/<?= (int)$e['id'] ?>/update">
<input type="hidden" name="_csrf" value="<?= $view->e($this->csrf()) ?>">
<div class="ssl-field-row">
<div class="ssl-field"><label for="f-7f48-host"><?= $this->te('Host') ?></label><input id="f-7f48-host" type="text" name="host" value="<?= $view->e($e['host']) ?>" required></div>
<div class="ssl-field" style="flex:0 0 90px;"><label for="f-7f48-port"><?= $this->te('Port') ?></label><input id="f-7f48-port" type="number" name="port" value="<?= (int)$e['port'] ?>" min="1" max="65535"></div>
</div>
<div class="ssl-field-row">
<div class="ssl-field"><label for="f-7f48-label"><?= $this->te('Bezeichnung') ?></label><input id="f-7f48-label" type="text" name="label" value="<?= $view->e($e['label']) ?>"></div>
<div class="ssl-field">
<label for="f-7f48-transport"><?= $this->te('Transport') ?></label>
<select id="f-7f48-transport" name="transport">
<?php foreach ($transports as $tr): ?>
<option value="<?= $view->e($tr) ?>" <?= ($e['transport'] ?? 'tls') === $tr ? 'selected' : '' ?>><?= $view->e(strtoupper($tr)) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="ssl-field">
<label for="f-7f48-owner_user_id"><?= $this->te('Owner') ?></label>
<select id="f-7f48-owner_user_id" name="owner_user_id">
<option value=""><?= $this->te('— kein Owner —') ?></option>
<?php foreach ($users as $u): ?>
<option value="<?= (int)$u['id'] ?>" <?= (int)($e['owner_user_id'] ?? 0) === (int)$u['id'] ? 'selected' : '' ?>><?= $view->e($u['display_name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="ssl-field-row">
<div class="ssl-field"><label for="f-7f48-tags"><?= $this->te('Tags (Komma)') ?></label><input id="f-7f48-tags" type="text" name="tags" value="<?= $view->e($e['tags'] ?? '') ?>"></div>
<div class="ssl-field" style="flex:0 0 130px;"><label><?= $this->te('Warn-Tage') ?></label><input type="number" name="warn_days" value="<?= $e['warn_days'] ? (int)$e['warn_days'] : '' ?>" min="1" placeholder="<?= $this->te('Standard') ?>"></div>
</div>
<button type="submit" class="btn btn-primary"><?= $this->te('Speichern & neu prüfen') ?></button>
</form>
</div>
</div>
</div>
<?php endif; ?>