Skip to content

Commit 54830ed

Browse files
authored
[5.x] Set the proper CSP headers for multi-domain iframe (#11447)
1 parent c66f9f7 commit 54830ed

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

src/Tokens/Handlers/LivePreview.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
use Closure;
66
use Facades\Statamic\CP\LivePreview as Facade;
7+
use Illuminate\Support\Collection;
78
use Statamic\Contracts\Tokens\Token;
9+
use Statamic\Facades\Site as Sites;
10+
use Statamic\Sites\Site;
811

912
class LivePreview
1013
{
@@ -16,8 +19,26 @@ public function handle(Token $token, $request, Closure $next)
1619

1720
$response = $next($request);
1821

22+
if (Sites::multiEnabled()) {
23+
/** @var Collection */
24+
$siteURLs = Sites::all()
25+
->map(fn (Site $site) => $this->getSchemeAndHost($site))
26+
->values()
27+
->unique()
28+
->join(' ');
29+
30+
$response->headers->set('Content-Security-Policy', "frame-ancestors $siteURLs");
31+
}
32+
1933
$response->headers->set('X-Statamic-Live-Preview', true);
2034

2135
return $response;
2236
}
37+
38+
private function getSchemeAndHost(Site $site): string
39+
{
40+
$parts = parse_url($site->absoluteUrl());
41+
42+
return $parts['scheme'].'://'.$parts['host'];
43+
}
2344
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace Tests\Feature\Entries;
4+
5+
use Facades\Statamic\CP\LivePreview;
6+
use Facades\Tests\Factories\EntryFactory;
7+
use Illuminate\Support\Facades\Route;
8+
use PHPUnit\Framework\Attributes\Test;
9+
use Statamic\Facades\Entry;
10+
use Statamic\View\View;
11+
use Tests\FakesViews;
12+
use Tests\PreventSavingStacheItemsToDisk;
13+
use Tests\TestCase;
14+
15+
class AddsHeadersToLivePreviewTest extends TestCase
16+
{
17+
use FakesViews;
18+
use PreventSavingStacheItemsToDisk;
19+
20+
protected function setUp(): void
21+
{
22+
parent::setUp();
23+
24+
// The array driver would store entry instances in memory, and we could get false-positive
25+
// tests by just modifying the entry without actually performing the substitution.
26+
config(['cache.default' => 'file']);
27+
28+
EntryFactory::collection('test')->id('1')->slug('alfa')->data(['title' => 'Alfa', 'foo' => 'Alfa foo'])->create();
29+
30+
$this->withFakeViews();
31+
32+
$this->viewShouldReturnRaw('test', '');
33+
}
34+
35+
protected function resolveApplicationConfiguration($app)
36+
{
37+
parent::resolveApplicationConfiguration($app);
38+
39+
// Use our View::make() to make sure the Cascade is used.
40+
// We'd use Route::statamic() but it isn't available at this point.
41+
Route::get('/test', fn () => View::make('test'))->middleware('statamic.web');
42+
}
43+
44+
#[Test]
45+
public function it_doesnt_set_header_when_single_site()
46+
{
47+
$this->setSites(['en' => ['url' => 'http://localhost/', 'locale' => 'en']]);
48+
$substitute = EntryFactory::collection('test')->id('2')->slug('charlie')->data(['title' => 'Substituted title', 'foo' => 'Substituted foo'])->make();
49+
50+
LivePreview::tokenize('test-token', $substitute);
51+
52+
$this->get('/test?token=test-token')
53+
->assertHeader('X-Statamic-Live-Preview', true)
54+
->assertHeaderMissing('Content-Security-Policy', true);
55+
}
56+
57+
#[Test]
58+
public function it_sets_header_when_multisite()
59+
{
60+
config()->set('statamic.system.multisite', true);
61+
$this->setSites([
62+
'en' => ['url' => 'http://localhost/', 'locale' => 'en'],
63+
'fr' => ['url' => 'http://localhost/fr/', 'locale' => 'fr'],
64+
'third' => ['url' => 'http://third/', 'locale' => 'en'],
65+
]);
66+
$substitute = EntryFactory::collection('test')->id('2')->slug('charlie')->data(['title' => 'Substituted title', 'foo' => 'Substituted foo'])->make();
67+
68+
LivePreview::tokenize('test-token', $substitute);
69+
70+
$this->get('/test?token=test-token')
71+
->assertHeader('X-Statamic-Live-Preview', true)
72+
->assertHeader('Content-Security-Policy', 'frame-ancestors http://localhost http://third');
73+
}
74+
}

0 commit comments

Comments
 (0)