lockForUpdate()->findOrFail($player->id); $this->assertPasswordManagedLocally($locked); if (! is_string($locked->password_hash) || ! Hash::check($currentPassword, $locked->password_hash)) { throw ValidationException::withMessages([ 'current_password' => ['current_password_invalid'], ]); } if (Hash::check($newPassword, $locked->password_hash)) { throw ValidationException::withMessages([ 'password' => ['new_password_must_differ'], ]); } return $this->persist($locked, $newPassword); }); } public function reset(Player $player, string $newPassword): Player { return DB::transaction(function () use ($player, $newPassword): Player { $locked = Player::query()->lockForUpdate()->findOrFail($player->id); $this->assertPasswordManagedLocally($locked); return $this->persist($locked, $newPassword); }); } private function assertPasswordManagedLocally(Player $player): void { if (! $player->isLotteryNative()) { throw ValidationException::withMessages([ 'password' => ['native_password_unavailable'], ]); } } private function persist(Player $player, string $newPassword): Player { $player->forceFill([ 'password_hash' => Hash::make($newPassword), 'native_token_version' => (int) $player->native_token_version + 1, 'login_failed_count' => 0, 'login_locked_until' => null, ])->save(); return $player->refresh(); } }