160 lines
5.6 KiB
PHP
160 lines
5.6 KiB
PHP
<?php
|
||
|
||
namespace App\Jobs;
|
||
|
||
use App\Events\CertProvisionProgress;
|
||
use App\Models\SystemTask;
|
||
use Illuminate\Bus\Queueable;
|
||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||
use Illuminate\Support\Facades\Artisan;
|
||
use Illuminate\Foundation\Bus\Dispatchable;
|
||
use Illuminate\Queue\InteractsWithQueue;
|
||
use Illuminate\Queue\SerializesModels;
|
||
use Illuminate\Support\Facades\Cache;
|
||
|
||
class ProvisionCertJob implements ShouldQueue
|
||
{
|
||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||
|
||
public function __construct(
|
||
public string $domain,
|
||
public ?string $email,
|
||
public string $taskKey,
|
||
public bool $useLetsEncrypt // true => LE, false => self-signed
|
||
) {}
|
||
|
||
/** NEU: DB→Redis spiegeln (fehler-tolerant) */
|
||
private function syncCache(SystemTask $task, int $ttlMinutes = 30): void
|
||
{
|
||
try {
|
||
Cache::store('redis')->put($task->key, [
|
||
'type' => $task->type,
|
||
'status' => $task->status,
|
||
'message' => $task->message,
|
||
'payload' => $task->payload ?? ['domain' => $this->domain],
|
||
], now()->addMinutes($ttlMinutes));
|
||
} catch (\Throwable $e) {
|
||
// Redis down? Ignorieren – der Banner würde dann einfach nichts finden.
|
||
}
|
||
}
|
||
|
||
/** Einmalig alles machen: DB updaten, Cache spiegeln, Broadcast senden */
|
||
private function emit(SystemTask $task, string $status, string $message, ?string $mode = null, int $ttl = 30): void
|
||
{
|
||
$task->update(['status' => $status, 'message' => $message]);
|
||
$this->syncCache($task, $ttl);
|
||
|
||
// Live-Update an Frontend (Reverb/Echo)
|
||
broadcast(new CertProvisionProgress(
|
||
taskKey: $task->key,
|
||
status : $status, // queued|running|done|failed
|
||
message: $message,
|
||
mode : $mode // letsencrypt|self-signed
|
||
));
|
||
}
|
||
|
||
|
||
public function handle(): void
|
||
{
|
||
$task = SystemTask::where('key', $this->taskKey)->first();
|
||
if (!$task) return;
|
||
|
||
$mode = $this->useLetsEncrypt ? 'letsencrypt' : 'self-signed';
|
||
|
||
// running
|
||
$this->emit($task, 'running', 'Starte Zertifikat-Provisionierung…', $mode);
|
||
|
||
if ($this->useLetsEncrypt) {
|
||
$this->emit($task, 'running', 'Let’s Encrypt wird ausgeführt…', $mode);
|
||
|
||
$exit = Artisan::call('mailwolt:provision-cert', [
|
||
'domain' => $this->domain,
|
||
'--email' => $this->email ?? '',
|
||
]);
|
||
|
||
if ($exit !== 0) {
|
||
$out = trim(Artisan::output());
|
||
$this->emit(
|
||
$task,
|
||
'running',
|
||
'Let’s Encrypt fehlgeschlagen: '.($out ?: 'Unbekannter Fehler') . ' – Fallback auf Self-Signed…',
|
||
$mode
|
||
);
|
||
|
||
// Fallback → self-signed
|
||
$mode = 'self-signed';
|
||
$exit = Artisan::call('mailwolt:provision-cert', [
|
||
'domain' => $this->domain,
|
||
'--self-signed' => true,
|
||
]);
|
||
}
|
||
} else {
|
||
$this->emit($task, 'running', 'Self-Signed Zertifikat wird erstellt…', $mode);
|
||
$exit = Artisan::call('mailwolt:provision-cert', [
|
||
'domain' => $this->domain,
|
||
'--self-signed' => true,
|
||
]);
|
||
}
|
||
|
||
$out = trim(Artisan::output());
|
||
|
||
if ($exit === 0) {
|
||
$msg = 'Zertifikat erfolgreich erstellt. '.$out;
|
||
$this->emit($task, 'done', $msg, $mode, ttl: 10);
|
||
} else {
|
||
$msg = $out ?: 'Zertifikatserstellung fehlgeschlagen.';
|
||
$this->emit($task, 'failed', $msg, $mode, ttl: 30);
|
||
}
|
||
}
|
||
|
||
// public function handle(): void
|
||
// {
|
||
// $task = SystemTask::where('key', $this->taskKey)->first();
|
||
// if (!$task) return;
|
||
//
|
||
// // running
|
||
// $task->update(['status' => 'running', 'message' => 'Starte Zertifikat-Provisionierung…']);
|
||
// $this->syncCache($task);
|
||
//
|
||
// if ($this->useLetsEncrypt) {
|
||
// $task->update(['message' => 'Let’s Encrypt wird ausgeführt…']);
|
||
// $this->syncCache($task);
|
||
//
|
||
// $exit = Artisan::call('mailwolt:provision-cert', [
|
||
// 'domain' => $this->domain,
|
||
// '--email' => $this->email ?? '',
|
||
// ]);
|
||
//
|
||
// if ($exit !== 0) {
|
||
// $out = trim(Artisan::output());
|
||
// $task->update(['message' => 'LE fehlgeschlagen: '.($out ?: 'Unbekannter Fehler – Fallback auf Self-Signed…')]);
|
||
// $this->syncCache($task);
|
||
//
|
||
// // Fallback: Self-Signed
|
||
// $exit = Artisan::call('mailwolt:provision-cert', [
|
||
// 'domain' => $this->domain,
|
||
// '--self-signed' => true,
|
||
// ]);
|
||
// }
|
||
// } else {
|
||
// $task->update(['message' => 'Self-Signed wird erstellt…']);
|
||
// $this->syncCache($task);
|
||
//
|
||
// $exit = Artisan::call('mailwolt:provision-cert', [
|
||
// 'domain' => $this->domain,
|
||
// '--self-signed' => true,
|
||
// ]);
|
||
// }
|
||
//
|
||
// $out = trim(Artisan::output());
|
||
//
|
||
// if ($exit === 0) {
|
||
// $task->update(['status' => 'done', 'message' => 'Zertifikat aktiv. '.$out]);
|
||
// $this->syncCache($task, 10);
|
||
// } else {
|
||
// $task->update(['status' => 'failed', 'message' => $out ?: 'Zertifikatserstellung fehlgeschlagen.']);
|
||
// $this->syncCache($task, 30);
|
||
// }
|
||
// }
|
||
}
|