214 lines
7.1 KiB
PHP
214 lines
7.1 KiB
PHP
<?php
|
||
|
||
namespace App\Livewire\Setup;
|
||
|
||
use App\Jobs\ProvisionCertJob;
|
||
use App\Support\Setting;
|
||
use App\Models\SystemTask;
|
||
use App\Models\User;
|
||
use App\Support\EnvWriter;
|
||
use Illuminate\Support\Facades\Cache;
|
||
use Illuminate\Support\Facades\Hash;
|
||
use Illuminate\Support\Facades\Redis;
|
||
use Livewire\Attributes\Validate;
|
||
use Livewire\Component;
|
||
|
||
class Wizard extends Component
|
||
{
|
||
public int $step = 1;
|
||
|
||
// Step 1
|
||
#[Validate('required|string|min:3')]
|
||
public string $form_domain = '';
|
||
|
||
#[Validate('required|timezone')]
|
||
public string $form_timezone = 'UTC';
|
||
|
||
public bool $form_cert_force_https = true;
|
||
|
||
// Step 2
|
||
#[Validate('required|string|min:3')]
|
||
public string $form_admin_name = '';
|
||
|
||
#[Validate('required|email')]
|
||
public string $form_admin_email = '';
|
||
|
||
/** optional: wenn du Login auch über username erlauben willst */
|
||
public ?string $form_admin_username = null;
|
||
|
||
#[Validate('required|string|min:8|same:form_admin_password_confirmation')]
|
||
public string $form_admin_password = '';
|
||
|
||
public string $form_admin_password_confirmation = '';
|
||
|
||
// Step 3 (Zertifikat)
|
||
public bool $form_cert_create_now = false;
|
||
|
||
#[Validate('required_if:form_cert_create_now,true|email')]
|
||
public string $form_cert_email = '';
|
||
|
||
public function nextStep()
|
||
{
|
||
if ($this->step === 1) {
|
||
$this->validateOnly('form_domain');
|
||
$this->validateOnly('form_timezone');
|
||
} elseif ($this->step === 2) {
|
||
$this->validate([
|
||
'form_admin_name' => 'required|string|min:3',
|
||
'form_admin_email' => 'required|email',
|
||
'form_admin_password' => 'required|string|min:8|same:form_admin_password_confirmation',
|
||
]);
|
||
}
|
||
|
||
$this->step = min($this->step + 1, 3);
|
||
}
|
||
|
||
public function prevStep()
|
||
{
|
||
$this->step = max($this->step - 1, 1);
|
||
}
|
||
|
||
public function finish()
|
||
{
|
||
// Step 3 Validierung (nur wenn sofort erstellen)
|
||
if ($this->form_cert_create_now) {
|
||
$this->validateOnly('form_cert_email');
|
||
}
|
||
|
||
// 1) Settings persistieren
|
||
Setting::set('app.domain', $this->form_domain);
|
||
Setting::set('app.timezone', $this->form_timezone);
|
||
Setting::set('app.force_https', (bool)$this->form_cert_force_https);
|
||
|
||
// Optional: .env spiegeln, damit URLs/HMR etc. sofort passen
|
||
$scheme = $this->form_cert_force_https ? 'https' : 'http';
|
||
EnvWriter::set([
|
||
'APP_HOST' => $this->form_domain,
|
||
'APP_URL' => "{$scheme}://{$this->form_domain}",
|
||
'APP_TIMEZONE' => $this->form_timezone,
|
||
]);
|
||
|
||
// 2) Admin anlegen/aktualisieren
|
||
$user = User::query()
|
||
->where('email', $this->form_admin_email)
|
||
->when($this->form_admin_username, fn($q) => $q->orWhere('username', $this->form_admin_username)
|
||
)
|
||
->first();
|
||
|
||
if (!$user) {
|
||
$user = new User();
|
||
$user->email = $this->form_admin_email;
|
||
if ($this->form_admin_username) {
|
||
$user->username = $this->form_admin_username;
|
||
}
|
||
} else {
|
||
// vorhandene Email/Username harmonisieren
|
||
$user->email = $this->form_admin_email;
|
||
if ($this->form_admin_username) {
|
||
$user->username = $this->form_admin_username;
|
||
}
|
||
}
|
||
|
||
$user->name = $this->form_admin_name;
|
||
$user->is_admin = true;
|
||
$user->password = Hash::make($this->form_admin_password);
|
||
$user->must_change_pw = true;
|
||
$user->save();
|
||
|
||
// 3) Zertifikat jetzt ausstellen (optional)
|
||
$taskKey = 'issue-cert:' . $this->form_domain;
|
||
|
||
if ($this->form_cert_create_now) {
|
||
SystemTask::updateOrCreate(
|
||
['key' => $taskKey],
|
||
[
|
||
'type' => 'issue-cert',
|
||
'status' => 'queued',
|
||
'message' => 'Warte auf Ausführung…',
|
||
'payload' => [
|
||
'domain' => $this->form_domain,
|
||
'email' => $this->form_cert_email,
|
||
'mode' => 'letsencrypt'
|
||
],
|
||
]
|
||
);
|
||
|
||
Cache::store('redis')->put($taskKey, [
|
||
'type' => 'issue-cert',
|
||
'status' => 'queued',
|
||
'message' => 'Warte auf Ausführung…',
|
||
'payload' => [
|
||
'domain' => $this->form_domain,
|
||
'email' => $this->form_cert_create_now ? $this->form_cert_email : null,
|
||
'mode' => $this->form_cert_create_now ? 'letsencrypt' : 'self-signed',
|
||
],
|
||
], now()->addMinutes(30));
|
||
|
||
Redis::sadd('ui:toasts', $taskKey);
|
||
|
||
ProvisionCertJob::dispatch(
|
||
domain: $this->form_domain,
|
||
email: $this->form_cert_email,
|
||
taskKey: $taskKey,
|
||
useLetsEncrypt: true
|
||
);
|
||
session()->flash('task_key', $taskKey);
|
||
session()->flash('banner_ok', 'Let’s Encrypt wird gestartet…');
|
||
} else {
|
||
// automatisch self-signed
|
||
SystemTask::updateOrCreate(
|
||
['key' => $taskKey],
|
||
[
|
||
'type' => 'issue-cert',
|
||
'status' => 'queued',
|
||
'message' => 'Warte auf Ausführung…',
|
||
'payload' => [
|
||
'domain' => $this->form_domain,
|
||
'mode' => 'self-signed'
|
||
],
|
||
]
|
||
);
|
||
|
||
Cache::store('redis')->put($taskKey, [
|
||
'type' => 'issue-cert',
|
||
'status' => 'queued',
|
||
'message' => 'Warte auf Ausführung…',
|
||
'payload' => [
|
||
'domain' => $this->form_domain,
|
||
'email' => $this->form_cert_create_now ? $this->form_cert_email : null,
|
||
'mode' => $this->form_cert_create_now ? 'letsencrypt' : 'self-signed',
|
||
],
|
||
], now()->addMinutes(30));
|
||
|
||
Cache::store('redis')->put($taskKey, [
|
||
'type' => 'issue-cert',
|
||
'status' => 'queued',
|
||
'message' => 'Warte auf Ausführung…',
|
||
'payload' => [
|
||
'domain' => $this->form_domain,
|
||
'email' => $this->form_cert_create_now ? $this->form_cert_email : null,
|
||
'mode' => $this->form_cert_create_now ? 'letsencrypt' : 'self-signed',
|
||
],
|
||
], now()->addMinutes(30));
|
||
|
||
Redis::sadd('ui:toasts', $taskKey);
|
||
|
||
ProvisionCertJob::dispatch(
|
||
domain: $this->form_domain,
|
||
email: null,
|
||
taskKey: $taskKey,
|
||
useLetsEncrypt: false
|
||
);
|
||
session()->flash('task_key', $taskKey);
|
||
session()->flash('banner_ok', 'Self-Signed Zertifikat wird erstellt…');
|
||
}
|
||
|
||
return redirect()->route('dashboard');
|
||
}
|
||
|
||
public function render()
|
||
{
|
||
return view('livewire.setup.wizard');
|
||
}
|
||
}
|