diff --git a/app/Entities/Controllers/PageRevisionController.php b/app/Entities/Controllers/PageRevisionController.php index 35f1e8daf0e..4bc15e6e967 100644 --- a/app/Entities/Controllers/PageRevisionController.php +++ b/app/Entities/Controllers/PageRevisionController.php @@ -12,6 +12,8 @@ use BookStack\Facades\Activity; use BookStack\Http\Controller; use BookStack\Permissions\Permission; +use BookStack\Util\HtmlContentFilter; +use BookStack\Util\HtmlContentFilterConfig; use BookStack\Util\SimpleListOptions; use Illuminate\Http\Request; use Ssddanbrown\HtmlDiff\Diff; @@ -101,12 +103,15 @@ public function changes(string $bookSlug, string $pageSlug, int $revisionId) $prev = $revision->getPreviousRevision(); $prevContent = $prev->html ?? ''; - $diff = Diff::excecute($prevContent, $revision->html); + + // TODO - Refactor PageContent so we can de-dupe these steps + $rawDiff = Diff::excecute($prevContent, $revision->html); + $filterConfig = HtmlContentFilterConfig::fromConfigString(config('app.content_filtering')); + $filter = new HtmlContentFilter($filterConfig); + $diff = $filter->filterString($rawDiff); $page->fill($revision->toArray()); - // TODO - Refactor PageContent so we don't need to juggle this - $page->html = $revision->html; - $page->html = (new PageContent($page))->render(); + $page->html = ''; $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()])); return view('pages.revision', [ diff --git a/app/Http/Controller.php b/app/Http/Controller.php index 5d3be4951ca..1a0f5932e6f 100644 --- a/app/Http/Controller.php +++ b/app/Http/Controller.php @@ -167,14 +167,26 @@ protected function getImageValidationRules(): array /** * Redirect to the URL provided in the request as a '_return' parameter. - * Will check that the parameter leads to a URL under the root path of the system. + * Will check that the parameter leads to a URL under the same origin as the application. */ protected function redirectToRequest(Request $request): RedirectResponse { $basePath = url('/'); $returnUrl = $request->input('_return') ?? $basePath; - if (!str_starts_with($returnUrl, $basePath)) { + // Only allow use of _return on requests where we expect CSRF to be active + // to prevent it potentially being used as an open redirect + $allowedMethods = ['POST', 'PUT', 'PATCH', 'DELETE']; + if (!in_array($request->getMethod(), $allowedMethods)) { + return redirect($basePath); + } + + $intendedUrl = parse_url($returnUrl); + $baseUrl = parse_url($basePath); + $isSameOrigin = ($intendedUrl['host'] ?? '') === ($baseUrl['host'] ?? '') + && ($intendedUrl['scheme'] ?? '') === ($baseUrl['scheme'] ?? '') + && ($intendedUrl['port'] ?? 0) === ($baseUrl['port'] ?? 0); + if (!$isSameOrigin) { return redirect($basePath); } diff --git a/composer.lock b/composer.lock index 18d0da62191..d8ea0066265 100644 --- a/composer.lock +++ b/composer.lock @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.371.2", + "version": "3.373.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "32090a8ac3ec8859cb83bdde800b8f0ecf92d8ec" + "reference": "fb74a2dca7ae2363e929c5cea33a4a4db0d22690" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/32090a8ac3ec8859cb83bdde800b8f0ecf92d8ec", - "reference": "32090a8ac3ec8859cb83bdde800b8f0ecf92d8ec", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fb74a2dca7ae2363e929c5cea33a4a4db0d22690", + "reference": "fb74a2dca7ae2363e929c5cea33a4a4db0d22690", "shasum": "" }, "require": { @@ -135,11 +135,11 @@ "authors": [ { "name": "Amazon Web Services", - "homepage": "http://aws.amazon.com" + "homepage": "https://aws.amazon.com" } ], "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", - "homepage": "http://aws.amazon.com/sdkforphp", + "homepage": "https://aws.amazon.com/sdk-for-php", "keywords": [ "amazon", "aws", @@ -153,9 +153,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.371.2" + "source": "https://github.com/aws/aws-sdk-php/tree/3.373.0" }, - "time": "2026-02-26T19:06:10+00:00" + "time": "2026-03-11T18:33:36+00:00" }, { "name": "bacon/bacon-qr-code", @@ -635,16 +635,16 @@ }, { "name": "dompdf/dompdf", - "version": "v3.1.4", + "version": "v3.1.5", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "db712c90c5b9868df3600e64e68da62e78a34623" + "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/db712c90c5b9868df3600e64e68da62e78a34623", - "reference": "db712c90c5b9868df3600e64e68da62e78a34623", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", + "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", "shasum": "" }, "require": { @@ -693,9 +693,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v3.1.4" + "source": "https://github.com/dompdf/dompdf/tree/v3.1.5" }, - "time": "2025-10-29T12:43:30+00:00" + "time": "2026-03-03T13:54:37+00:00" }, { "name": "dompdf/php-font-lib", @@ -1387,16 +1387,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.8.0", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884", + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884", "shasum": "" }, "require": { @@ -1412,6 +1412,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", + "jshttp/mime-db": "1.54.0.1", "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { @@ -1483,7 +1484,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.8.0" + "source": "https://github.com/guzzle/psr7/tree/2.9.0" }, "funding": [ { @@ -1499,7 +1500,7 @@ "type": "tidelift" } ], - "time": "2025-08-23T21:21:41+00:00" + "time": "2026-03-10T16:41:02+00:00" }, { "name": "guzzlehttp/uri-template", @@ -1800,16 +1801,16 @@ }, { "name": "laravel/framework", - "version": "v12.53.0", + "version": "v12.54.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "f57f035c0d34503d9ff30be76159bb35a003cd1f" + "reference": "325497463e7599cd14224c422c6e5dd2fe832868" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/f57f035c0d34503d9ff30be76159bb35a003cd1f", - "reference": "f57f035c0d34503d9ff30be76159bb35a003cd1f", + "url": "https://api.github.com/repos/laravel/framework/zipball/325497463e7599cd14224c422c6e5dd2fe832868", + "reference": "325497463e7599cd14224c422c6e5dd2fe832868", "shasum": "" }, "require": { @@ -1830,7 +1831,7 @@ "guzzlehttp/uri-template": "^1.0", "laravel/prompts": "^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", - "league/commonmark": "^2.7", + "league/commonmark": "^2.8.1", "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", @@ -2018,20 +2019,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-02-24T14:35:15+00:00" + "time": "2026-03-10T20:25:56+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.13", + "version": "v0.3.14", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "ed8c466571b37e977532fb2fd3c272c784d7050d" + "reference": "9f0e371244eedfe2ebeaa72c79c54bb5df6e0176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/ed8c466571b37e977532fb2fd3c272c784d7050d", - "reference": "ed8c466571b37e977532fb2fd3c272c784d7050d", + "url": "https://api.github.com/repos/laravel/prompts/zipball/9f0e371244eedfe2ebeaa72c79c54bb5df6e0176", + "reference": "9f0e371244eedfe2ebeaa72c79c54bb5df6e0176", "shasum": "" }, "require": { @@ -2075,9 +2076,9 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.13" + "source": "https://github.com/laravel/prompts/tree/v0.3.14" }, - "time": "2026-02-06T12:17:10+00:00" + "time": "2026-03-01T09:02:38+00:00" }, { "name": "laravel/serializable-closure", @@ -2142,16 +2143,16 @@ }, { "name": "laravel/socialite", - "version": "v5.24.3", + "version": "v5.25.0", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "0feb62267e7b8abc68593ca37639ad302728c129" + "reference": "231f572e1a37c9ca1fb8085e9fb8608285beafb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/0feb62267e7b8abc68593ca37639ad302728c129", - "reference": "0feb62267e7b8abc68593ca37639ad302728c129", + "url": "https://api.github.com/repos/laravel/socialite/zipball/231f572e1a37c9ca1fb8085e9fb8608285beafb3", + "reference": "231f572e1a37c9ca1fb8085e9fb8608285beafb3", "shasum": "" }, "require": { @@ -2210,7 +2211,7 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2026-02-21T13:32:50+00:00" + "time": "2026-02-27T13:56:35+00:00" }, { "name": "laravel/tinker", @@ -2280,16 +2281,16 @@ }, { "name": "league/commonmark", - "version": "2.8.0", + "version": "2.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" + "reference": "84b1ca48347efdbe775426f108622a42735a6579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/84b1ca48347efdbe775426f108622a42735a6579", + "reference": "84b1ca48347efdbe775426f108622a42735a6579", "shasum": "" }, "require": { @@ -2314,9 +2315,9 @@ "phpstan/phpstan": "^1.8.2", "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 | ^7.0", - "symfony/process": "^5.4 | ^6.0 | ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0", "unleashedtech/php-coding-standard": "^3.1.1", "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" }, @@ -2383,7 +2384,7 @@ "type": "tidelift" } ], - "time": "2025-11-26T21:48:24+00:00" + "time": "2026-03-05T21:37:03+00:00" }, { "name": "league/config", @@ -3360,16 +3361,16 @@ }, { "name": "nesbot/carbon", - "version": "3.11.1", + "version": "3.11.3", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "f438fcc98f92babee98381d399c65336f3a3827f" + "reference": "6a7e652845bb018c668220c2a545aded8594fbbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/f438fcc98f92babee98381d399c65336f3a3827f", - "reference": "f438fcc98f92babee98381d399c65336f3a3827f", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6a7e652845bb018c668220c2a545aded8594fbbf", + "reference": "6a7e652845bb018c668220c2a545aded8594fbbf", "shasum": "" }, "require": { @@ -3461,7 +3462,7 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:26:29+00:00" + "time": "2026-03-11T17:23:39+00:00" }, { "name": "nette/schema", @@ -4188,16 +4189,16 @@ }, { "name": "predis/predis", - "version": "v3.4.1", + "version": "v3.4.2", "source": { "type": "git", "url": "https://github.com/predis/predis.git", - "reference": "0850f2f36ee179f0ff96c92c750e1366c6cd754c" + "reference": "2033429520d8997a7815a2485f56abe6d2d0e075" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/predis/predis/zipball/0850f2f36ee179f0ff96c92c750e1366c6cd754c", - "reference": "0850f2f36ee179f0ff96c92c750e1366c6cd754c", + "url": "https://api.github.com/repos/predis/predis/zipball/2033429520d8997a7815a2485f56abe6d2d0e075", + "reference": "2033429520d8997a7815a2485f56abe6d2d0e075", "shasum": "" }, "require": { @@ -4239,7 +4240,7 @@ ], "support": { "issues": "https://github.com/predis/predis/issues", - "source": "https://github.com/predis/predis/tree/v3.4.1" + "source": "https://github.com/predis/predis/tree/v3.4.2" }, "funding": [ { @@ -4247,7 +4248,7 @@ "type": "github" } ], - "time": "2026-02-23T19:51:21+00:00" + "time": "2026-03-09T20:33:04+00:00" }, { "name": "psr/clock", @@ -4663,16 +4664,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.20", + "version": "v0.12.21", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "19678eb6b952a03b8a1d96ecee9edba518bb0373" + "reference": "4821fab5b7cd8c49a673a9fd5754dc9162bb9e97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/19678eb6b952a03b8a1d96ecee9edba518bb0373", - "reference": "19678eb6b952a03b8a1d96ecee9edba518bb0373", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4821fab5b7cd8c49a673a9fd5754dc9162bb9e97", + "reference": "4821fab5b7cd8c49a673a9fd5754dc9162bb9e97", "shasum": "" }, "require": { @@ -4736,9 +4737,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.20" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.21" }, - "time": "2026-02-11T15:05:28+00:00" + "time": "2026-03-06T21:21:28+00:00" }, { "name": "ralouphie/getallheaders", @@ -4982,16 +4983,16 @@ }, { "name": "sabberworm/php-css-parser", - "version": "v9.2.0", + "version": "v9.3.0", "source": { "type": "git", "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", - "reference": "59373045e11ad47b5c18fc615feee0219e42f6d3" + "reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/59373045e11ad47b5c18fc615feee0219e42f6d3", - "reference": "59373045e11ad47b5c18fc615feee0219e42f6d3", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949", + "reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949", "shasum": "" }, "require": { @@ -5018,7 +5019,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.3.x-dev" + "dev-main": "9.4.x-dev" } }, "autoload": { @@ -5056,9 +5057,9 @@ ], "support": { "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", - "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.2.0" + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.3.0" }, - "time": "2026-02-21T17:12:03+00:00" + "time": "2026-03-03T17:31:43+00:00" }, { "name": "socialiteproviders/discord", @@ -5508,16 +5509,16 @@ }, { "name": "symfony/console", - "version": "v7.4.6", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6d643a93b47398599124022eb24d97c153c12f27" + "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6d643a93b47398599124022eb24d97c153c12f27", - "reference": "6d643a93b47398599124022eb24d97c153c12f27", + "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d", + "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d", "shasum": "" }, "require": { @@ -5582,7 +5583,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.6" + "source": "https://github.com/symfony/console/tree/v7.4.7" }, "funding": [ { @@ -5602,7 +5603,7 @@ "type": "tidelift" } ], - "time": "2026-02-25T17:02:47+00:00" + "time": "2026-03-06T14:06:20+00:00" }, { "name": "symfony/css-selector", @@ -6123,16 +6124,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.4.6", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "fd97d5e926e988a363cef56fbbf88c5c528e9065" + "reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/fd97d5e926e988a363cef56fbbf88c5c528e9065", - "reference": "fd97d5e926e988a363cef56fbbf88c5c528e9065", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f94b3e7b7dafd40e666f0c9ff2084133bae41e81", + "reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81", "shasum": "" }, "require": { @@ -6181,7 +6182,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.6" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.7" }, "funding": [ { @@ -6201,20 +6202,20 @@ "type": "tidelift" } ], - "time": "2026-02-21T16:25:55+00:00" + "time": "2026-03-06T13:15:18+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.6", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "002ac0cf4cd972a7fd0912dcd513a95e8a81ce83" + "reference": "3b3fcf386c809be990c922e10e4c620d6367cab1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/002ac0cf4cd972a7fd0912dcd513a95e8a81ce83", - "reference": "002ac0cf4cd972a7fd0912dcd513a95e8a81ce83", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3b3fcf386c809be990c922e10e4c620d6367cab1", + "reference": "3b3fcf386c809be990c922e10e4c620d6367cab1", "shasum": "" }, "require": { @@ -6300,7 +6301,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.6" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.7" }, "funding": [ { @@ -6320,7 +6321,7 @@ "type": "tidelift" } ], - "time": "2026-02-26T08:30:57+00:00" + "time": "2026-03-06T16:33:18+00:00" }, { "name": "symfony/mailer", @@ -6408,16 +6409,16 @@ }, { "name": "symfony/mime", - "version": "v7.4.6", + "version": "v7.4.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "9fc881d95feae4c6c48678cb6372bd8a7ba04f5f" + "reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/9fc881d95feae4c6c48678cb6372bd8a7ba04f5f", - "reference": "9fc881d95feae4c6c48678cb6372bd8a7ba04f5f", + "url": "https://api.github.com/repos/symfony/mime/zipball/da5ab4fde3f6c88ab06e96185b9922f48b677cd1", + "reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1", "shasum": "" }, "require": { @@ -6473,7 +6474,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.4.6" + "source": "https://github.com/symfony/mime/tree/v7.4.7" }, "funding": [ { @@ -6493,7 +6494,7 @@ "type": "tidelift" } ], - "time": "2026-02-05T15:57:06+00:00" + "time": "2026-03-05T15:24:09+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8721,40 +8722,40 @@ }, { "name": "larastan/larastan", - "version": "v3.9.2", + "version": "v3.9.3", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2" + "reference": "64a52bcc5347c89fdf131cb59f96ebfbc8d1ad65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2", - "reference": "2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2", + "url": "https://api.github.com/repos/larastan/larastan/zipball/64a52bcc5347c89fdf131cb59f96ebfbc8d1ad65", + "reference": "64a52bcc5347c89fdf131cb59f96ebfbc8d1ad65", "shasum": "" }, "require": { "ext-json": "*", "iamcal/sql-parser": "^0.7.0", - "illuminate/console": "^11.44.2 || ^12.4.1", - "illuminate/container": "^11.44.2 || ^12.4.1", - "illuminate/contracts": "^11.44.2 || ^12.4.1", - "illuminate/database": "^11.44.2 || ^12.4.1", - "illuminate/http": "^11.44.2 || ^12.4.1", - "illuminate/pipeline": "^11.44.2 || ^12.4.1", - "illuminate/support": "^11.44.2 || ^12.4.1", + "illuminate/console": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/container": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/contracts": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/database": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/http": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/pipeline": "^11.44.2 || ^12.4.1 || ^13", + "illuminate/support": "^11.44.2 || ^12.4.1 || ^13", "php": "^8.2", "phpstan/phpstan": "^2.1.32" }, "require-dev": { "doctrine/coding-standard": "^13", - "laravel/framework": "^11.44.2 || ^12.7.2", + "laravel/framework": "^11.44.2 || ^12.7.2 || ^13", "mockery/mockery": "^1.6.12", "nikic/php-parser": "^5.4", - "orchestra/canvas": "^v9.2.2 || ^10.0.1", - "orchestra/testbench-core": "^9.12.0 || ^10.1", + "orchestra/canvas": "^v9.2.2 || ^10.0.1 || ^11", + "orchestra/testbench-core": "^9.12.0 || ^10.1 || ^11", "phpstan/phpstan-deprecation-rules": "^2.0.1", - "phpunit/phpunit": "^10.5.35 || ^11.5.15" + "phpunit/phpunit": "^10.5.35 || ^11.5.15 || ^12.5.8" }, "suggest": { "orchestra/testbench": "Using Larastan for analysing a package needs Testbench", @@ -8799,7 +8800,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v3.9.2" + "source": "https://github.com/larastan/larastan/tree/v3.9.3" }, "funding": [ { @@ -8807,7 +8808,7 @@ "type": "github" } ], - "time": "2026-01-30T15:16:32+00:00" + "time": "2026-02-20T12:07:12+00:00" }, { "name": "mockery/mockery", @@ -10743,21 +10744,22 @@ }, { "name": "ssddanbrown/asserthtml", - "version": "v3.1.0", + "version": "v3.2.0", "source": { "type": "git", "url": "https://codeberg.org/danb/asserthtml", - "reference": "cf8206171d667d43e1bdde17d67191f30e95c8a0" + "reference": "0811b5c8d541f344c193bd7f2c2d79d13d23b141" }, "dist": { "type": "zip", - "url": "https://codeberg.org/api/v1/repos/danb/asserthtml/archive/%prettyVersion%.zip" + "url": "https://codeberg.org/api/v1/repos/danb/asserthtml/archive/%prettyVersion%.zip", + "reference": "0811b5c8d541f344c193bd7f2c2d79d13d23b141" }, "require": { "ext-dom": "*", "ext-json": "*", "php": ">=8.1", - "phpunit/phpunit": "^10.0|^11.0", + "phpunit/phpunit": "^10.0|^11.0|^12.0|^13.0", "symfony/css-selector": "^6.0|^7.0", "symfony/dom-crawler": "^6.0|^7.0" }, @@ -10783,7 +10785,7 @@ ], "description": "HTML Content Assertions for PHPUnit", "homepage": "https://codeberg.org/danb/asserthtml", - "time": "2025-01-11T13:35:55+00:00" + "time": "2026-03-04T14:19:44+00:00" }, { "name": "staabm/side-effects-detector", diff --git a/tests/Entity/PageRevisionTest.php b/tests/Entity/PageRevisionTest.php index 3828bd06e4a..132a10fa4da 100644 --- a/tests/Entity/PageRevisionTest.php +++ b/tests/Entity/PageRevisionTest.php @@ -47,6 +47,20 @@ public function test_page_revision_preview_shows_content_of_revision() $revisionView->assertSee('new revision content'); } + public function test_page_revision_preview_filters_html_content() + { + $this->asEditor(); + $page = $this->entities->page(); + $this->createRevisions($page, 1, ['name' => 'updated page', 'html' => '
expectthisthough
']); + $pageRevision = $page->revisions->last(); + $this->createRevisions($page, 1, ['name' => 'updated page', 'html' => 'Updated content
']); + + $revisionView = $this->get($page->getUrl() . '/revisions/' . $pageRevision->id); + $revisionView->assertStatus(200); + $revisionView->assertSee('expectthisthough'); + $revisionView->assertDontSee('dontwantthishere'); + } + public function test_page_revision_restore_updates_content() { $this->asEditor(); @@ -215,6 +229,34 @@ public function test_revision_changes_link_not_shown_for_oldest_revision() $html->assertElementContains('.item-list > .item-list-row:nth-child(2)', 'Changes'); } + public function test_revision_changes_view_shows_diff() + { + $this->asEditor(); + $page = $this->entities->page(); + $this->createRevisions($page, 1, ['name' => 'updated page', 'html' => 'Hello there dog
']); + $this->createRevisions($page, 1, ['name' => 'updated page', 'html' => 'Hello there cat
']); + + $pageRevision = $page->revisions()->orderBy('id', 'desc')->first(); + $revisionView = $this->get("{$page->getUrl()}/revisions/{$pageRevision->id}/changes"); + $revisionView->assertStatus(200); + $revisionView->assertSee('Hello there dogcat
expectthisthough
'; + $this->createRevisions($page, 1, ['name' => 'updated page', 'html' => $html]); + $this->createRevisions($page, 1, ['name' => 'updated page', 'html' => $html]); + + $pageRevision = $page->revisions()->orderBy('id', 'desc')->first(); + $revisionView = $this->get("{$page->getUrl()}/revisions/{$pageRevision->id}/changes"); + $revisionView->assertStatus(200); + $revisionView->assertSee('expectthisthough'); + $revisionView->assertDontSee('dontwantthishere'); + } + public function test_revision_restore_action_only_visible_with_permission() { $page = $this->entities->page(); diff --git a/tests/User/UserPreferencesTest.php b/tests/User/UserPreferencesTest.php index ff3cb63ca70..e893f002dfd 100644 --- a/tests/User/UserPreferencesTest.php +++ b/tests/User/UserPreferencesTest.php @@ -153,6 +153,26 @@ public function test_shelf_view_type_change() ->assertElementNotExists('.content-wrap .entity-list-item'); } + public function test_redirect_on_preference_change_checks_host() + { + $expectedByRedirect = [ + 'http://localhost/beans' => 'http://localhost/beans', + 'https://localhost/beans' => 'http://localhost', + 'http://localhost:9090/beans' => 'http://localhost', + 'http://localhost.example.com/beans' => 'http://localhost', + 'http://localhost@example.com/beans' => 'http://localhost', + ]; + + $this->asEditor(); + foreach ($expectedByRedirect as $url => $expected) { + $req = $this->patch("/preferences/change-view/bookshelf", [ + 'view' => 'grid', + '_return' => $url, + ]); + $req->assertRedirect($expected); + } + } + public function test_update_code_language_favourite() { $editor = $this->users->editor();