6b688f72e0
Internal cron is now triggered by an axios request from the frontend so it can truly run in a separate request. Fixes #167
125 lines
3.9 KiB
PHP
125 lines
3.9 KiB
PHP
<?php
|
|
|
|
use Inertia\Inertia;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Route;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use App\Http\Controllers\InvoiceController;
|
|
use App\Http\Controllers\CustomerController;
|
|
use App\Http\Controllers\ProductController;
|
|
use App\Models\Setting;
|
|
|
|
Route::middleware('auth')->group(function () {
|
|
|
|
// Dashboard
|
|
Route::get('/', function () {
|
|
return Inertia::render('Dashboard');
|
|
})->name('home');
|
|
|
|
Route::get('dashboard', function () {
|
|
return Inertia::render('Dashboard');
|
|
})->name('dashboard');
|
|
|
|
// CRM
|
|
Route::get('crm', function () {
|
|
return Inertia::render('CRM');
|
|
})->name('crm');
|
|
|
|
// Offers
|
|
Route::get('offers', function () {
|
|
return Inertia::render('Offers');
|
|
})->name('offers');
|
|
|
|
// Customers
|
|
Route::get('customers', [CustomerController::class, 'show'])->name('customers');
|
|
|
|
// Leads
|
|
Route::get('leads', function () {
|
|
return Inertia::render('Leads');
|
|
})->name('leads');
|
|
|
|
// Achievements
|
|
Route::get('achievements', function () {
|
|
return Inertia::render('Achievements');
|
|
})->name('achievements');
|
|
|
|
// Invoices
|
|
Route::get('invoices', [InvoiceController::class, 'show'])->name('invoices');
|
|
Route::get('invoices?action=new', [InvoiceController::class, 'show'])->name('newInvoice');
|
|
Route::get('invoice/{id}', [InvoiceController::class, 'preview'])->name('invoicePreview');
|
|
Route::get('invoice/{id}/pdf', [InvoiceController::class, 'exportPdf'])->name('invoiceExportPdf');
|
|
Route::get('invoice/{id}/xml', [InvoiceController::class, 'exportXml'])->name('invoiceExportXml');
|
|
|
|
// Products
|
|
Route::get('products', [ProductController::class, 'show'])->name('products');
|
|
|
|
Route::get('timesheets', function () {
|
|
return Inertia::render('Timesheets');
|
|
})->name('timesheets');
|
|
|
|
// Procedural Documentation
|
|
Route::get('proceduralDocumentation', function () {
|
|
return Inertia::render('ProceduralDocumentation');
|
|
})->name('proceduralDocumentation');
|
|
});
|
|
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Web cron route
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Example: GET /webcron?token=SECRET or set header X-WEBCron-Token: SECRET
|
|
| Configure secret in .env as WEBCRON_SECRET (optional). If no secret is set,
|
|
| the route is open (not recommended in production).
|
|
|
|
|
*/
|
|
Route::get('/webcron', function (Request $request) {
|
|
|
|
// Return early of cron method is set to anything other then 'webcron' or 'request'
|
|
$method = \App\Models\Setting::where('key', 'app.cron_method')->value('value') ?? 'request';
|
|
if (!in_array($method, ['webcron', 'request'])) {
|
|
return response('Not Found', 404);
|
|
}
|
|
|
|
// TODO: Only allow requests from the same host or with the secret token
|
|
// $clientHost = ;
|
|
// $serverHost = ;
|
|
$sameHost = true;
|
|
|
|
$secret = env('WEBCRON_SECRET', null);
|
|
$token = null;
|
|
if ($secret) {
|
|
$token = $request->query('token') ?? $request->header('X-WEBCron-Token');
|
|
}
|
|
if (
|
|
!hash_equals((string)$secret, (string)$token) &&
|
|
!$sameHost
|
|
) {
|
|
return response('Forbidden', 403);
|
|
}
|
|
|
|
// Throttle to avoid abuse (server-side)
|
|
$cacheKey = 'caramel_webcron_last_run';
|
|
if (\Illuminate\Support\Facades\Cache::has($cacheKey)) {
|
|
return response('Throttled', 304);
|
|
}
|
|
Cache::put($cacheKey, true, 55);
|
|
|
|
// Run scheduler
|
|
try {
|
|
Log::info('Triggering scheduler via /webcron route');
|
|
$output = '';
|
|
Artisan::call('schedule:run');
|
|
return response('OK', 200);
|
|
} catch (\Throwable $e) {
|
|
Log::error('Error running scheduler: ' . $e->getMessage());
|
|
return response('Error', 500);
|
|
}
|
|
});
|
|
|
|
require __DIR__ . '/settings.php';
|
|
require __DIR__ . '/auth.php';
|