97 lines
3.1 KiB
PHP
97 lines
3.1 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Ui\Security;
|
|
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Attributes\Title;
|
|
use Livewire\Component;
|
|
|
|
#[Layout('layouts.dvx')]
|
|
#[Title('SSL/TLS · Mailwolt')]
|
|
class SslCertificatesTable extends Component
|
|
{
|
|
public array $certs = [];
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->certs = $this->loadCertificates();
|
|
}
|
|
|
|
public function refresh(): void
|
|
{
|
|
$this->certs = $this->loadCertificates();
|
|
$this->dispatch('toast', type: 'done', badge: 'SSL', title: 'Aktualisiert',
|
|
text: 'Zertifikatsliste wurde neu geladen.', duration: 3000);
|
|
}
|
|
|
|
public function renew(string $name): void
|
|
{
|
|
$safe = preg_replace('/[^a-z0-9._-]/i', '', $name);
|
|
if ($safe === '') return;
|
|
|
|
$out = (string) @shell_exec(
|
|
"sudo -n /usr/bin/certbot renew --cert-name {$safe} --force-renewal 2>&1"
|
|
);
|
|
|
|
$this->certs = $this->loadCertificates();
|
|
|
|
if (str_contains($out, 'Successfully renewed') || str_contains($out, 'success')) {
|
|
$this->dispatch('toast', type: 'done', badge: 'SSL',
|
|
title: 'Zertifikat erneuert', text: "Zertifikat <b>{$safe}</b> wurde erfolgreich erneuert.", duration: 5000);
|
|
} else {
|
|
$this->dispatch('toast', type: 'error', badge: 'SSL',
|
|
title: 'Fehler', text: nl2br(htmlspecialchars(substr($out, 0, 300))), duration: 0);
|
|
}
|
|
}
|
|
|
|
private function loadCertificates(): array
|
|
{
|
|
$out = (string) @shell_exec('sudo -n /usr/bin/certbot certificates 2>&1');
|
|
if (empty(trim($out))) return [['_error' => 'unavailable']];
|
|
if (str_contains($out, 'No certificates found')) return [];
|
|
|
|
$certs = [];
|
|
$blocks = preg_split('/\n(?=Certificate Name:)/m', $out);
|
|
|
|
foreach ($blocks as $block) {
|
|
if (!preg_match('/Certificate Name:\s*(.+)/i', $block, $nameM)) continue;
|
|
|
|
preg_match('/Domains:\s*(.+)/i', $block, $domainsM);
|
|
preg_match('/Expiry Date:\s*(.+)/i', $block, $expiryM);
|
|
preg_match('/Certificate Path:\s*(.+)/i', $block, $certM);
|
|
|
|
$expiryRaw = trim($expiryM[1] ?? '');
|
|
$daysLeft = null;
|
|
$expired = false;
|
|
|
|
if (preg_match('/VALID: (\d+) days/i', $expiryRaw, $dM)) {
|
|
$daysLeft = (int) $dM[1];
|
|
} elseif (preg_match('/INVALID/i', $expiryRaw)) {
|
|
$expired = true;
|
|
$daysLeft = 0;
|
|
}
|
|
|
|
$domainsRaw = trim($domainsM[1] ?? '');
|
|
$domains = $domainsRaw !== '' ? array_values(array_filter(explode(' ', $domainsRaw))) : [];
|
|
|
|
$certs[] = [
|
|
'name' => trim($nameM[1]),
|
|
'domains' => $domains,
|
|
'expiry' => $expiryRaw,
|
|
'days_left' => $daysLeft,
|
|
'expired' => $expired,
|
|
'cert_path' => trim($certM[1] ?? ''),
|
|
];
|
|
}
|
|
|
|
usort($certs, fn($a, $b) => ($a['days_left'] ?? 999) <=> ($b['days_left'] ?? 999));
|
|
|
|
return $certs;
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.ui.security.ssl-certificates-table');
|
|
}
|
|
}
|