Skip to content
Open
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
32 changes: 21 additions & 11 deletions app/Console/Commands/RemoveAppInstancesByEmail.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class RemoveAppInstancesByEmail extends Command
* @var string
*/
protected $signature = 'polydock:remove-instances-by-email
{email : The email address to search for}
{email : The email address or pattern to search for (supports % wildcards)}
{--dry-run : Show what would be removed without actually doing it}
{--force : Skip confirmation prompt}';

Expand All @@ -24,7 +24,7 @@ class RemoveAppInstancesByEmail extends Command
*
* @var string
*/
protected $description = 'Find all app instances with the given email address and set them to pending removal';
protected $description = 'Find all app instances with the given email address or pattern and set them to pending removal';

/**
* Execute the console command.
Expand All @@ -35,19 +35,28 @@ public function handle()
$isDryRun = $this->option('dry-run');
$force = $this->option('force');

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->error('Invalid email address provided.');
// Check if this is a pattern (contains %) or exact email
$isPattern = str_contains($email, '%');

if (!$isPattern && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->error('Invalid email address provided. Use % for wildcard patterns (e.g., %@example.com).');
return 1;
}

$this->info("Searching for app instances with email: {$email}");
$searchType = $isPattern ? 'pattern' : 'email';
$this->info("Searching for app instances with {$searchType}: {$email}");

// Find all app instances with the given email in their data
$instances = PolydockAppInstance::whereJsonContains('data->user-email', $email)->get();
// Find all app instances with the given email or pattern in their data
if ($isPattern) {
// Use raw SQL for pattern matching (compatible with MariaDB/MySQL)
$instances = PolydockAppInstance::whereRaw("JSON_UNQUOTE(JSON_EXTRACT(data, '$.\"user-email\"')) LIKE ?", [$email])->get();
Copy link

Copilot AI Oct 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The raw SQL query with user input could be vulnerable to SQL injection. Consider using a parameterized query builder method or additional input sanitization to ensure the email pattern is properly escaped.

Suggested change
$instances = PolydockAppInstance::whereRaw("JSON_UNQUOTE(JSON_EXTRACT(data, '$.\"user-email\"')) LIKE ?", [$email])->get();
$instances = PolydockAppInstance::where(
DB::raw('JSON_UNQUOTE(JSON_EXTRACT(data, \'$."user-email"\'))'),
'LIKE',
$email
)->get();

Copilot uses AI. Check for mistakes.
} else {
$instances = PolydockAppInstance::whereJsonContains('data->user-email', $email)->get();
}


if ($instances->isEmpty()) {
$this->info('No app instances found with the email address: ' . $email);
$this->info("No app instances found matching {$searchType}: {$email}");
return 0;
}

Expand All @@ -67,18 +76,19 @@ public function handle()
return 0;
}

$this->info("Found {$instances->count()} app instance(s) with email: {$email}");
$this->info("Found {$instances->count()} app instance(s) matching {$searchType}: {$email}");
$this->info("Removable instances: {$removableInstances->count()}");
$this->newLine();

// Display the removable instances
$headers = ['ID', 'Name', 'Status', 'Store App', 'Created At'];
$headers = ['ID', 'Name', 'Email', 'Status', 'Store App', 'Created At'];
$rows = [];

foreach ($removableInstances as $instance) {
$rows[] = [
$instance->id,
$instance->name ?: 'N/A',
$instance->getUserEmail() ?: 'N/A',
$instance->status->getLabel(),
$instance->storeApp->name ?? 'N/A',
$instance->created_at->format('Y-m-d H:i:s')
Expand Down Expand Up @@ -116,7 +126,7 @@ public function handle()

$instance->setStatus(
PolydockAppInstanceStatus::PENDING_PRE_REMOVE,
"Marked for removal by email: {$email}"
"Marked for removal by {$searchType}: {$email}"
);
$instance->save();

Expand Down