Skip to content

Commit 8f513a5

Browse files
committed
fix: Use full page URL for preview token
Allows to generate preview tokens for external preview URLs. See reasoning in #7240 (comment) and following comments. Fixes #7240
1 parent 1190227 commit 8f513a5

File tree

3 files changed

+54
-65
lines changed

3 files changed

+54
-65
lines changed

src/Content/Version.php

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use Kirby\Exception\NotFoundException;
1212
use Kirby\Form\Fields;
1313
use Kirby\Http\Uri;
14-
use Kirby\Toolkit\Str;
1514

1615
/**
1716
* The Version class handles all actions for a single
@@ -415,37 +414,23 @@ public function previewToken(): string
415414
throw new LogicException('Invalid model type');
416415
}
417416

418-
return $this->previewTokenFromUrl($this->model->url())
419-
?? throw new LogicException('Cannot produce local preview token for model');
417+
return $this->previewTokenFromUrl($this->model->url());
420418
}
421419

422420
/**
423421
* Returns a verification token for the authentication
424422
* of draft and version previews from a raw URL
425-
* if the URL comes from the same site
426423
*/
427-
protected function previewTokenFromUrl(string $url): string|null
424+
protected function previewTokenFromUrl(string $url): string
428425
{
429-
$localPrefix = $this->model->kirby()->url('base') . '/';
430-
431-
// normalize homepage URLs to have a trailing slash
432-
// to make the following logic work with those as well
433-
if ($url . '/' === $localPrefix) {
434-
$url .= '/';
435-
}
436-
437-
if (Str::startsWith($url, $localPrefix) === false) {
438-
return null;
439-
}
440-
441426
// get rid of all modifiers after the path
442427
$uri = new Uri($url);
443428
$uri->fragment = null;
444429
$uri->params = null;
445430
$uri->query = null;
446431

447432
$data = [
448-
'uri' => Str::after($uri->toString(), $localPrefix),
433+
'url' => $uri->toString(),
449434
'versionId' => $this->id->value()
450435
];
451436

tests/Cms/Page/PagePreviewUrlTest.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ public static function providerForBlueprintSettings(): array
1414
{
1515
return [
1616
[null, '/test', null, false],
17-
[null, '/test?{token}', 'test', true],
17+
[null, '/test?{token}', '/test', true],
1818
[true, '/test', null, false],
19-
[true, '/test?{token}', 'test', true],
19+
[true, '/test?{token}', '/test', true],
2020
['/something/different', '/something/different', null, false],
21-
['/something/different', '/something/different?{token}', 'something/different', true],
21+
['/something/different', '/something/different?{token}', '/something/different', true],
2222
['{{ site.url }}#{{ page.slug }}', '/#test', null, false],
23-
['{{ site.url }}#{{ page.slug }}', '/?{token}#test', '', true],
24-
['{{ page.url }}?preview=true', '/test?preview=true&{token}', 'test', true],
23+
['{{ site.url }}#{{ page.slug }}', '/?{token}#test', '/', true],
24+
['{{ page.url }}?preview=true', '/test?preview=true&{token}', '/test', true],
2525
[false, null, null, false],
2626
[false, null, null, true],
2727
[null, null, null, false, false],
@@ -41,7 +41,7 @@ public function testPreviewUrl(): void
4141
public function testPreviewUrlWithBlueprintSettings(
4242
$input,
4343
$expected,
44-
$expectedUri,
44+
$expectedUrl,
4545
bool $draft,
4646
bool $authenticated = true
4747
): void {
@@ -85,7 +85,7 @@ public function testPreviewUrlWithBlueprintSettings(
8585
]);
8686

8787
if ($draft === true && $expected !== null) {
88-
$expectedToken = substr(hash_hmac('sha1', '{"uri":"' . $expectedUri . '","versionId":"latest"}', $page->kirby()->root('content')), 0, 10);
88+
$expectedToken = substr(hash_hmac('sha1', '{"url":"' . $expectedUrl . '","versionId":"latest"}', $page->kirby()->root('content')), 0, 10);
8989
$expected = str_replace(
9090
'{token}',
9191
'_token=' . $expectedToken,

tests/Content/VersionTest.php

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -788,28 +788,31 @@ public function testPreviewToken(string $indexUrl)
788788
]
789789
]);
790790

791+
$siteUrl = $this->app->url();
792+
$pageUrl = $this->app->page('a-page')->url();
793+
791794
// site
792795
$version = new Version(
793796
model: $this->app->site(),
794797
id: VersionId::latest()
795798
);
796-
$expected = substr(hash_hmac('sha1', '{"uri":"","versionId":"latest"}', static::TMP . '/content'), 0, 10);
799+
$expected = substr(hash_hmac('sha1', '{"url":"' . $siteUrl . '","versionId":"latest"}', static::TMP . '/content'), 0, 10);
797800
$this->assertSame($expected, $version->previewToken());
798801

799802
// homepage
800803
$version = new Version(
801804
model: $this->app->site()->page('home'),
802805
id: VersionId::latest()
803806
);
804-
$expected = substr(hash_hmac('sha1', '{"uri":"","versionId":"latest"}', static::TMP . '/content'), 0, 10);
807+
$expected = substr(hash_hmac('sha1', '{"url":"' . $siteUrl . '","versionId":"latest"}', static::TMP . '/content'), 0, 10);
805808
$this->assertSame($expected, $version->previewToken());
806809

807810
// another page
808811
$version = new Version(
809812
model: $this->model,
810813
id: VersionId::latest()
811814
);
812-
$expected = substr(hash_hmac('sha1', '{"uri":"a-page","versionId":"latest"}', static::TMP . '/content'), 0, 10);
815+
$expected = substr(hash_hmac('sha1', '{"url":"' . $pageUrl . '","versionId":"latest"}', static::TMP . '/content'), 0, 10);
813816
$this->assertSame($expected, $version->previewToken());
814817
}
815818

@@ -830,7 +833,7 @@ public function testPreviewTokenCustomSalt()
830833
id: VersionId::latest()
831834
);
832835

