Initial commit
This commit is contained in:
219
app/Console/Commands/RestoreDeletedProfile.php
Normal file
219
app/Console/Commands/RestoreDeletedProfile.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Actions\Jetstream\RestoreProfile;
|
||||
use App\Models\Admin;
|
||||
use App\Models\Bank;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class RestoreDeletedProfile extends Command
|
||||
{
|
||||
protected $signature = 'profiles:restore
|
||||
{username? : The username of the profile to restore}
|
||||
{--list : List all deleted profiles within grace period}
|
||||
{--type= : Filter by profile type (user, organization, bank, admin)}';
|
||||
|
||||
protected $description = 'Restore a deleted profile within the grace period or list all restorable profiles';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
// If --list option is provided, show all deleted profiles
|
||||
if ($this->option('list')) {
|
||||
return $this->listDeletedProfiles();
|
||||
}
|
||||
|
||||
// Get username argument
|
||||
$username = $this->argument('username');
|
||||
|
||||
// If no username provided, ask for it
|
||||
if (!$username) {
|
||||
$username = $this->ask('Enter the username of the profile to restore');
|
||||
}
|
||||
|
||||
if (!$username) {
|
||||
$this->error('Username is required.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Search for the deleted profile
|
||||
$profile = $this->findDeletedProfile($username);
|
||||
|
||||
if (!$profile) {
|
||||
$this->error("No deleted profile found with username: {$username}");
|
||||
$this->info('Use --list option to see all restorable profiles.');
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Display profile information
|
||||
$profileType = class_basename(get_class($profile));
|
||||
$deletedAt = $profile->deleted_at;
|
||||
$gracePeriodDays = timebank_config('delete_profile.grace_period_days', 30);
|
||||
$expiresAt = $deletedAt->copy()->addDays($gracePeriodDays);
|
||||
|
||||
// Calculate remaining time more accurately
|
||||
if (now()->greaterThanOrEqualTo($expiresAt)) {
|
||||
$timeRemaining = 'EXPIRED';
|
||||
} else {
|
||||
$daysRemaining = now()->diffInDays($expiresAt, false);
|
||||
if ($daysRemaining > 0) {
|
||||
$timeRemaining = $daysRemaining . ' day' . ($daysRemaining > 1 ? 's' : '');
|
||||
} else {
|
||||
$hoursRemaining = now()->diffInHours($expiresAt, false);
|
||||
$timeRemaining = $hoursRemaining . ' hour' . ($hoursRemaining > 1 ? 's' : '');
|
||||
}
|
||||
}
|
||||
|
||||
$this->info("Profile found:");
|
||||
$this->table(
|
||||
['Field', 'Value'],
|
||||
[
|
||||
['Type', $profileType],
|
||||
['Username', $profile->name],
|
||||
['Full Name', $profile->full_name ?? 'N/A'],
|
||||
['Email', $profile->email],
|
||||
['Deleted At', $deletedAt->format('Y-m-d H:i:s')],
|
||||
['Grace Period Expires', $expiresAt->format('Y-m-d H:i:s')],
|
||||
['Days Remaining', $timeRemaining],
|
||||
]
|
||||
);
|
||||
|
||||
// Confirm restoration
|
||||
if (!$this->confirm('Do you want to restore this profile?')) {
|
||||
$this->info('Restoration cancelled.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Restore the profile
|
||||
$restoreAction = new RestoreProfile();
|
||||
$result = $restoreAction->restore($profile);
|
||||
|
||||
if ($result['status'] === 'success') {
|
||||
$this->info("✓ Profile '{$profile->name}' has been successfully restored!");
|
||||
Log::info("Profile restored via artisan command", [
|
||||
'profile_type' => get_class($profile),
|
||||
'profile_id' => $profile->id,
|
||||
'profile_name' => $profile->name,
|
||||
'restored_by' => 'CLI',
|
||||
]);
|
||||
return 0;
|
||||
} else {
|
||||
$this->error("✗ Failed to restore profile: {$result['message']}");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all deleted profiles within grace period
|
||||
*/
|
||||
protected function listDeletedProfiles()
|
||||
{
|
||||
$gracePeriodDays = timebank_config('delete_profile.grace_period_days', 30);
|
||||
$gracePeriodExpiry = now()->subDays($gracePeriodDays);
|
||||
|
||||
$profileTypes = [
|
||||
'User' => User::class,
|
||||
'Organization' => Organization::class,
|
||||
'Bank' => Bank::class,
|
||||
'Admin' => Admin::class,
|
||||
];
|
||||
|
||||
// Filter by type if provided
|
||||
$typeFilter = $this->option('type');
|
||||
if ($typeFilter) {
|
||||
$typeFilter = ucfirst(strtolower($typeFilter));
|
||||
if (!isset($profileTypes[$typeFilter])) {
|
||||
$this->error("Invalid profile type. Valid types: user, organization, bank, admin");
|
||||
return 1;
|
||||
}
|
||||
$profileTypes = [$typeFilter => $profileTypes[$typeFilter]];
|
||||
}
|
||||
|
||||
$allDeletedProfiles = [];
|
||||
|
||||
foreach ($profileTypes as $typeName => $modelClass) {
|
||||
// Find profiles that are deleted, within grace period, and not anonymized
|
||||
$profiles = $modelClass::whereNotNull('deleted_at')
|
||||
->where('deleted_at', '>', $gracePeriodExpiry)
|
||||
->where('email', 'not like', 'removed-%@remove.ed')
|
||||
->orderBy('deleted_at', 'desc')
|
||||
->get();
|
||||
|
||||
foreach ($profiles as $profile) {
|
||||
$expiresAt = $profile->deleted_at->copy()->addDays($gracePeriodDays);
|
||||
|
||||
// Calculate remaining time more accurately
|
||||
if (now()->greaterThanOrEqualTo($expiresAt)) {
|
||||
$timeRemaining = 'EXPIRED';
|
||||
} else {
|
||||
$daysRemaining = now()->diffInDays($expiresAt, false);
|
||||
if ($daysRemaining > 0) {
|
||||
$timeRemaining = $daysRemaining . 'd';
|
||||
} else {
|
||||
$hoursRemaining = now()->diffInHours($expiresAt, false);
|
||||
$timeRemaining = $hoursRemaining . 'h';
|
||||
}
|
||||
}
|
||||
|
||||
$allDeletedProfiles[] = [
|
||||
'Type' => $typeName,
|
||||
'Username' => $profile->name,
|
||||
'Full Name' => $profile->full_name ?? 'N/A',
|
||||
'Email' => $profile->email,
|
||||
'Deleted At' => $profile->deleted_at->format('Y-m-d H:i'),
|
||||
'Expires At' => $expiresAt->format('Y-m-d H:i'),
|
||||
'Time Left' => $timeRemaining,
|
||||
'Comment' => $profile->comment ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($allDeletedProfiles)) {
|
||||
$this->info('No deleted profiles found within the grace period.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->info("Deleted profiles within {$gracePeriodDays}-day grace period:");
|
||||
$this->table(
|
||||
['Type', 'Username', 'Full Name', 'Email', 'Deleted At', 'Expires At', 'Time Left', 'Comment'],
|
||||
$allDeletedProfiles
|
||||
);
|
||||
|
||||
$this->info("\nTo restore a profile, run: php artisan profiles:restore {username}");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a deleted profile by username across all profile types
|
||||
*/
|
||||
protected function findDeletedProfile($username)
|
||||
{
|
||||
$gracePeriodDays = timebank_config('delete_profile.grace_period_days', 30);
|
||||
$gracePeriodExpiry = now()->subDays($gracePeriodDays);
|
||||
|
||||
$profileTypes = [
|
||||
User::class,
|
||||
Organization::class,
|
||||
Bank::class,
|
||||
Admin::class,
|
||||
];
|
||||
|
||||
foreach ($profileTypes as $modelClass) {
|
||||
$profile = $modelClass::whereNotNull('deleted_at')
|
||||
->where('deleted_at', '>', $gracePeriodExpiry)
|
||||
->where('email', 'not like', 'removed-%@remove.ed')
|
||||
->where('name', $username)
|
||||
->first();
|
||||
|
||||
if ($profile) {
|
||||
return $profile;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user