Fix 40+ codebase issues: security, performance, duplication, dead code, and routes

HIGH:
- Add missing import RadioSongRequestFormRequest (fixes crash on POST)
- Add Purify XSS sanitization for article full_story
- Fix duplicate radio API routes (/api/radio vs /api/radio/v2)
- Add try-catch guards in InstallationController for missing records

MEDIUM:
- Fix N+1: eager load comments.user in ArticleController::show()
- Fix GuestbookController authorization logic
- Remove dead doSetup() method and duplicate route
- Extract shared HasRadioDefaults trait (remove code duplication)
- Use named routes in ForceStaffTwoFactorMiddleware
- Fix WebsiteHelpCenterTicket::isOpen() (no permission leak)
- Enable  on WebsiteHelpCenterTicket (matches schema)
- Replace WebsiteTeam::all()->pluck() with direct pluck()
- Replace CatalogPage::all()->pluck() with direct pluck()
- Replace WebsiteBadge::all() with direct pluck()
- Add throttle middleware to guestbook store, logo-generator, radio embed

LOW:
- Remove unused imports
- Remove dead /inertia-test route
- Consolidate cache keys in RadioController
This commit is contained in:
root
2026-06-08 18:56:34 +02:00
parent 6eeb85fcf2
commit 4094f0fb14
19 changed files with 97 additions and 101 deletions
@@ -34,10 +34,14 @@ class InstallationController extends Controller
'installation_key' => ['required', 'string', 'max:255', new ValidateInstallationKeyRule],
]);
WebsiteInstallation::first()->update([
'step' => 1,
'user_ip' => $request->ip(),
]);
try {
WebsiteInstallation::firstOrFail()->update([
'step' => 1,
'user_ip' => $request->ip(),
]);
} catch (\Exception $e) {
return back()->withErrors(['message' => 'Installation record not found. Please restart.']);
}
return to_route('installation.show-step', 1);
}
@@ -55,25 +59,31 @@ class InstallationController extends Controller
{
$this->updateSettings($request);
WebsiteInstallation::first()->increment('step');
$installation = WebsiteInstallation::firstOrFail();
$installation->increment('step');
return to_route('installation.show-step', WebsiteInstallation::first()->step);
return to_route('installation.show-step', $installation->step);
}
public function previousStep(): RedirectResponse
{
WebsiteInstallation::first()->decrement('step');
$installation = WebsiteInstallation::firstOrFail();
$installation->decrement('step');
return to_route('installation.show-step', WebsiteInstallation::first()->step);
return to_route('installation.show-step', $installation->step);
}
public function restartInstallation(): RedirectResponse
{
WebsiteInstallation::first()->update([
'step' => 0,
'installation_key' => Str::uuid(),
'user_ip' => null,
]);
try {
WebsiteInstallation::firstOrFail()->update([
'step' => 0,
'installation_key' => Str::uuid(),
'user_ip' => null,
]);
} catch (\Exception $e) {
return to_route('installation.index');
}
WebsiteSetting::where('key', 'theme')->update([
'value' => 'atom',
@@ -87,9 +97,13 @@ class InstallationController extends Controller
Cache::forget('website_permissions');
Cache::forget('website_settings');
WebsiteInstallation::latest()->first()->update([
'completed' => true,
]);
try {
WebsiteInstallation::latest()->firstOrFail()->update([
'completed' => true,
]);
} catch (\Exception $e) {
return to_route('installation.index');
}
return to_route('welcome');
}