833-
$expected = substr(hash_hmac('sha1', '{"uri":"a-page","versionId":"latest"}', 'testsalt'), 0, 10);
836+
$expected = substr(hash_hmac('sha1', '{"url":"/a-page","versionId":"latest"}', 'testsalt'), 0, 10);
834837
$this->assertSame($expected, $version->previewToken());
835838
}
836839

@@ -855,7 +858,7 @@ public function testPreviewTokenCustomSaltCallback()
855858
id: VersionId::latest()
856859
);
857860

858-
$expected = substr(hash_hmac('sha1', '{"uri":"a-page","versionId":"latest"}', 'salt-lake-city'), 0, 10);
861+
$expected = substr(hash_hmac('sha1', '{"url":"/a-page","versionId":"latest"}', 'salt-lake-city'), 0, 10);
859862
$this->assertSame($expected, $version->previewToken());
860863
}
861864

@@ -1519,38 +1522,38 @@ public static function pageUrlProvider(): array
15191522
return [
15201523
// latest version
15211524
[null, '/test', null, false, 'latest'],
1522-
[null, '/test?{token}', 'test', true, 'latest'],
1525+
[null, '/test?{token}', '/test', true, 'latest'],
15231526
[true, '/test', null, false, 'latest'],
1524-
[true, '/test?{token}', 'test', true, 'latest'],
1527+
[true, '/test?{token}', '/test', true, 'latest'],
15251528
['https://test.com', 'https://test.com', null, false, 'latest'],
1526-
['https://test.com', 'https://test.com', null, true, 'latest'],
1527-
['/something/different', '/something/different', 'something/different', false, 'latest'],
1528-
['/something/different', '/something/different?{token}', 'something/different', true, 'latest'],
1529+
['https://test.com', 'https://test.com?{token}', 'https://test.com', true, 'latest'],
1530+
['/something/different', '/something/different', '/something/different', false, 'latest'],
1531+
['/something/different', '/something/different?{token}', '/something/different', true, 'latest'],
15291532
['{{ site.url }}#{{ page.slug }}', '/#test', null, false, 'latest'],
1530-
['{{ site.url }}#{{ page.slug }}', '/?{token}#test', '', true, 'latest'],
1533+
['{{ site.url }}#{{ page.slug }}', '/?{token}#test', '/', true, 'latest'],
15311534
['{{ page.url }}?preview=true', '/test?preview=true', null, false, 'latest'],
1532-
['{{ page.url }}?preview=true', '/test?preview=true&{token}', 'test', true, 'latest'],
1535+
['{{ page.url }}?preview=true', '/test?preview=true&{token}', '/test', true, 'latest'],
15331536
['{{ page.url }}/param:something', '/test/param:something', null, false, 'latest'],
1534-
['{{ page.url }}/param:something', '/test/param:something?{token}', 'test', true, 'latest'],
1537+
['{{ page.url }}/param:something', '/test/param:something?{token}', '/test', true, 'latest'],
15351538
[false, null, null, false, 'latest'],
15361539
[false, null, null, true, 'latest'],
15371540
[null, null, null, false, 'latest', false],
15381541

15391542
// changes version
1540-
[null, '/test?{token}&_version=changes', 'test', false, 'changes'],
1541-
[null, '/test?{token}&_version=changes', 'test', true, 'changes'],
1542-
[true, '/test?{token}&_version=changes', 'test', false, 'changes'],
1543-
[true, '/test?{token}&_version=changes', 'test', true, 'changes'],
1544-
['https://test.com', 'https://test.com', null, false, 'changes'],
1545-
['https://test.com', 'https://test.com', null, true, 'changes'],
1546-
['/something/different', '/something/different?{token}&_version=changes', 'something/different', false, 'changes'],
1547-
['/something/different', '/something/different?{token}&_version=changes', 'something/different', true, 'changes'],
1548-
['{{ site.url }}#{{ page.slug }}', '/?{token}&_version=changes#test', '', false, 'changes'],
1549-
['{{ site.url }}#{{ page.slug }}', '/?{token}&_version=changes#test', '', true, 'changes'],
1550-
['{{ page.url }}?preview=true', '/test?preview=true&{token}&_version=changes', 'test', false, 'changes'],
1551-
['{{ page.url }}?preview=true', '/test?preview=true&{token}&_version=changes', 'test', true, 'changes'],
1552-
['{{ page.url }}/param:something', '/test/param:something?{token}&_version=changes', 'test', false, 'changes'],
1553-
['{{ page.url }}/param:something', '/test/param:something?{token}&_version=changes', 'test', true, 'changes'],
1543+
[null, '/test?{token}&_version=changes', '/test', false, 'changes'],
1544+
[null, '/test?{token}&_version=changes', '/test', true, 'changes'],
1545+
[true, '/test?{token}&_version=changes', '/test', false, 'changes'],
1546+
[true, '/test?{token}&_version=changes', '/test', true, 'changes'],
1547+
['https://test.com', 'https://test.com?{token}&_version=changes', 'https://test.com', false, 'changes'],
1548+
['https://test.com', 'https://test.com?{token}&_version=changes', 'https://test.com', true, 'changes'],
1549+
['/something/different', '/something/different?{token}&_version=changes', '/something/different', false, 'changes'],
1550+
['/something/different', '/something/different?{token}&_version=changes', '/something/different', true, 'changes'],
1551+
['{{ site.url }}#{{ page.slug }}', '/?{token}&_version=changes#test', '/', false, 'changes'],
1552+
['{{ site.url }}#{{ page.slug }}', '/?{token}&_version=changes#test', '/', true, 'changes'],
1553+
['{{ page.url }}?preview=true', '/test?preview=true&{token}&_version=changes', '/test', false, 'changes'],
1554+
['{{ page.url }}?preview=true', '/test?preview=true&{token}&_version=changes', '/test', true, 'changes'],
1555+
['{{ page.url }}/param:something', '/test/param:something?{token}&_version=changes', '/test', false, 'changes'],
1556+
['{{ page.url }}/param:something', '/test/param:something?{token}&_version=changes', '/test', true, 'changes'],
15541557
[false, null, null, false, 'changes'],
15551558
[false, null, null, true, 'changes'],
15561559
[null, null, null, false, 'changes', false],
@@ -1561,7 +1564,7 @@ public static function pageUrlProvider(): array
15611564
public function testUrlPageCustom(
15621565
$input,
15631566
$expected,
1564-
$expectedUri,
1567+
$expectedUrl,
15651568
bool $draft,
15661569
string $versionId,
15671570
bool $authenticated = true
@@ -1610,7 +1613,7 @@ public function testUrlPageCustom(
16101613
$expectedToken = substr(
16111614
hash_hmac(
16121615
'sha1',
1613-
'{"uri":"' . $expectedUri . '","versionId":"' . $versionId . '"}',
1616+
'{"url":"' . $expectedUrl . '","versionId":"' . $versionId . '"}',
16141617
$page->kirby()->root('content')
16151618
),
16161619
0,
@@ -1662,25 +1665,26 @@ public static function siteUrlProvider(): array
16621665
{
16631666
return [
16641667
// latest version
1665-
[null, '/', 'latest'],
1666-
['https://test.com', 'https://test.com', 'latest'],
1667-
['{{ site.url }}#test', '/#test', 'latest'],
1668-
[false, null, 'latest'],
1669-
[null, null, 'latest', false],
1668+
[null, '/', '/', 'latest'],
1669+
['https://test.com', 'https://test.com', 'https://test.com', 'latest'],
1670+
['{{ site.url }}#test', '/#test', '/', 'latest'],
1671+
[false, null, null, 'latest'],
1672+
[null, null, null, 'latest', false],
16701673

16711674
// changes version
1672-
[null, '/?{token}&_version=changes', 'changes'],
1673-
['https://test.com', 'https://test.com', 'changes'],
1674-
['{{ site.url }}#test', '/?{token}&_version=changes#test', 'changes'],
1675-
[false, null, 'changes'],
1676-
[null, null, 'changes', false],
1675+
[null, '/?{token}&_version=changes', '/', 'changes'],
1676+
['https://test.com', 'https://test.com?{token}&_version=changes', 'https://test.com', 'changes'],
1677+
['{{ site.url }}#test', '/?{token}&_version=changes#test', '/', 'changes'],
1678+
[false, null, null, 'changes'],
1679+
[null, null, null, 'changes', false],
16771680
];
16781681
}
16791682

16801683
#[DataProvider('siteUrlProvider')]
16811684
public function testUrlSiteCustom(
16821685
$input,
16831686
$expected,
1687+
$expectedUrl,
16841688
string $versionId,
16851689
bool $authenticated = true
16861690
): void {
@@ -1727,7 +1731,7 @@ public function testUrlSiteCustom(
17271731
$expectedToken = substr(
17281732
hash_hmac(
17291733
'sha1',
1730-
'{"uri":"","versionId":"' . $versionId . '"}',
1734+
'{"url":"' . $expectedUrl . '","versionId":"' . $versionId . '"}',
17311735
$site->kirby()->root('content')
17321736
),
17331737
0,

0 commit comments

Comments
 (0)