Feature: Domain Auto-fill, SSL-Skip, Dashboard SSL-Banner
- Wizard Schritt 2: leere Domain-Felder werden beim Tippen auto-gefüllt (wer nur eine Domain nutzt muss sie nur einmal eingeben) - Wizard Schritt 4: Checkbox "SSL jetzt überspringen" mit Hinweistext - Wizard Schritt 5: skip-Status wird pro Domain angezeigt - WizardDomains schreibt ssl_configured=0/1 in Settings - SettingsForm: setzt ssl_configured=1 nach erfolgreichem applyDomains - Dashboard: gelber Banner wenn ssl_configured != 1, Link zu Einstellungen Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main v1.1.148
parent
077a029ff4
commit
627ef668e5
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Models\Setting;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
class WizardDomains extends Command
|
class WizardDomains extends Command
|
||||||
|
|
@ -81,6 +82,7 @@ class WizardDomains extends Command
|
||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents(self::STATE_DIR . '/done', $allOk ? '1' : '0');
|
file_put_contents(self::STATE_DIR . '/done', $allOk ? '1' : '0');
|
||||||
|
Setting::set('ssl_configured', $allOk ? '1' : '0');
|
||||||
return self::SUCCESS;
|
return self::SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ class Wizard extends Component
|
||||||
public string $mail_domain = '';
|
public string $mail_domain = '';
|
||||||
public string $webmail_domain = '';
|
public string $webmail_domain = '';
|
||||||
|
|
||||||
|
// Schritt 4 — Option
|
||||||
|
public bool $skipSsl = false;
|
||||||
|
|
||||||
// Schritt 3 — Admin-Account
|
// Schritt 3 — Admin-Account
|
||||||
public string $admin_name = '';
|
public string $admin_name = '';
|
||||||
public string $admin_email = '';
|
public string $admin_email = '';
|
||||||
|
|
@ -52,6 +55,18 @@ class Wizard extends Component
|
||||||
$this->webmail_domain = Setting::get('webmail_domain', '');
|
$this->webmail_domain = Setting::get('webmail_domain', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function updatedUiDomain(): void { $this->fillEmptyDomains($this->ui_domain); }
|
||||||
|
public function updatedMailDomain(): void { $this->fillEmptyDomains($this->mail_domain); }
|
||||||
|
public function updatedWebmailDomain(): void { $this->fillEmptyDomains($this->webmail_domain); }
|
||||||
|
|
||||||
|
private function fillEmptyDomains(string $value): void
|
||||||
|
{
|
||||||
|
if ($value === '') return;
|
||||||
|
if ($this->ui_domain === '') $this->ui_domain = $value;
|
||||||
|
if ($this->mail_domain === '') $this->mail_domain = $value;
|
||||||
|
if ($this->webmail_domain === '') $this->webmail_domain = $value;
|
||||||
|
}
|
||||||
|
|
||||||
public function next(): void
|
public function next(): void
|
||||||
{
|
{
|
||||||
match ($this->step) {
|
match ($this->step) {
|
||||||
|
|
@ -133,7 +148,7 @@ class Wizard extends Component
|
||||||
file_put_contents(self::STATE_DIR . "/{$k}", 'pending');
|
file_put_contents(self::STATE_DIR . "/{$k}", 'pending');
|
||||||
}
|
}
|
||||||
|
|
||||||
$ssl = app()->isProduction() ? 1 : 0;
|
$ssl = (!$this->skipSsl && app()->isProduction()) ? 1 : 0;
|
||||||
$artisan = base_path('artisan');
|
$artisan = base_path('artisan');
|
||||||
$cmd = sprintf(
|
$cmd = sprintf(
|
||||||
'nohup php %s mailwolt:wizard-domains --ui=%s --mail=%s --webmail=%s --ssl=%d > /dev/null 2>&1 &',
|
'nohup php %s mailwolt:wizard-domains --ui=%s --mail=%s --webmail=%s --ssl=%d > /dev/null 2>&1 &',
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,10 @@ class Dashboard extends Component
|
||||||
|
|
||||||
$servicesActive = count(array_filter($services, fn($s) => $s['status'] === 'online'));
|
$servicesActive = count(array_filter($services, fn($s) => $s['status'] === 'online'));
|
||||||
|
|
||||||
|
$sslConfigured = SettingModel::get('ssl_configured', '1') === '1';
|
||||||
|
|
||||||
return view('livewire.ui.nx.dashboard', [
|
return view('livewire.ui.nx.dashboard', [
|
||||||
|
'sslConfigured' => $sslConfigured,
|
||||||
'domainCount' => Domain::where('is_system', false)->where('is_server', false)->count(),
|
'domainCount' => Domain::where('is_system', false)->where('is_server', false)->count(),
|
||||||
'mailboxCount' => MailUser::where('is_system', false)->where('is_active', true)->count(),
|
'mailboxCount' => MailUser::where('is_system', false)->where('is_active', true)->count(),
|
||||||
'servicesActive' => $servicesActive,
|
'servicesActive' => $servicesActive,
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@ class SettingsForm extends Component
|
||||||
\Illuminate\Support\Facades\Log::info('mailwolt-apply-domains', ['output' => $output]);
|
\Illuminate\Support\Facades\Log::info('mailwolt-apply-domains', ['output' => $output]);
|
||||||
|
|
||||||
if ($ok) {
|
if ($ok) {
|
||||||
|
Setting::set('ssl_configured', '1');
|
||||||
$this->dispatch('toast', type: 'done', badge: 'Nginx',
|
$this->dispatch('toast', type: 'done', badge: 'Nginx',
|
||||||
title: 'Nginx aktualisiert',
|
title: 'Nginx aktualisiert',
|
||||||
text: 'Nginx-Konfiguration wurde neu geladen.',
|
text: 'Nginx-Konfiguration wurde neu geladen.',
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,16 @@
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top:16px;padding:12px 14px;background:var(--mw-bg3);border-radius:8px;border:1px solid var(--mw-b2)">
|
||||||
|
<label class="mw-modal-check">
|
||||||
|
<input type="checkbox" wire:model="skipSsl">
|
||||||
|
<span class="mw-modal-check-label">SSL jetzt überspringen — später in den Einstellungen einrichten</span>
|
||||||
|
</label>
|
||||||
|
@if($skipSsl)
|
||||||
|
<div style="margin-top:8px;font-size:11.5px;color:#fbbf24;padding-left:23px">Nginx wird ohne SSL konfiguriert. Im Dashboard erscheint ein Hinweis bis SSL eingerichtet ist.</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- ── Schritt 5: Domain-Setup ── --}}
|
{{-- ── Schritt 5: Domain-Setup ── --}}
|
||||||
@elseif($step === 5)
|
@elseif($step === 5)
|
||||||
@if(!$setupDone)
|
@if(!$setupDone)
|
||||||
|
|
@ -170,7 +180,7 @@
|
||||||
'done' => ['icon' => '✓', 'color' => 'rgba(34,197,94,.9)', 'bg' => 'rgba(34,197,94,.07)', 'label' => 'Abgeschlossen'],
|
'done' => ['icon' => '✓', 'color' => 'rgba(34,197,94,.9)', 'bg' => 'rgba(34,197,94,.07)', 'label' => 'Abgeschlossen'],
|
||||||
'nodns' => ['icon' => '!', 'color' => '#fbbf24', 'bg' => 'rgba(251,191,36,.07)', 'label' => 'Kein DNS-Eintrag gefunden'],
|
'nodns' => ['icon' => '!', 'color' => '#fbbf24', 'bg' => 'rgba(251,191,36,.07)', 'label' => 'Kein DNS-Eintrag gefunden'],
|
||||||
'error' => ['icon' => '✗', 'color' => '#f87171', 'bg' => 'rgba(239,68,68,.07)', 'label' => 'Fehler bei Registrierung'],
|
'error' => ['icon' => '✗', 'color' => '#f87171', 'bg' => 'rgba(239,68,68,.07)', 'label' => 'Fehler bei Registrierung'],
|
||||||
'skip' => ['icon' => '–', 'color' => 'var(--mw-t5)', 'bg' => 'var(--mw-bg3)', 'label' => 'Übersprungen'],
|
'skip' => ['icon' => '–', 'color' => 'var(--mw-t4)', 'bg' => 'var(--mw-bg3)', 'label' => 'SSL übersprungen'],
|
||||||
];
|
];
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,20 @@
|
||||||
|
|
||||||
<div wire:poll.30s>
|
<div wire:poll.30s>
|
||||||
|
|
||||||
|
{{-- SSL-Banner --}}
|
||||||
|
@if(!$sslConfigured)
|
||||||
|
<div style="display:flex;align-items:center;gap:12px;padding:12px 16px;margin-bottom:16px;background:rgba(251,191,36,.07);border:1px solid rgba(251,191,36,.25);border-radius:10px">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" style="flex-shrink:0;color:#fbbf24"><path d="M8 1.5L14.5 13H1.5L8 1.5Z" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/><path d="M8 6v4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/><circle cx="8" cy="11.5" r=".8" fill="currentColor"/></svg>
|
||||||
|
<div style="flex:1">
|
||||||
|
<span style="font-size:13px;font-weight:600;color:#fbbf24">SSL noch nicht eingerichtet</span>
|
||||||
|
<span style="font-size:12px;color:rgba(251,191,36,.7);margin-left:8px">Domains laufen ohne HTTPS — Zertifikate in den Einstellungen beantragen.</span>
|
||||||
|
</div>
|
||||||
|
<a href="{{ route('ui.system.settings') }}" style="font-size:12px;padding:5px 12px;border-radius:6px;background:rgba(251,191,36,.15);border:1px solid rgba(251,191,36,.3);color:#fbbf24;text-decoration:none;white-space:nowrap">
|
||||||
|
Jetzt einrichten →
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
{{-- Hero Banner --}}
|
{{-- Hero Banner --}}
|
||||||
<div class="mw-hero">
|
<div class="mw-hero">
|
||||||
<div class="mw-hero-icon">
|
<div class="mw-hero-icon">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue