Part A: Fix duplicate Service creation on provisioning retry - All 4 provisioning services use Service::firstOrCreate() keyed on subscription_id+service_type to prevent duplicates on queue retries - HandleSubscriptionCreated sends notification before provisioning, no longer re-throws on failure - RetryProvisioningCommand simplified to reuse existing Service records Part B: Plans/Pricing page complete redesign - Service type tabs (VPS, Dedicated, Web Hosting, MySQL) - Billing cycle segmented toggle (monthly/quarterly/semi-annual/annual) - Feature icons per service type, Popular/Best Value badges - Stock indicators, effective monthly price calculations Part C: Admin service soft-delete/archive - Service model uses SoftDeletes trait - Admin can archive and restore services - Show archived toggle on services list - Migration adds deleted_at column Docs: Updated TASKS.md, CLAUDE.md, PROJECT_DEVELOPMENT.md, MEMORY.md - Phase 3 marked complete, test counts updated (252 passing) - SupportPal references replaced with standalone ticket system - Frontend design skill background rule added - Closed GitHub issues #3, #6, #7, #8, #9 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
69 lines
2.0 KiB
PHP
69 lines
2.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\AuditLog;
|
|
use App\Models\User;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class ImpersonationController extends Controller
|
|
{
|
|
public function start(Request $request, User $user): RedirectResponse
|
|
{
|
|
if ($user->isAdmin()) {
|
|
return redirect()
|
|
->back()
|
|
->with('error', 'Cannot impersonate admin users.');
|
|
}
|
|
|
|
AuditLog::query()->create([
|
|
'user_id' => $user->id,
|
|
'admin_id' => $request->user()->id,
|
|
'action' => 'impersonate_start',
|
|
'resource_type' => 'User',
|
|
'resource_id' => $user->id,
|
|
'ip_address' => $request->ip(),
|
|
'user_agent' => $request->userAgent(),
|
|
'changes' => [
|
|
'admin' => $request->user()->name,
|
|
'customer' => $user->name,
|
|
],
|
|
]);
|
|
|
|
$request->session()->put('impersonator_id', $request->user()->id);
|
|
|
|
Auth::login($user);
|
|
|
|
return redirect()->away('https://'.config('app.domains.account').'/dashboard')
|
|
->with('info', "You are now impersonating {$user->name}.")
|
|
->with('success', "Impersonation started. You are now viewing as {$user->name}.");
|
|
}
|
|
|
|
public function stop(Request $request): RedirectResponse
|
|
{
|
|
$impersonatorId = $request->session()->get('impersonator_id');
|
|
|
|
if (! $impersonatorId) {
|
|
return redirect()->back();
|
|
}
|
|
|
|
$admin = User::find($impersonatorId);
|
|
|
|
if (! $admin) {
|
|
return redirect()->back()->with('error', 'Original admin user not found.');
|
|
}
|
|
|
|
$request->session()->forget('impersonator_id');
|
|
|
|
Auth::login($admin);
|
|
|
|
return redirect('https://'.config('app.domains.admin').'/dashboard')
|
|
->with('success', 'Impersonation ended.');
|
|
}
|
|
}
|