From 8c83e1e57c2571cc5189c7173b9150fe42559fad Mon Sep 17 00:00:00 2001 From: Tofandel Date: Thu, 13 Jun 2024 12:15:29 +0200 Subject: [PATCH 1/3] Improve provider --- config/twill.php | 2 +- phpunit-legacy.xml | 6 +- phpunit.xml | 6 +- src/Exceptions/Handler.php | 45 +----- src/Http/Controllers/Admin/Controller.php | 3 - src/Http/Controllers/Front/Controller.php | 4 - src/TwillRoutes.php | 10 ++ src/TwillServiceProvider.php | 132 ++++++++++++------ .../Exceptions/ExceptionHandlerTest.php | 39 ++++++ 9 files changed, 147 insertions(+), 100 deletions(-) create mode 100644 tests/integration/Exceptions/ExceptionHandlerTest.php diff --git a/config/twill.php b/config/twill.php index 2ac04da688..60eb306150 100644 --- a/config/twill.php +++ b/config/twill.php @@ -25,7 +25,7 @@ /* |-------------------------------------------------------------------------- - | Application strict url handeling + | Application strict url handling |-------------------------------------------------------------------------- | | Setting this value to true will enable strict domain handling. diff --git a/phpunit-legacy.xml b/phpunit-legacy.xml index 00e6666513..2b02d5be6f 100644 --- a/phpunit-legacy.xml +++ b/phpunit-legacy.xml @@ -17,13 +17,13 @@ - - tests/Browser - tests/unit tests/integration + + tests/Browser + diff --git a/phpunit.xml b/phpunit.xml index f38f3f79c5..5bb5c42323 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,13 +7,13 @@ - - tests/Browser - tests/unit tests/integration + + tests/Browser + diff --git a/src/Exceptions/Handler.php b/src/Exceptions/Handler.php index a267e038db..3799db157a 100644 --- a/src/Exceptions/Handler.php +++ b/src/Exceptions/Handler.php @@ -2,51 +2,16 @@ namespace A17\Twill\Exceptions; +use Illuminate\Contracts\Container\Container; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; -use Illuminate\Support\Facades\Request; -use Illuminate\Support\Str; -use Illuminate\Validation\ValidationException; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; +/** @deprecated It is not needed anymore and will be removed in v4 */ class Handler extends ExceptionHandler { - /** - * Get the view used to render HTTP exceptions. - * - * @return string - */ - protected function getHttpExceptionView(HttpExceptionInterface $e) + public function __construct(Container $container) { - $usesAdminPath = !empty(config('twill.admin_app_path')); - $adminAppUrl = config('twill.admin_app_url', config('app.url')); + parent::__construct($container); - $isSubdomainAdmin = !$usesAdminPath && Str::contains(Request::url(), $adminAppUrl); - $isSubdirectoryAdmin = $usesAdminPath && Str::startsWith(Request::path(), config('twill.admin_app_path')); - - return $this->getTwillErrorView($e->getStatusCode(), !$isSubdomainAdmin && !$isSubdirectoryAdmin); - } - - /** - * Get the Twill error view used to render a specified HTTP status code. - * - * @param integer $statusCode - * @return string - */ - protected function getTwillErrorView($statusCode, $frontend = false) - { - if ($frontend) { - $view = config('twill.frontend.views_path') . ".errors.$statusCode"; - - return view()->exists($view) ? $view : "errors::{$statusCode}"; - } - - $view = "twill.errors.$statusCode"; - - return view()->exists($view) ? $view : "twill::errors.$statusCode"; - } - - protected function invalidJson($request, ValidationException $exception) - { - return response()->json($exception->errors(), $exception->status); + trigger_deprecation('area17/twill', '3.4', 'The Twill Exception handler is deprecated and will be removed in v4, go back to extending the laravel ExceptionHandler'); } } diff --git a/src/Http/Controllers/Admin/Controller.php b/src/Http/Controllers/Admin/Controller.php index 8944770775..247afe3ab5 100644 --- a/src/Http/Controllers/Admin/Controller.php +++ b/src/Http/Controllers/Admin/Controller.php @@ -20,9 +20,6 @@ class Controller extends BaseController public function __construct() { - if (Config::get('twill.bind_exception_handler', true)) { - App::singleton(ExceptionHandler::class, TwillHandler::class); - } } /** diff --git a/src/Http/Controllers/Front/Controller.php b/src/Http/Controllers/Front/Controller.php index 9d72359b26..3848488c36 100644 --- a/src/Http/Controllers/Front/Controller.php +++ b/src/Http/Controllers/Front/Controller.php @@ -19,10 +19,6 @@ class Controller extends BaseController public function __construct() { - if (Config::get('twill.bind_exception_handler', true)) { - App::singleton(ExceptionHandler::class, TwillHandler::class); - } - $this->seo = new Seo(); $this->seo->title = Config::get('twill.seo.site_title'); diff --git a/src/TwillRoutes.php b/src/TwillRoutes.php index 5881d146fc..f72334cd34 100644 --- a/src/TwillRoutes.php +++ b/src/TwillRoutes.php @@ -402,4 +402,14 @@ public function getAuthRedirectPath(): string return config('twill.auth_login_redirect_path') ?? rtrim(config('twill.admin_app_url') ?: '', '/') . '/' . ltrim(config('twill.admin_app_path') ?? 'admin', '/'); } + + public function isTwillRequest(): bool + { + $adminAppUrl = config('twill.admin_app_url', config('app.url')); + + $matchesDomain = !config('twill.admin_app_strict') || Str::endsWith(\request()->getSchemeAndHttpHost(), $adminAppUrl); + $matchesPath = empty(config('twill.admin_app_path')) || \request()->is(config('twill.admin_app_path', '') . '*'); + + return $matchesDomain && $matchesPath; + } } diff --git a/src/TwillServiceProvider.php b/src/TwillServiceProvider.php index 7fec36a823..4e2dbe55d4 100644 --- a/src/TwillServiceProvider.php +++ b/src/TwillServiceProvider.php @@ -28,6 +28,7 @@ use A17\Twill\Commands\Update; use A17\Twill\Commands\UpdateExampleCommand; use A17\Twill\Commands\UpdateMorphMapReferences; +use A17\Twill\Facades\TwillRoutes; use A17\Twill\Http\ViewComposers\CurrentUser; use A17\Twill\Http\ViewComposers\FilesUploaderConfig; use A17\Twill\Http\ViewComposers\Localization; @@ -42,14 +43,20 @@ use Astrotomic\Translatable\TranslatableServiceProvider; use Cartalyst\Tags\TagsServiceProvider; use Exception; +use Illuminate\Contracts\Debug\ExceptionHandler; +use Illuminate\Contracts\Foundation\CachesConfiguration; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Foundation\AliasLoader; +use Illuminate\Foundation\Exceptions\Handler; use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; +use Illuminate\Support\ViewErrorBag; +use Illuminate\Validation\ValidationException; use PragmaRX\Google2FAQRCode\Google2FA as Google2FAQRCode; use Spatie\Activitylog\ActivitylogServiceProvider; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; class TwillServiceProvider extends ServiceProvider { @@ -79,8 +86,6 @@ class TwillServiceProvider extends ServiceProvider */ public function boot(): void { - $this->requireHelpers(); - $this->publishConfigs(); $this->publishMigrations(); $this->publishAssets(); @@ -116,8 +121,13 @@ private function requireHelpers(): void */ public function register(): void { - $this->mergeConfigs(); + $this->requireHelpers(); + if (! ($this->app instanceof CachesConfiguration && $this->app->configurationIsCached())) { + $this->mergeConfigs(); + } + + $this->registerErrorHandlers(); $this->registerProviders(); $this->registerAliases(); $this->registerFacades(); @@ -150,8 +160,6 @@ public function register(): void 'blocks' => config('twill.models.block', Block::class), 'groups' => config('twill.models.group', Group::class), ]); - - config(['twill.version' => $this->version()]); } private function registerFacades(): void @@ -214,47 +222,6 @@ private function registerAliases(): void */ private function publishConfigs(): void { - if (config('twill.enabled.users-management')) { - config([ - 'auth.providers.twill_users' => [ - 'driver' => 'eloquent', - 'model' => twillModel('user'), - ], - ]); - - config([ - 'auth.guards.twill_users' => [ - 'driver' => 'session', - 'provider' => 'twill_users', - ], - ]); - - if (blank(config('auth.passwords.twill_users'))) { - config([ - 'auth.passwords.twill_users' => [ - 'provider' => 'twill_users', - 'table' => config('twill.password_resets_table', 'twill_password_resets'), - 'expire' => 60, - 'throttle' => 60, - ], - ]); - } - } - - config( - ['activitylog.enabled' => config('twill.enabled.dashboard') ? true : config('twill.enabled.activitylog')] - ); - config(['activitylog.subject_returns_soft_deleted_models' => true]); - - config( - [ - 'analytics.service_account_credentials_json' => config( - 'twill.dashboard.analytics.service_account_credentials_json', - storage_path('app/analytics/service-account-credentials.json') - ), - ] - ); - $this->publishes([__DIR__ . '/../config/twill-publish.php' => config_path('twill.php')], 'config'); $this->publishes([__DIR__ . '/../config/translatable.php' => config_path('translatable.php')], 'config'); } @@ -299,6 +266,49 @@ private function mergeConfigs(): void } $this->mergeConfigFrom(__DIR__ . '/../config/services.php', 'services'); + + if (config('twill.enabled.users-management')) { + config([ + 'auth.providers.twill_users' => [ + 'driver' => 'eloquent', + 'model' => twillModel('user'), + ], + ]); + + config([ + 'auth.guards.twill_users' => [ + 'driver' => 'session', + 'provider' => 'twill_users', + ], + ]); + + if (blank(config('auth.passwords.twill_users'))) { + config([ + 'auth.passwords.twill_users' => [ + 'provider' => 'twill_users', + 'table' => config('twill.password_resets_table', 'twill_password_resets'), + 'expire' => 60, + 'throttle' => 60, + ], + ]); + } + } + + config( + ['activitylog.enabled' => config('twill.enabled.dashboard') ? true : config('twill.enabled.activitylog')] + ); + config(['activitylog.subject_returns_soft_deleted_models' => true]); + + config( + [ + 'analytics.service_account_credentials_json' => config( + 'twill.dashboard.analytics.service_account_credentials_json', + storage_path('app/analytics/service-account-credentials.json') + ), + ] + ); + + config(['twill.version' => $this->version()]); } private function setLocalDiskUrl($type): void @@ -625,4 +635,34 @@ public function check2FA(): void ); } } + + private function registerErrorHandlers(): void + { + $handler = app(ExceptionHandler::class); + if ($handler instanceof Handler) { + $handler->renderable(function (HttpExceptionInterface $e) { + $statusCode = $e->getStatusCode(); + if (TwillRoutes::isTwillRequest()) { + $view = "twill.errors.$statusCode"; + + $view = view()->exists($view) ? $view : "twill::errors.$statusCode"; + } else { + $view = config('twill.frontend.views_path') . ".errors.$statusCode"; + + $view = view()->exists($view) ? $view : null; + } + return $view ? response()->view($view, [ + 'errors' => new ViewErrorBag(), + 'exception' => $e, + ], $e->getStatusCode(), $e->getHeaders()) : null; + }); + + $handler->renderable(function (ValidationException $exception) { + if (TwillRoutes::isTwillRequest() && request()->expectsJson()) { + return response()->json($exception->errors(), $exception->status); + } + return null; + }); + } + } } diff --git a/tests/integration/Exceptions/ExceptionHandlerTest.php b/tests/integration/Exceptions/ExceptionHandlerTest.php new file mode 100644 index 0000000000..3b4c5d2d62 --- /dev/null +++ b/tests/integration/Exceptions/ExceptionHandlerTest.php @@ -0,0 +1,39 @@ +get('/twill/foobar'); + $res->assertStatus(404); + $this->assertEquals($res->original->name(), "twill::errors.404"); + } + + public function test404InFrontend() + { + $res = $this->get('/foobar'); + $res->assertStatus(404); + $this->assertTrue(is_string($res->original)); + } + + public function testValidationException() + { + Route::post('/twill/validation-exception', function (Request $request) { + $request->validate([ + 'dummy' => 'required', + ]); + }); + + $res = $this->postJson('/twill/validation-exception'); + $res->assertStatus(422); + // Response is directly an array of exceptions and doesn't have a response key + $res->assertJsonValidationErrors('dummy', null); + } +} From 01799fc40b1f97be0f418fa911af1efca8ed328c Mon Sep 17 00:00:00 2001 From: Tofandel Date: Thu, 13 Jun 2024 13:27:14 +0200 Subject: [PATCH 2/3] Remove outdated doc --- .../2_getting-started/3_configuration.md | 25 ------------------- phpunit-legacy.xml | 6 ++--- phpunit.xml | 6 ++--- 3 files changed, 6 insertions(+), 31 deletions(-) diff --git a/docs/content/1_docs/2_getting-started/3_configuration.md b/docs/content/1_docs/2_getting-started/3_configuration.md index 5bfc125fdc..33230f7cf7 100644 --- a/docs/content/1_docs/2_getting-started/3_configuration.md +++ b/docs/content/1_docs/2_getting-started/3_configuration.md @@ -79,31 +79,6 @@ return [ ]; ``` -Twill registers its own exception handler in all controllers. If you need to customize it (to report errors on a 3rd party service like Sentry or Rollbar for example), you can opt-out from it in your `config/twill.php` file: - -```php - false, -]; -``` - -And then extend it from your own `app/Exceptions/Handler.php` class: - -```php - + + tests/Browser + tests/unit tests/integration - - tests/Browser - diff --git a/phpunit.xml b/phpunit.xml index 5bb5c42323..f38f3f79c5 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,13 +7,13 @@ + + tests/Browser + tests/unit tests/integration - - tests/Browser - From f76d55f79f74507ceaaddbe49aa392cf9f5966ce Mon Sep 17 00:00:00 2001 From: Tofandel Date: Thu, 13 Jun 2024 23:40:51 +0200 Subject: [PATCH 3/3] Support subdomain --- UPGRADE.md | 2 +- src/TwillRoutes.php | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index bcd263b48a..39d574b1cc 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -52,7 +52,7 @@ If you are relying on Quill.js specifics (like css classes), use `'type' => 'qui Previously `withVideo` was true by default, if you relied on this you have to update these media fields to `'withVideo' => true`. -#### SVG's are now no longer passing thorough glide +#### SVG's are now no longer passing through glide These are now rendered directly, you can change this by updating config `twill.glide.original_media_for_extensions` to an empty array `[]` diff --git a/src/TwillRoutes.php b/src/TwillRoutes.php index f72334cd34..9c9624f9b3 100644 --- a/src/TwillRoutes.php +++ b/src/TwillRoutes.php @@ -9,6 +9,8 @@ use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; +use function request; + class TwillRoutes { /** @@ -405,10 +407,14 @@ public function getAuthRedirectPath(): string public function isTwillRequest(): bool { - $adminAppUrl = config('twill.admin_app_url', config('app.url')); + $adminAppUrl = str_replace(['http://', 'https://'], '', config('twill.admin_app_url', config('app.url'))); + $requestHost = request()->getHttpHost(); + + $matchesDomain = config('twill.support_subdomain_admin_routing') ? + Str::startsWith($requestHost, config('twill.admin_app_subdomain', 'admin') . '.') && Str::endsWith($requestHost, '.' . $adminAppUrl) + : !config('twill.admin_app_strict') || $requestHost === $adminAppUrl; - $matchesDomain = !config('twill.admin_app_strict') || Str::endsWith(\request()->getSchemeAndHttpHost(), $adminAppUrl); - $matchesPath = empty(config('twill.admin_app_path')) || \request()->is(config('twill.admin_app_path', '') . '*'); + $matchesPath = empty(config('twill.admin_app_path')) || request()->is(config('twill.admin_app_path', '') . '*'); return $matchesDomain && $matchesPath; }