CluPilotCloud/app/Support/PasswordPolicy.php

73 lines
2.3 KiB
PHP

<?php
namespace App\Support;
use Illuminate\Validation\Rules\Password;
/**
* Wie lang ein Passwort in dieser Installation sein muss — an einer Stelle.
*
* Vorher gab es die Regel dreimal, mit drei verschiedenen Antworten:
* `ResetPassword` verlangte fest `min:12`, `CreateAdmin` `Password::min(12)`,
* und alles über `PasswordValidationRules` bekam `Password::default()` — also
* Laravels acht. Derselbe Kunde brauchte beim Zurücksetzen zwölf Zeichen und
* bei der Registrierung acht, und einstellbar war nichts davon.
*
* Gemeldet wurde die Zwölf als „zu lang". Die eigentliche Auffälligkeit war,
* dass es die Regel dreimal gibt: drei Stellen, die dieselbe Frage
* verschieden beantworten, laufen auseinander — hier waren sie es schon.
*
* Geklemmt statt abgelehnt: der Wert kommt aus einem Formular im Adminbereich,
* und eine stillschweigend gespeicherte 1 wäre schlimmer als eine sichtbar auf
* 6 geklemmte Eingabe.
*/
final class PasswordPolicy
{
public const SETTING = 'security.password_min_length';
/**
* Die kürzeste Länge, die diese Installation zulässt.
*
* Sechs ist wenig. Es ist die ausdrückliche Vorgabe des Betreibers
* (31.7.2026, „6 ist mindestens"), und die Zahl steht direkt neben dem
* Feld, an dem sie sich erhöhen lässt.
*/
public const FLOOR = 6;
/** bcrypt schneidet jenseits von 72 Byte ohnehin ab; 128 ist reichlich Luft. */
public const CEILING = 128;
public const DEFAULT_LENGTH = 6;
public static function minLength(): int
{
$stored = Settings::get(self::SETTING);
return self::clamp(is_numeric($stored) ? (int) $stored : self::DEFAULT_LENGTH);
}
public static function set(int $length): void
{
Settings::set(self::SETTING, self::clamp($length));
}
/**
* Die Regeln OHNE `confirmed`.
*
* Die Bestätigung hängt am Formular, nicht an der Richtlinie: `CreateAdmin`
* fragt auf der Kommandozeile einmal, jedes Formular zweimal. Wer sie
* braucht, hängt sie an.
*
* @return array<int, mixed>
*/
public static function rules(): array
{
return ['required', 'string', Password::min(self::minLength())];
}
private static function clamp(int $length): int
{
return max(self::FLOOR, min(self::CEILING, $length));
}
}