configureRateLimiting(); Request::macro('pagination', function (int $defaultPageSize = 25): Pagination { /** @var \Illuminate\Http\Request $this */ return RequestHelper::pagination($this, $defaultPageSize); }); $this->routes(function (): void { Route::middleware([ self::ROUTE_GROUP_WEB, 'admin-secure', 'throttle:' . self::ROUTE_GROUP_WEB, ])->name('bo.')->prefix('bo') ->group(base_path('routes/web-bo.php')); Route::middleware([ self::ROUTE_GROUP_WEB, 'throttle:' . self::ROUTE_GROUP_WEB, ])->name('fo.') ->group(base_path('routes/web-fo.php')); Route::middleware([ self::ROUTE_GROUP_WEB_AJAX, 'throttle:' . self::ROUTE_GROUP_WEB_AJAX, ])->name('ajax.')->prefix('ajax') ->group(base_path('routes/ajax-fo.php')); Route::middleware([ self::ROUTE_GROUP_API, 'throttle:' . self::ROUTE_GROUP_API, ])->name('api.')->prefix('api') ->group(base_path('routes/api.php')); }); Route::model('inco', ProductInco::class); Route::model('faq', Faq::class); Route::model('tag', Tag::class); Route::model('slide', Slide::class); Route::model('range', Range::class); Route::model('discount', Discount::class); Route::model('product', Product::class); Route::bind( 'productWithPricingPublished', fn (string $value) => $this->resolvePublishedProductWithPricing($value) ); $this->cspReportRoute(); } /** * Configure the rate limiters for the application. */ protected function configureRateLimiting(): void { RateLimiter::for( self::ROUTE_GROUP_WEB_CREDENTIALS, fn (Request $request) => Limit::perMinute(self::RATE_LIMIT_PER_MINUTE_FOR_CREDENTIALS) ->by($request->user()?->id ?: resolve('clientIp')) ); RateLimiter::for( self::ROUTE_GROUP_WEB, fn (Request $request) => Limit::perMinute(self::RATE_LIMIT_PER_MINUTE_FOR_WEB) ->by($request->user()?->id ?: resolve('clientIp')) ); RateLimiter::for( self::ROUTE_GROUP_WEB_AJAX, fn (Request $request) => Limit::perMinute(self::RATE_LIMIT_PER_MINUTE_FOR_AJAX) ->by($request->user()?->id ?: resolve('clientIp')) ); RateLimiter::for( self::ROUTE_GROUP_API, fn (Request $request) => Limit::perMinute(self::RATE_LIMIT_PER_MINUTE_FOR_API) ->by($request->user()?->id ?: resolve('clientIp')) ); } private function resolvePublishedProductWithPricing(string $value): ProductWithPricingDto { $domainProductRepository = resolve(ProductRepository::class); $product = Product::query() ->where('slug', $value) ->published() ->firstOrFail(); if (Gate::denies('viewPublished', $product)) { throw new NotFoundHttpException(); } $product->load(['inco', 'validDiscount', 'products']); $domainProduct = $domainProductRepository->find($product->getId()); $pricing = $domainProduct?->pricing(); if (! $pricing) { throw new NotFoundHttpException(); } return new ProductWithPricingDto($product, $pricing); } /** * * Register CSP report URI * * Put this function inside RouteServiceProvider, * and call it in RouteServiceProvider::boot */ private function cspReportRoute(): void { // * CSP REPORT URI, Please add /csp-report to VerifyCsrfToken $except middleware Route::post('/csp-report', function (Request $request): void { $isCspRequest = in_array( request()->header('Content-Type'), [ 'application/reports+json', 'application/csp-report', ] ); abort_if(! $isCspRequest, 401); $cspReport = (function (array $data): array { // Format Reporting API moderne if (isset($data[0]['type']) && $data[0]['type'] === 'csp-violation') { return (array) ($data[0]['body'] ?? []); } // Format CSP classique if (isset($data['csp-report'])) { return (array) $data['csp-report']; } return []; })((array) $request->json()->all()); // * Filter array keys $cspReport = Collection::make([ 'document-uri' => Arr::string($cspReport, 'documentURL', Arr::string($cspReport, 'document-uri', 'unknown')), 'referrer' => Arr::string($cspReport, 'referrer', ''), 'blocked-uri' => Arr::string($cspReport, 'blockedURL', Arr::string($cspReport, 'blocked-uri', '')), 'effective-directive' => Arr::string($cspReport, 'effectiveDirective', Arr::string($cspReport, 'effective-directive', 'unknown')), 'original-policy' => Arr::string($cspReport, 'originalPolicy', Arr::string($cspReport, 'original-policy', 'unknown')), 'disposition' => Arr::string($cspReport, 'disposition', 'enforce'), 'status-code' => Arr::integer( $cspReport, 'statusCode', Arr::integer($cspReport, 'status-code', 200) ), 'line-number' => Arr::integer($cspReport, 'lineNumber'), 'column-number' => Arr::integer($cspReport, 'columnNumber'), 'source-file' => Arr::string($cspReport, 'sourceFile'), ]); Log::warning(sprintf( "CSP REPORT : \n %s", $cspReport->transform(fn ($value, $key) => "\t{$key} -> {$value}")->join("\n") )); })->middleware('throttle:5,2') ->withoutMiddleware(PreventRequestForgery::class) ->name('cspReportUri'); } }