83 lines
2.0 KiB
PHP
83 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
class TwoFactorRecoveryCode extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $table = 'two_factor_recovery_codes';
|
|
|
|
protected $fillable = [
|
|
'user_id',
|
|
'code_hash',
|
|
'used_at',
|
|
];
|
|
|
|
protected $casts = [
|
|
'used_at' => '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;
|
|
}
|
|
|
|
}
|