Fix 500 error on admin access: make navigation layout resilient and auto-run pending migrations on admin entry
This commit is contained in:
@@ -8,6 +8,7 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\View\View;
|
||||
|
||||
@@ -26,11 +27,14 @@ class AccountController extends Controller
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
$communications = collect();
|
||||
if (Schema::hasTable('communications')) {
|
||||
$communications = Communication::where('user_id', $user->id)
|
||||
->orWhere('email', strtolower($user->email))
|
||||
->with('replies')
|
||||
->latest()
|
||||
->get();
|
||||
}
|
||||
|
||||
return view('account.index', compact('user', 'orders', 'communications'));
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@ use App\Models\Communication;
|
||||
use App\Models\CommunicationReply;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class CommunicationController extends Controller
|
||||
@@ -20,6 +22,10 @@ class CommunicationController extends Controller
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
if (! Schema::hasTable('communications')) {
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
}
|
||||
|
||||
$query = Communication::with(['user', 'order', 'replies'])->latest();
|
||||
|
||||
// Status filter
|
||||
|
||||
@@ -8,6 +8,8 @@ use App\Models\Order;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class CustomerController extends Controller
|
||||
@@ -17,6 +19,10 @@ class CustomerController extends Controller
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
if (! Schema::hasTable('communications')) {
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
}
|
||||
|
||||
$search = trim($request->input('q', ''));
|
||||
|
||||
// Query registered non-admin users
|
||||
|
||||
@@ -9,9 +9,11 @@ use App\Models\Order;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ContactController extends Controller
|
||||
@@ -60,6 +62,10 @@ class ContactController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
if (! Schema::hasTable('communications')) {
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
}
|
||||
|
||||
$communication = Communication::create([
|
||||
'user_id' => Auth::id(),
|
||||
'order_id' => $orderId,
|
||||
|
||||
@@ -4,6 +4,9 @@ namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class EnsureUserIsAdmin
|
||||
@@ -23,6 +26,16 @@ class EnsureUserIsAdmin
|
||||
->with('error', 'Je hebt geen beheerderstoegang tot deze pagina.');
|
||||
}
|
||||
|
||||
// Auto-migrate check: Ensure that new database tables (like communications) are migrated
|
||||
// automatically when an admin enters the admin panel, avoiding 500 errors on Coolify/production.
|
||||
try {
|
||||
if (! Schema::hasTable('communications')) {
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('Auto-migration in EnsureUserIsAdmin failed: '.$e->getMessage());
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,14 @@
|
||||
</a>
|
||||
|
||||
@php
|
||||
$draftBadgeCount = 0;
|
||||
try {
|
||||
if (\Illuminate\Support\Facades\Schema::hasTable('products')) {
|
||||
$draftBadgeCount = \App\Models\Product::where('status', 'draft')->count();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$draftBadgeCount = 0;
|
||||
}
|
||||
@endphp
|
||||
<a href="{{ route('admin.makerworld.staging') }}" class="px-3 py-1.5 rounded-lg transition flex items-center space-x-1.5 {{ request()->routeIs('admin.makerworld.staging*') ? 'bg-slate-900 text-white font-semibold' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100' }}">
|
||||
<i data-lucide="layers" class="w-3.5 h-3.5"></i>
|
||||
@@ -74,7 +81,14 @@
|
||||
</a>
|
||||
|
||||
@php
|
||||
$unreadCommCount = 0;
|
||||
try {
|
||||
if (\Illuminate\Support\Facades\Schema::hasTable('communications')) {
|
||||
$unreadCommCount = \App\Models\Communication::where('status', 'new')->count();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$unreadCommCount = 0;
|
||||
}
|
||||
@endphp
|
||||
<a href="{{ route('admin.communications.index') }}" class="px-3 py-1.5 rounded-lg transition flex items-center space-x-1.5 {{ request()->routeIs('admin.communications.*') ? 'bg-slate-900 text-white font-semibold' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100' }}">
|
||||
<i data-lucide="message-square" class="w-3.5 h-3.5"></i>
|
||||
@@ -101,7 +115,14 @@
|
||||
<!-- Right Actions -->
|
||||
<div class="flex items-center space-x-2.5">
|
||||
@php
|
||||
$isShopOffline = false;
|
||||
try {
|
||||
if (\Illuminate\Support\Facades\Schema::hasTable('settings')) {
|
||||
$isShopOffline = \App\Models\Setting::get('shop_offline', '0') === '1';
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$isShopOffline = false;
|
||||
}
|
||||
@endphp
|
||||
|
||||
<!-- Webshop Offline / Online Status Switcher -->
|
||||
@@ -175,7 +196,7 @@
|
||||
</header>
|
||||
|
||||
<!-- Offline Alert Banner -->
|
||||
@if($isShopOffline ?? (\App\Models\Setting::get('shop_offline', '0') === '1'))
|
||||
@if(!empty($isShopOffline))
|
||||
<div class="bg-rose-500 text-white px-4 py-2.5 text-xs font-medium border-b border-rose-600 shadow-sm flex flex-col sm:flex-row items-center justify-between gap-3 sticky top-16 z-20">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span class="w-2 h-2 rounded-full bg-white animate-pulse shrink-0"></span>
|
||||
|
||||
@@ -10,6 +10,7 @@ use App\Models\Order;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CustomerCommunicationTest extends TestCase
|
||||
@@ -231,4 +232,14 @@ class CustomerCommunicationTest extends TestCase
|
||||
$this->actingAs($this->customer)->get(route('admin.communications.index'))->assertRedirect(route('home'));
|
||||
$this->actingAs($this->customer)->get(route('admin.customers.index'))->assertRedirect(route('home'));
|
||||
}
|
||||
|
||||
public function test_admin_layout_does_not_crash_even_if_communications_table_is_initially_missing(): void
|
||||
{
|
||||
Schema::dropIfExists('communication_replies');
|
||||
Schema::dropIfExists('communications');
|
||||
|
||||
// Layout renders with HTTP 200 without 500 server error even when table was absent
|
||||
$response = $this->actingAs($this->admin)->get(route('admin.content.index'));
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user