124 lines
4.4 KiB
PHP
124 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace App\Providers;
|
|
|
|
use Illuminate\Cache\RateLimiting\Limit;
|
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Broadcast;
|
|
use Illuminate\Support\Facades\RateLimiter;
|
|
use Illuminate\Support\Facades\Route;
|
|
use Namu\WireChat\Models\Attachment as WireChatAttachment;
|
|
|
|
class RouteServiceProvider extends ServiceProvider
|
|
{
|
|
use \Mcamara\LaravelLocalization\Traits\LoadsTranslatedCachedRoutes;
|
|
|
|
/**
|
|
* The path to the "home" route for your application.
|
|
*
|
|
* This is used by Laravel authentication to redirect users after login.
|
|
*
|
|
* @var string
|
|
*/
|
|
|
|
public const HOME = '/main-page'; // Not used because of route localization
|
|
|
|
/**
|
|
* Get the localized home route.
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function localizedHome()
|
|
{
|
|
return \Mcamara\LaravelLocalization\Facades\LaravelLocalization::localizeURL(self::HOME);
|
|
}
|
|
|
|
/**
|
|
* The controller namespace for the application.
|
|
*
|
|
* When present, controller route declarations will automatically be prefixed with this namespace.
|
|
*
|
|
* @var string|null
|
|
*/
|
|
// protected $namespace = 'App\\Http\\Controllers';
|
|
|
|
/**
|
|
* Define your route model bindings, pattern filters, etc.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function boot()
|
|
{
|
|
$this->configureRateLimiting();
|
|
|
|
$this->routes(function () {
|
|
Route::prefix('api')
|
|
->middleware('api')
|
|
->namespace($this->namespace)
|
|
->group(base_path('routes/api.php'));
|
|
|
|
Route::middleware('web')
|
|
->namespace($this->namespace)
|
|
->group(function () {
|
|
require base_path('routes/web.php');
|
|
require base_path('routes/fortify.php'); // <-- Fortify routes, with some routes disabled as they are customized and therefore in web.php
|
|
require base_path('routes/test.php');
|
|
});
|
|
});
|
|
|
|
// Route parameter constraints:
|
|
Route::pattern('id', '[0-9]+');
|
|
|
|
// Explicit model binding for WireChat attachment (not in App\Models namespace)
|
|
Route::model('attachment', WireChatAttachment::class);
|
|
|
|
Broadcast::routes([
|
|
'middleware' => ['auth.any:admin,bank,organization,web'],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Configure the rate limiters for the application.
|
|
*
|
|
* Public so tests can register the limiters again on a limiter rebuilt
|
|
* over an in-memory cache (see PdfRateLimitTest).
|
|
*
|
|
* @return void
|
|
*/
|
|
public function configureRateLimiting()
|
|
{
|
|
RateLimiter::for('api', function (Request $request) {
|
|
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
|
|
});
|
|
|
|
// Public PDFs are rendered on every request and can take ~128 MB of
|
|
// PHP memory each. On 2026-10-07 one crawler fetched them ~11 times a
|
|
// second, the server ran out of memory and the kernel killed MariaDB.
|
|
// A person downloading flyers never gets near 30 a minute; the
|
|
// crawler ran at ~660.
|
|
RateLimiter::for('pdf', function (Request $request) {
|
|
return Limit::perMinute(30)->by($request->ip());
|
|
});
|
|
|
|
// Search runs an Elasticsearch query per request. Per user where
|
|
// logged in (it is behind login), so people sharing an IP - a
|
|
// community centre - do not share one allowance.
|
|
RateLimiter::for('search', function (Request $request) {
|
|
return Limit::perMinute(30)->by(optional($request->user())->id ?: $request->ip());
|
|
});
|
|
|
|
// Every Livewire interaction posts to livewire/update. On 2026-10-08
|
|
// one bot posted tampered payloads there for 9 hours, up to ~850 a
|
|
// minute. Chat (WireChat) is the busiest real use: up to ~280 a minute
|
|
// from one person with two browsers open. Logged-in people are counted
|
|
// per user, so people sharing an IP do not share one allowance; guests
|
|
// only see forms like login and registration and are counted per IP.
|
|
RateLimiter::for('livewire', function (Request $request) {
|
|
return $request->user()
|
|
? Limit::perMinute(500)->by('user:' . $request->user()->id)
|
|
: Limit::perMinute(120)->by('ip:' . $request->ip());
|
|
});
|
|
}
|
|
}
|