Initial commit
This commit is contained in:
184
app/Console/Commands/CleanupIpAddresses.php
Normal file
184
app/Console/Commands/CleanupIpAddresses.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Admin;
|
||||
use App\Models\Bank;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
|
||||
class CleanupIpAddresses extends Command
|
||||
{
|
||||
protected $signature = 'ip:cleanup {--dry-run : Show what would be cleaned without actually deleting}';
|
||||
protected $description;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->description = 'Anonymize IP addresses older than ' .
|
||||
timebank_config('ip_retention.retention_days') . ' days for GDPR compliance';
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$retentionDays = timebank_config('ip_retention.retention_days', 180);
|
||||
$cutoffDate = now()->subDays($retentionDays);
|
||||
$isDryRun = $this->option('dry-run');
|
||||
|
||||
$this->info('Starting IP address cleanup...');
|
||||
$this->info('Retention period: ' . $retentionDays . ' days');
|
||||
$this->info('Cutoff date: ' . $cutoffDate->toDateTimeString());
|
||||
|
||||
if ($isDryRun) {
|
||||
$this->warn('DRY RUN MODE - No changes will be made');
|
||||
}
|
||||
|
||||
$totalAnonymized = 0;
|
||||
|
||||
// Cleanup profile tables (users, organizations, banks, admins)
|
||||
$profileModels = [
|
||||
'users' => User::class,
|
||||
'organizations' => Organization::class,
|
||||
'banks' => Bank::class,
|
||||
'admins' => Admin::class,
|
||||
];
|
||||
|
||||
foreach ($profileModels as $tableName => $modelClass) {
|
||||
$count = $this->cleanupProfileTable($tableName, $modelClass, $cutoffDate, $isDryRun);
|
||||
$totalAnonymized += $count;
|
||||
}
|
||||
|
||||
// Cleanup activity log IP addresses
|
||||
$activityLogCount = $this->cleanupActivityLog($cutoffDate, $isDryRun);
|
||||
$totalAnonymized += $activityLogCount;
|
||||
|
||||
$action = $isDryRun ? 'Would anonymize' : 'Anonymized';
|
||||
$this->info("✓ {$action} {$totalAnonymized} IP address records in total.");
|
||||
|
||||
// Log the cleanup action
|
||||
if (!$isDryRun) {
|
||||
Log::info('IP address cleanup completed', [
|
||||
'retention_days' => $retentionDays,
|
||||
'cutoff_date' => $cutoffDate->toDateTimeString(),
|
||||
'total_anonymized' => $totalAnonymized,
|
||||
]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup IP addresses from profile tables
|
||||
*
|
||||
* @param string $tableName
|
||||
* @param string $modelClass
|
||||
* @param \Carbon\Carbon $cutoffDate
|
||||
* @param bool $isDryRun
|
||||
* @return int Number of records anonymized
|
||||
*/
|
||||
protected function cleanupProfileTable(string $tableName, string $modelClass, $cutoffDate, bool $isDryRun): int
|
||||
{
|
||||
$this->line("\nProcessing {$tableName} table...");
|
||||
|
||||
// Find profiles with last_login_ip that should be anonymized
|
||||
$query = $modelClass::whereNotNull('last_login_ip')
|
||||
->where('last_login_ip', '!=', '')
|
||||
->where(function ($q) use ($cutoffDate) {
|
||||
// Anonymize if last_login_at is older than cutoff date
|
||||
$q->where('last_login_at', '<', $cutoffDate)
|
||||
// Or if last_login_at is null (should not happen, but handle it)
|
||||
->orWhereNull('last_login_at');
|
||||
});
|
||||
|
||||
$count = $query->count();
|
||||
|
||||
if ($count === 0) {
|
||||
$this->line(" No IP addresses to anonymize in {$tableName}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($isDryRun) {
|
||||
$this->warn(" Would anonymize {$count} IP addresses in {$tableName}");
|
||||
|
||||
// Show some examples in dry run
|
||||
$examples = $query->take(3)->get(['id', 'name', 'last_login_ip', 'last_login_at']);
|
||||
if ($examples->isNotEmpty()) {
|
||||
$this->line(" Examples:");
|
||||
foreach ($examples as $example) {
|
||||
$loginDate = 'never';
|
||||
if ($example->last_login_at) {
|
||||
$loginDate = is_string($example->last_login_at)
|
||||
? $example->last_login_at
|
||||
: $example->last_login_at->toDateString();
|
||||
}
|
||||
$this->line(" - ID {$example->id} ({$example->name}): {$example->last_login_ip} (last login: {$loginDate})");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Anonymize by setting to null
|
||||
$updated = $query->update(['last_login_ip' => null]);
|
||||
$this->info(" ✓ Anonymized {$updated} IP addresses in {$tableName}");
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup IP addresses from activity log
|
||||
*
|
||||
* @param \Carbon\Carbon $cutoffDate
|
||||
* @param bool $isDryRun
|
||||
* @return int Number of records anonymized
|
||||
*/
|
||||
protected function cleanupActivityLog($cutoffDate, bool $isDryRun): int
|
||||
{
|
||||
$this->line("\nProcessing activity_log table...");
|
||||
|
||||
// Find activity logs with IP addresses older than cutoff date
|
||||
$query = Activity::whereNotNull('properties->ip')
|
||||
->where('created_at', '<', $cutoffDate);
|
||||
|
||||
$count = $query->count();
|
||||
|
||||
if ($count === 0) {
|
||||
$this->line(" No IP addresses to anonymize in activity_log");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($isDryRun) {
|
||||
$this->warn(" Would anonymize {$count} IP addresses in activity_log");
|
||||
|
||||
// Show some examples in dry run
|
||||
$examples = $query->take(3)->get(['id', 'log_name', 'properties', 'created_at']);
|
||||
if ($examples->isNotEmpty()) {
|
||||
$this->line(" Examples:");
|
||||
foreach ($examples as $example) {
|
||||
$ip = $example->properties['ip'] ?? 'N/A';
|
||||
$this->line(" - ID {$example->id} ({$example->log_name}): {$ip} (date: {$example->created_at->toDateString()})");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Anonymize by removing IP from properties JSON
|
||||
$activities = $query->get();
|
||||
$updated = 0;
|
||||
|
||||
foreach ($activities as $activity) {
|
||||
$properties = $activity->properties;
|
||||
if (isset($properties['ip'])) {
|
||||
unset($properties['ip']);
|
||||
$activity->properties = $properties;
|
||||
$activity->save();
|
||||
$updated++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info(" ✓ Anonymized {$updated} IP addresses in activity_log");
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user