'datetime', ]; // === Beziehungen === public function user() { return $this->belongsTo(User::class); } // === Logik === /** * Prüft, ob der eingegebene Code gültig ist (noch nicht benutzt & hash-match) */ public static function verifyAndConsume(int $userId, string $inputCode): bool { $codes = self::where('user_id', $userId) ->whereNull('used_at') ->get(); foreach ($codes as $code) { if (password_verify($inputCode, $code->code_hash)) { $code->update(['used_at' => now()]); return true; } } return false; } /** * Prüft, ob der Code für den Benutzer existiert (ohne ihn zu verbrauchen) */ public static function checkValid(int $userId, string $inputCode): bool { return self::where('user_id', $userId) ->whereNull('used_at') ->get() ->contains(fn($c) => password_verify($inputCode, $c->code_hash)); } /** * Generiert neue Recovery-Codes (löscht alte unbenutzte) */ public static function generateNewSet(int $userId, int $count = 10): array { self::where('user_id', $userId)->delete(); $plainCodes = []; for ($i = 0; $i < $count; $i++) { $plain = strtoupper(str()->random(10)); self::create([ 'user_id' => $userId, 'code_hash' => password_hash($plain, PASSWORD_DEFAULT), ]); $plainCodes[] = $plain; } return $plainCodes; } }