87 lines
2.7 KiB
PHP
87 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
/**
|
|
* Ein Hostname, den der Reverse Proxy für diese Installation bedienen soll.
|
|
*
|
|
* Die Zeile ist der Wunsch, nicht der Zustand. Ob der Name wirklich bedient
|
|
* wird und ob er ein Zertifikat hat, steht nicht hier — das wird gemessen, an
|
|
* dem, was ein Besucher tatsächlich bekommt (siehe CertificateInspector).
|
|
*/
|
|
class ProxyHost extends Model
|
|
{
|
|
protected $fillable = ['hostname', 'purpose', 'note', 'source'];
|
|
|
|
/**
|
|
* Aus der Umgebung abgeleitet — nicht von Hand angelegt, also auch nicht
|
|
* von Hand zu entfernen: beim nächsten Abgleich käme er wieder, und ein
|
|
* Knopf, der nichts bewirkt, ist schlimmer als keiner.
|
|
*/
|
|
public function isFromConfig(): bool
|
|
{
|
|
return $this->source === 'config';
|
|
}
|
|
|
|
/** Hat die Prüfung ein gültiges Zertifikat gefunden? */
|
|
public function hasCertificate(): bool
|
|
{
|
|
return $this->certificate_expires_at !== null && $this->certificate_error === null;
|
|
}
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'certificate_expires_at' => 'datetime',
|
|
'certificate_checked_at' => 'datetime',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Wofür der Name da ist — und damit, was er darf.
|
|
*
|
|
* `public` — Website, Portal, Status, Dateien. Vom offenen Internet
|
|
* erreichbar, Zertifikat über die HTTP-Prüfung.
|
|
* `console` — der Adminbereich. Er bekommt die Netzsperre und ist NICHT
|
|
* öffentlich; ein Zertifikat holt er trotzdem.
|
|
*
|
|
* Getrennt, weil ein Name mit dem falschen Zweck genau die Sorte Fehler
|
|
* ist, die niemand sieht: die Konsole öffentlich zu stellen sieht aus wie
|
|
* eine funktionierende Seite.
|
|
*/
|
|
public const PURPOSES = ['public', 'console'];
|
|
|
|
public function isConsole(): bool
|
|
{
|
|
return $this->purpose === 'console';
|
|
}
|
|
|
|
/** Tage bis zum Ablauf, oder null wenn nichts gemessen wurde. */
|
|
public function daysLeft(): ?int
|
|
{
|
|
if ($this->certificate_expires_at === null) {
|
|
return null;
|
|
}
|
|
|
|
// Aufgerundet auf ganze Tage und nie negativ dargestellt: „noch -3 Tage"
|
|
// ist keine Auskunft, „abgelaufen" ist eine.
|
|
return max(0, (int) now()->diffInDays($this->certificate_expires_at, false));
|
|
}
|
|
|
|
/**
|
|
* Läuft es bald ab?
|
|
*
|
|
* Dreißig Tage, weil Let's Encrypt bei neunzig Tagen Laufzeit nach dreißig
|
|
* verbleibenden längst hätte erneuern müssen. Was darunter steht, ist kein
|
|
* knappes Zertifikat mehr, sondern eine Erneuerung, die nicht stattfindet.
|
|
*/
|
|
public function isExpiringSoon(): bool
|
|
{
|
|
$days = $this->daysLeft();
|
|
|
|
return $days !== null && $days <= 30;
|
|
}
|
|
}
|