You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pixelfed/bootstrap/app.php

228 lines
8.6 KiB
PHTML

<?php
use App\Http\Middleware\AccountInterstitial;
use App\Http\Middleware\Admin;
use App\Http\Middleware\Api\Admin as ApiAdmin;
use App\Http\Middleware\FrameGuard;
use App\Http\Middleware\GrantFirstPartyToken;
use App\Http\Middleware\Localization;
use App\Http\Middleware\RedirectIfAuthenticated;
use App\Http\Middleware\RestrictedAccess;
use App\Services\PendingLoginService;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Auth\Middleware\Authenticate;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
use Illuminate\Auth\Middleware\Authorize;
use Illuminate\Auth\Middleware\RequirePassword;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
Upgrade to Laravel 13 - laravel/framework ^12.0 -> ^13.0 - spatie/laravel-backup ^9.2.9 -> ^10.0 (forced: 9.x pins illuminate/notifications ^12.40, incompatible with L13) - Drop psalm/plugin-laravel + vimeo/psalm (dev-only static analysis): the only version chain compatible with L13's testbench-core needs vimeo/psalm ^7.0.0-beta, which requires narrowing the project's declared PHP floor (composer platform.php is pinned to 8.3.0 to keep composer.lock installable on the oldest supported PHP patch; the psalm 7 betas require specific 8.3.16+/8.4.3+/8.5.0+ floors). Its CI workflow (.github/workflows/php-psalm.yml) was already disabled (`on: []`, "too many errors"). Larastan/PHPStan remains as the project's static analysis tool, unaffected. - Rename VerifyCsrfToken/ValidateCsrfToken -> PreventRequestForgery in bootstrap/app.php and config/sanctum.php (the L13 rename; old classes remain as deprecated aliases but new code should reference the new name), and validateCsrfTokens() -> preventRequestForgery() in the middleware config. Everything else (cache serializable_classes, cache/session/redis key prefixes, upsert() uniqueBy, JobAttempted/QueueBusy event properties, pagination view names, Manager::extend bindings, model-boot nested instantiation) was checked against the app's actual code and found to be either already handled, already using the new convention, or not applicable to any pattern in this codebase. All 715 tests pass (verified against a clean baseline with Redis available locally via Docker); Pint and Larastan (the project's configured `composer analyse` scope) are both clean.
2 weeks ago
use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
use Illuminate\Foundation\Http\Middleware\TrimStrings;
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\Middleware\HandleCors;
use Illuminate\Http\Middleware\SetCacheHeaders;
use Illuminate\Http\Middleware\TrustProxies;
3 weeks ago
use Illuminate\Http\Request;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Routing\Middleware\ValidateSignature;
use Illuminate\Session\Middleware\AuthenticateSession;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use Illuminate\Validation\ValidationException;
use Illuminate\View\Middleware\ShareErrorsFromSession;
use Laravel\Passport\Http\Middleware\CheckToken;
use Laravel\Passport\Http\Middleware\CheckTokenForAnyScope;
use Laravel\Passport\Http\Middleware\CreateFreshApiToken;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
using: function () {
Route::middleware('web')
->group(base_path('routes/web-admin.php'));
Route::middleware('web')
->group(base_path('routes/web-portfolio.php'));
Route::middleware('web')
->group(base_path('routes/web-api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
Route::middleware('api')
->group(base_path('routes/api.php'));
Route::middleware('api')
->group(base_path('routes/v2026.php'));
},
channels: __DIR__.'/../routes/channels.php',
commands: __DIR__.'/../routes/console.php',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->use([
HandleCors::class,
PreventRequestsDuringMaintenance::class,
ValidatePostSize::class,
TrustProxies::class,
TrimStrings::class,
ConvertEmptyStringsToNull::class,
]);
$middleware->group('web', [
EncryptCookies::class,
FrameGuard::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
AuthenticateSession::class,
ShareErrorsFromSession::class,
Upgrade to Laravel 13 - laravel/framework ^12.0 -> ^13.0 - spatie/laravel-backup ^9.2.9 -> ^10.0 (forced: 9.x pins illuminate/notifications ^12.40, incompatible with L13) - Drop psalm/plugin-laravel + vimeo/psalm (dev-only static analysis): the only version chain compatible with L13's testbench-core needs vimeo/psalm ^7.0.0-beta, which requires narrowing the project's declared PHP floor (composer platform.php is pinned to 8.3.0 to keep composer.lock installable on the oldest supported PHP patch; the psalm 7 betas require specific 8.3.16+/8.4.3+/8.5.0+ floors). Its CI workflow (.github/workflows/php-psalm.yml) was already disabled (`on: []`, "too many errors"). Larastan/PHPStan remains as the project's static analysis tool, unaffected. - Rename VerifyCsrfToken/ValidateCsrfToken -> PreventRequestForgery in bootstrap/app.php and config/sanctum.php (the L13 rename; old classes remain as deprecated aliases but new code should reference the new name), and validateCsrfTokens() -> preventRequestForgery() in the middleware config. Everything else (cache serializable_classes, cache/session/redis key prefixes, upsert() uniqueBy, JobAttempted/QueueBusy event properties, pagination view names, Manager::extend bindings, model-boot nested instantiation) was checked against the app's actual code and found to be either already handled, already using the new convention, or not applicable to any pattern in this codebase. All 715 tests pass (verified against a clean baseline with Redis available locally via Docker); Pint and Larastan (the project's configured `composer analyse` scope) are both clean.
2 weeks ago
PreventRequestForgery::class,
SubstituteBindings::class,
CreateFreshApiToken::class,
'restricted',
]);
$middleware->group('oauth-web', [
EncryptCookies::class,
FrameGuard::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
ShareErrorsFromSession::class,
Upgrade to Laravel 13 - laravel/framework ^12.0 -> ^13.0 - spatie/laravel-backup ^9.2.9 -> ^10.0 (forced: 9.x pins illuminate/notifications ^12.40, incompatible with L13) - Drop psalm/plugin-laravel + vimeo/psalm (dev-only static analysis): the only version chain compatible with L13's testbench-core needs vimeo/psalm ^7.0.0-beta, which requires narrowing the project's declared PHP floor (composer platform.php is pinned to 8.3.0 to keep composer.lock installable on the oldest supported PHP patch; the psalm 7 betas require specific 8.3.16+/8.4.3+/8.5.0+ floors). Its CI workflow (.github/workflows/php-psalm.yml) was already disabled (`on: []`, "too many errors"). Larastan/PHPStan remains as the project's static analysis tool, unaffected. - Rename VerifyCsrfToken/ValidateCsrfToken -> PreventRequestForgery in bootstrap/app.php and config/sanctum.php (the L13 rename; old classes remain as deprecated aliases but new code should reference the new name), and validateCsrfTokens() -> preventRequestForgery() in the middleware config. Everything else (cache serializable_classes, cache/session/redis key prefixes, upsert() uniqueBy, JobAttempted/QueueBusy event properties, pagination view names, Manager::extend bindings, model-boot nested instantiation) was checked against the app's actual code and found to be either already handled, already using the new convention, or not applicable to any pattern in this codebase. All 715 tests pass (verified against a clean baseline with Redis available locally via Docker); Pint and Larastan (the project's configured `composer analyse` scope) are both clean.
2 weeks ago
PreventRequestForgery::class,
SubstituteBindings::class,
CreateFreshApiToken::class,
]);
$middleware->group('api', [
EnsureFrontendRequestsAreStateful::class,
'throttle:api',
'bindings',
GrantFirstPartyToken::class,
]);
Upgrade to Laravel 13 - laravel/framework ^12.0 -> ^13.0 - spatie/laravel-backup ^9.2.9 -> ^10.0 (forced: 9.x pins illuminate/notifications ^12.40, incompatible with L13) - Drop psalm/plugin-laravel + vimeo/psalm (dev-only static analysis): the only version chain compatible with L13's testbench-core needs vimeo/psalm ^7.0.0-beta, which requires narrowing the project's declared PHP floor (composer platform.php is pinned to 8.3.0 to keep composer.lock installable on the oldest supported PHP patch; the psalm 7 betas require specific 8.3.16+/8.4.3+/8.5.0+ floors). Its CI workflow (.github/workflows/php-psalm.yml) was already disabled (`on: []`, "too many errors"). Larastan/PHPStan remains as the project's static analysis tool, unaffected. - Rename VerifyCsrfToken/ValidateCsrfToken -> PreventRequestForgery in bootstrap/app.php and config/sanctum.php (the L13 rename; old classes remain as deprecated aliases but new code should reference the new name), and validateCsrfTokens() -> preventRequestForgery() in the middleware config. Everything else (cache serializable_classes, cache/session/redis key prefixes, upsert() uniqueBy, JobAttempted/QueueBusy event properties, pagination view names, Manager::extend bindings, model-boot nested instantiation) was checked against the app's actual code and found to be either already handled, already using the new convention, or not applicable to any pattern in this codebase. All 715 tests pass (verified against a clean baseline with Redis available locally via Docker); Pint and Larastan (the project's configured `composer analyse` scope) are both clean.
2 weeks ago
$middleware->preventRequestForgery(except: [
'oauth/token',
]);
$middleware->alias([
'api.admin' => ApiAdmin::class,
'admin' => Admin::class,
'auth' => Authenticate::class,
'auth.basic' => AuthenticateWithBasicAuth::class,
'bindings' => SubstituteBindings::class,
'cache.headers' => SetCacheHeaders::class,
'can' => Authorize::class,
'dangerzone' => RequirePassword::class,
'localization' => Localization::class,
'guest' => RedirectIfAuthenticated::class,
'signed' => ValidateSignature::class,
'throttle' => ThrottleRequests::class,
'interstitial' => AccountInterstitial::class,
'scopes' => CheckToken::class,
'scope' => CheckTokenForAnyScope::class,
'restricted' => RestrictedAccess::class,
]);
})
->withSchedule(function (Schedule $schedule) {
require __DIR__.'/scheduledtasks.php';
})
->withExceptions(function (Exceptions $exceptions) {
3 weeks ago
$exceptions->shouldRenderJsonWhen(
fn (Request $request) => $request->is('api/*') || $request->expectsJson(),
);
$exceptions->dontReport([
OAuthServerException::class,
ConnectionException::class,
]);
$exceptions->dontFlash([
'password',
'password_confirmation',
]);
$exceptions->reportable(function (BadMethodCallException $e) {
return app()->environment() !== 'production';
});
$exceptions->reportable(function (ConnectionException $e) {
return app()->environment() !== 'production';
});
// A login-flow form submitted from a tab whose CSRF token is stale
// (the session was regenerated by a login or a pending step elsewhere)
// lands on wherever the session actually is instead of a 419.
//
// The handler rewrites TokenMismatchException into an HttpException(419)
// (keeping the original as the previous exception) in prepareException()
// before render callbacks run, so this must key on the rewritten type
// and identify the CSRF case via status code + previous exception.
// Returning null for anything else lets the JSON Throwable callback below
// continue to handle XHR/JSON login requests as a 419.
$exceptions->render(function (HttpException $e, Request $request) {
if ($e->getStatusCode() !== 419 || ! $e->getPrevious() instanceof TokenMismatchException) {
return null;
}
if ($request->wantsJson() || ! $request->is('login', 'login/*')) {
return null;
}
if (Auth::check()) {
return redirect('/i/web');
}
if ($step = PendingLoginService::step($request)) {
return redirect()->route('login', ['step' => $step]);
}
return redirect()->route('login')->withErrors([
'login' => __('Your sign-in session expired. Please sign in again.'),
]);
});
$exceptions->render(function (Throwable $e, $request) {
if ($request->wantsJson()) {
if ($e instanceof HttpResponseException) {
return $e->getResponse();
}
if ($e instanceof AuthenticationException) {
return response()->json(
['error' => $e->getMessage()],
401,
);
}
if ($e instanceof ValidationException) {
return response()->json([
'message' => $e->getMessage(),
'errors' => $e->validator->getMessageBag(),
], $e->status);
}
$isHttp = $e instanceof HttpExceptionInterface;
return response()->json(
['error' => $e->getMessage()],
$isHttp ? $e->getStatusCode() : 500,
$isHttp ? $e->getHeaders() : [],
);
}
});
})
->create();