diff --git a/app/Entities/Controllers/PageController.php b/app/Entities/Controllers/PageController.php index a648bc298..8778560e2 100644 --- a/app/Entities/Controllers/PageController.php +++ b/app/Entities/Controllers/PageController.php @@ -21,6 +21,8 @@ use BookStack\Exceptions\PermissionsException; use BookStack\Http\Controller; use BookStack\Permissions\Permission; use BookStack\References\ReferenceFetcher; +use BookStack\Util\HtmlContentFilter; +use BookStack\Util\HtmlContentFilterConfig; use Exception; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Http\Request; @@ -173,7 +175,7 @@ class PageController extends Controller } /** - * Get page from an ajax request. + * Get a page from an ajax request. * * @throws NotFoundException */ @@ -183,6 +185,10 @@ class PageController extends Controller $page->setHidden(array_diff($page->getHidden(), ['html', 'markdown'])); $page->makeHidden(['book']); + $filterConfig = HtmlContentFilterConfig::fromConfigString(config('app.content_filtering')); + $filter = new HtmlContentFilter($filterConfig); + $page->html = $filter->filterString($page->html); + return response()->json($page); } diff --git a/app/Entities/Tools/PageEditorData.php b/app/Entities/Tools/PageEditorData.php index b41b31909..2872eca14 100644 --- a/app/Entities/Tools/PageEditorData.php +++ b/app/Entities/Tools/PageEditorData.php @@ -8,6 +8,8 @@ use BookStack\Entities\Queries\EntityQueries; use BookStack\Entities\Tools\Markdown\HtmlToMarkdown; use BookStack\Entities\Tools\Markdown\MarkdownToHtml; use BookStack\Permissions\Permission; +use BookStack\Util\HtmlContentFilter; +use BookStack\Util\HtmlContentFilterConfig; class PageEditorData { @@ -47,6 +49,7 @@ class PageEditorData $isDraftRevision = false; $this->warnings = []; $editActivity = new PageEditActivity($page); + $lastEditorId = $page->updated_by ?? user()->id; if ($editActivity->hasActiveEditing()) { $this->warnings[] = $editActivity->activeEditingMessage(); @@ -58,11 +61,20 @@ class PageEditorData $page->forceFill($userDraft->only(['name', 'html', 'markdown'])); $isDraftRevision = true; $this->warnings[] = $editActivity->getEditingActiveDraftMessage($userDraft); + $lastEditorId = $userDraft->created_by; } + // Get editor type and handle changes $editorType = $this->getEditorType($page); $this->updateContentForEditor($page, $editorType); + // Filter HTML content if required + if ($editorType->isHtmlBased() && !old('html') && $lastEditorId !== user()->id) { + $filterConfig = HtmlContentFilterConfig::fromConfigString(config('app.content_filtering')); + $filter = new HtmlContentFilter($filterConfig); + $page->html = $filter->filterString($page->html); + } + return [ 'page' => $page, 'book' => $page->book, diff --git a/tests/Entity/PageEditorTest.php b/tests/Entity/PageEditorTest.php index d98b1f998..4cd3c1671 100644 --- a/tests/Entity/PageEditorTest.php +++ b/tests/Entity/PageEditorTest.php @@ -265,4 +265,21 @@ class PageEditorTest extends TestCase $this->assertEquals($test['expected'], $page->refresh()->editor, "Failed asserting global editor {$test['setting']} with request editor {$test['request']} results in {$test['expected']} set for the page"); } } + + public function test_editor_html_content_is_filtered_if_loaded_by_a_different_user() + { + $editor = $this->users->editor(); + $page = $this->entities->page(); + $page->html = ''; + $page->updated_by = $editor->id; + $page->save(); + + $resp = $this->asAdmin()->get($page->getUrl('edit')); + $resp->assertOk(); + $resp->assertDontSee('hellotherethisisaturtlemonster', false); + + $resp = $this->asAdmin()->get("/ajax/page/{$page->id}"); + $resp->assertOk(); + $resp->assertDontSee('hellotherethisisaturtlemonster', false); + } }