Skip to content
This repository was archived by the owner on Aug 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/Actions/CheckServerFirewallAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function handle(string $ip, int $hostId): array
'error' => $e->getMessage(),
];
} finally {
if ($keyName) {
if ($keyName !== '' && $keyName !== '0') {
$this->firewallService->removeMultiplexingPath($keyName);
}
}
Expand Down
8 changes: 4 additions & 4 deletions app/Actions/WhmcsSynchro.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public function handle(?Command $command = null): void
}

// Set debug mode and specific user from command options
if ($command) {
if ($command instanceof Command) {
$this->debugMode = (bool) ($command->option('debug') ?? false);
$userOption = $command->option('user');
$this->specificUserEmail = is_string($userOption) ? $userOption : null;
Expand Down Expand Up @@ -123,7 +123,7 @@ public function handle(?Command $command = null): void

protected function output(?Command $command, string $message): void
{
if ($command) {
if ($command instanceof Command) {
$command->info($message);
}

Expand Down Expand Up @@ -272,7 +272,7 @@ protected function processClient(object $whmcsClient, ?Command $command): void

$user = $this->findOrCreateUser($whmcsClient, $command);

if (! $user) {
if (! $user instanceof User) {
$this->debugOutput($command, "❌ Could not find or create user for: {$whmcsClient->email}");

return;
Expand Down Expand Up @@ -425,7 +425,7 @@ public function processActiveHostings(int $userId, ?Command $command = null): vo
}

$host = $this->findHostByWhmcsId((string) $whmcsHosting->server);
if (! $host) {
if (! $host instanceof Host) {
$this->debugOutput($command, "❌ No host found for WHMCS server ID: {$whmcsHosting->server}");
Log::warning("No host found for WHMCS server ID: {$whmcsHosting->server}");

Expand Down
2 changes: 1 addition & 1 deletion app/Console/Commands/AddHostKeyCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function handle(): void
// Si no se proporciona hostId, permitir seleccionar con prompts
if (! $hostId) {
$host = $this->selectHost();
if (! $host) {
if (! $host instanceof Host) {
error('No se seleccionó ningún host.');

return;
Expand Down
2 changes: 1 addition & 1 deletion app/Console/Commands/Develop/TestHostConnectionCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function handle(): int
info('=== DIAGNÓSTICO SSH REAL ===');

$host = $this->selectHost();
if (! $host) {
if (! $host instanceof Host) {
error('Host no encontrado');

return 1;
Expand Down
10 changes: 5 additions & 5 deletions app/Console/Commands/UserAuthorizeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private function createAuthorizedUser(): int
$parentUserId = search(
label: 'Select the parent user:',
options: function (string $value) use ($parentUsers) {
if (strlen($value) === 0) {
if ($value === '') {
return $parentUsers->take(10)->mapWithKeys(fn ($user) => [
(string) $user->id => "$user->name ($user->email)",
])->toArray();
Expand Down Expand Up @@ -145,7 +145,7 @@ private function assignPermissions(): int
$userId = search(
label: 'Select the authorized user:',
options: function (string $value) use ($authorizedUsers) {
if (strlen($value) === 0) {
if ($value === '') {
return $authorizedUsers->take(10)->mapWithKeys(fn ($user) => [
(string) $user->id => "$user->name ($user->email) - Parent: {$user->parentUser->name}",
])->toArray();
Expand Down Expand Up @@ -365,7 +365,7 @@ private function revokePermissions(): int
$userId = search(
label: 'Select the authorized user:',
options: function (string $value) use ($authorizedUsers) {
if (strlen($value) === 0) {
if ($value === '') {
return $authorizedUsers->take(10)->mapWithKeys(fn ($user) => [
(string) $user->id => "{$user->name} ({$user->email}) - Parent: {$user->parentUser->name}",
])->toArray();
Expand Down Expand Up @@ -537,7 +537,7 @@ private function reassignUserToParent(): int
$userId = search(
label: 'Select the authorized user:',
options: function (string $value) use ($authorizedUsers) {
if (strlen($value) === 0) {
if ($value === '') {
return $authorizedUsers->take(10)->mapWithKeys(fn ($user) => [
(string) $user->id => "$user->name ($user->email) - Current Parent: {$user->parentUser->name}",
])->toArray();
Expand Down Expand Up @@ -593,7 +593,7 @@ private function reassignUserToParent(): int
$parentUserId = search(
label: 'Select the new parent user:',
options: function (string $value) use ($parentUsers) {
if (strlen($value) === 0) {
if ($value === '') {
return $parentUsers->take(10)->mapWithKeys(fn ($user) => [
(string) $user->id => "$user->name ($user->email)",
])->toArray();
Expand Down
2 changes: 1 addition & 1 deletion app/Console/Commands/UserCreateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ private function handleInteractive(): int
$this->info('📋 User Summary:');
$this->line(" Email: {$email}");
$this->line(" Name: {$firstName} {$lastName}");
if ($companyName) {
if ($companyName !== '' && $companyName !== '0') {
$this->line(" Company: {$companyName}");
}
$this->line(' Type: '.($isAdmin ? '👑 Administrator' : '👤 Normal User'));
Expand Down
4 changes: 2 additions & 2 deletions app/Jobs/ProcessHqWhitelistJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __construct(
public function handle(FirewallService $firewallService): void
{
$hqHost = $this->resolveHqHost();
if (! $hqHost) {
if (! $hqHost instanceof Host) {
Log::warning('HQ host not found, skipping HQ whitelist check');

return;
Expand Down Expand Up @@ -95,7 +95,7 @@ public function handle(FirewallService $firewallService): void
throw $e;
} finally {
// Best effort cleanup of temporary key file
if ($keyPath) {
if ($keyPath !== '' && $keyPath !== '0') {
try {
$fileName = basename($keyPath);
Storage::disk('ssh')->delete($fileName);
Expand Down
2 changes: 1 addition & 1 deletion app/Livewire/OtpLogin.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public function verifyOtp(): void
'oneTimePassword' => 'required|string|size:6',
]);

if (! $this->user) {
if (! $this->user instanceof User) {
throw ValidationException::withMessages([
'oneTimePassword' => 'Sesión expirada. Solicita un nuevo código.',
]);
Expand Down
8 changes: 3 additions & 5 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -327,11 +327,9 @@ public function hasAccessToHosting(int $hostingId): bool
}

// If this is a principal user (no parent), check ownership
if (! $this->parent_user_id) {
// Check if user owns the hosting
if (Hosting::where('id', $hostingId)->where('user_id', $this->id)->exists()) {
return true;
}
// Check if user owns the hosting
if (! $this->parent_user_id && Hosting::where('id', $hostingId)->where('user_id', $this->id)->exists()) {
return true;
}

// For all users (principal and authorized), check specific permissions
Expand Down
2 changes: 1 addition & 1 deletion app/Services/Firewall/DirectAdminFirewallAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public function analyze(string $ipAddress, mixed $session): FirewallAnalysisResu
// STEP 3: Check DirectAdmin BFM blacklist (ALWAYS - independent of CSF status)
if ($this->serviceChecks['da_bfm_check'] ?? false) {
$bfmResult = $this->checkAndRemoveFromBfmBlacklist($ipAddress, $sshKeyName);
if ($bfmResult) {
if ($bfmResult instanceof FirewallAnalysisResult) {
$logs['da_bfm'] = $bfmResult->getLogs()['da_bfm'] ?? '';
$results[] = $bfmResult;
$bfmBlocked = $bfmResult->isBlocked();
Expand Down
2 changes: 1 addition & 1 deletion app/Services/Firewall/V2/FirewallLogAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function analyzeDirectAdmin(string $ipAddress, Host $host): FirewallAnaly

// STEP 3: Análisis BFM independiente (siempre se ejecuta)
$bfmResult = $this->analyzeBfmBlacklist($ipAddress, $host, $session);
if ($bfmResult) {
if ($bfmResult instanceof FirewallAnalysisResult) {
$logs['da_bfm_check'] = $bfmResult->getLogs()['da_bfm'] ?? '';
$results[] = $bfmResult;
}
Expand Down
6 changes: 1 addition & 5 deletions app/Services/FirewallUnblocker.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,7 @@ private function hasCsfBlocks(array $logs): bool
}

// Check for CSF temporary blocks - any content means blocked
if (! empty($logs['csf_tempip'] ?? '')) {
return true;
}

return false;
return ! empty($logs['csf_tempip'] ?? '');
}

/**
Expand Down
6 changes: 2 additions & 4 deletions app/Services/PatternDetection/AnomalyDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,8 @@ public function detectAll(): array
$currentTraffic = $this->getCurrentTraffic();

// Check if anomaly detected
if ($this->isAnomaly($currentTraffic, $baseline)) {
if ($detection = $this->createAnomalyDetection($currentTraffic, $baseline)) {
$detections[] = $detection;
}
if ($this->isAnomaly($currentTraffic, $baseline) && $detection = $this->createAnomalyDetection($currentTraffic, $baseline)) {
$detections[] = $detection;
}

return $detections;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function detectAll(): array
->filter();

foreach ($recentEmailHashes as $emailHash) {
if ($detection = $this->detectForEmail($emailHash)) {
if (($detection = $this->detectForEmail($emailHash)) instanceof PatternDetection) {
$detections[] = $detection;
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/Services/PatternDetection/SubnetScanDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function detectAll(): array
->keys();

foreach ($recentSubnets as $subnetPrefix) {
if ($detection = $this->detectForSubnet($subnetPrefix)) {
if (($detection = $this->detectForSubnet($subnetPrefix)) instanceof PatternDetection) {
$detections[] = $detection;
}
}
Expand Down
12 changes: 5 additions & 7 deletions app/Services/SshConnectionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@ public function prepareMultiplexingPath(): void
{
$directoryPath = '/tmp/cm';

if (! File::exists($directoryPath)) {
if (! File::makeDirectory($directoryPath, 0755, true)) {
Log::error('Error creating SSH multiplexing directory');
throw new ConnectionFailedException(
'Could not create SSH multiplexing directory: '.$directoryPath
);
}
if (! File::exists($directoryPath) && ! File::makeDirectory($directoryPath, 0755, true)) {
Log::error('Error creating SSH multiplexing directory');
throw new ConnectionFailedException(
'Could not create SSH multiplexing directory: '.$directoryPath
);
}
}

Expand Down
25 changes: 25 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

declare(strict_types=1);

use Rector\CodeQuality\Rector\Identical\StrlenZeroToIdenticalEmptyStringRector;
use Rector\CodeQuality\Rector\If_\{CombineIfRector, ExplicitBoolCompareRector, ObjectExplicitBoolCompareRector, SimplifyIfReturnBoolRector};
use Rector\Config\RectorConfig;
use Rector\Php83\Rector\ClassConst\AddTypeToConstRector;
use Rector\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector;
Expand Down Expand Up @@ -66,6 +68,29 @@
// Wave 1 (AID-529), landed last: the only semantic rule here, since
// strict_types changes runtime type coercion rather than shape.
DeclareStrictTypesRector::class,
// Wave 3 (AID-531). ONLY the equivalence-safe cosmetics from
// LARAVEL_CODE_QUALITY + codeQuality level 50. The rest of that set
// is NOT mechanical and was split off by risk profile:
// - MakeModelAttributesAndScopesProtectedRector (27 scopes
// public→protected, public surface) → AID-540
// - CarbonToDateFacadeRector + NowFunc...ToTodayFunc (runtime class
// + temporal semantics) → AID-541
// - ApplyDefaultInsteadOfNullCoalesceRector (?? vs ?: — differs on
// false/0/'') → AID-542
// - DispatchToHelperFunctions / RedirectRouteToToRoute /
// CompactToVariables / ThrowWithPreviousException (equivalence
// must be shown per transform) → AID-543
// Each transform below was diff-verified equivalence-preserving; the
// ExplicitBoolCompare rewrites were confirmed to fire only on
// string-typed vars (Rector left the ?string option() path alone).
// NB: measure/apply waves with `rector --clear-cache` — the cache does
// not discriminate the rule set, so `composer refactor` after a local
// measuring session can under-apply (16 files measured, 3 applied).
ObjectExplicitBoolCompareRector::class,
ExplicitBoolCompareRector::class,
SimplifyIfReturnBoolRector::class,
StrlenZeroToIdenticalEmptyStringRector::class,
CombineIfRector::class,
])
->withSkip([
// Excluded by design decision (AID-528), armed BEFORE any wave enables
Expand Down