@amazeelabs/silverback-preview-link 1.6.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/drupal/silverback_preview_link/CHANGELOG.md +195 -0
  3. package/drupal/silverback_preview_link/README.md +30 -0
  4. package/drupal/silverback_preview_link/composer.json +13 -0
  5. package/drupal/silverback_preview_link/config/install/silverback_preview_link.settings.yml +3 -0
  6. package/drupal/silverback_preview_link/config/schema/silverback_preview_link.schema.yml +14 -0
  7. package/drupal/silverback_preview_link/css/modal.css +17 -0
  8. package/drupal/silverback_preview_link/js/copy.js +39 -0
  9. package/drupal/silverback_preview_link/silverback_preview_link.info.yml +12 -0
  10. package/drupal/silverback_preview_link/silverback_preview_link.install +6 -0
  11. package/drupal/silverback_preview_link/silverback_preview_link.libraries.yml +9 -0
  12. package/drupal/silverback_preview_link/silverback_preview_link.links.menu.yml +5 -0
  13. package/drupal/silverback_preview_link/silverback_preview_link.module +79 -0
  14. package/drupal/silverback_preview_link/silverback_preview_link.permissions.yml +9 -0
  15. package/drupal/silverback_preview_link/silverback_preview_link.routing.yml +40 -0
  16. package/drupal/silverback_preview_link/silverback_preview_link.services.yml +31 -0
  17. package/drupal/silverback_preview_link/src/Access/PreviewEnabledAccessCheck.php +80 -0
  18. package/drupal/silverback_preview_link/src/Access/PreviewLinkAccessCheck.php +49 -0
  19. package/drupal/silverback_preview_link/src/Authentication/Provider/PreviewToken.php +118 -0
  20. package/drupal/silverback_preview_link/src/Controller/PreviewController.php +83 -0
  21. package/drupal/silverback_preview_link/src/Entity/SilverbackPreviewLink.php +224 -0
  22. package/drupal/silverback_preview_link/src/Entity/SilverbackPreviewLinkInterface.php +110 -0
  23. package/drupal/silverback_preview_link/src/Form/PreviewLinkForm.php +320 -0
  24. package/drupal/silverback_preview_link/src/Form/SettingsForm.php +204 -0
  25. package/drupal/silverback_preview_link/src/Plugin/EntityReferenceSelection/SilverbackPreviewLinkSelection.php +25 -0
  26. package/drupal/silverback_preview_link/src/Plugin/Field/FieldWidget/PreviewLinkEntitiesWidget.php +103 -0
  27. package/drupal/silverback_preview_link/src/Plugin/Validation/Constraint/SilverbackPreviewLinkEntitiesUniqueConstraint.php +26 -0
  28. package/drupal/silverback_preview_link/src/Plugin/Validation/Constraint/SilverbackPreviewLinkEntitiesUniqueConstraintValidator.php +44 -0
  29. package/drupal/silverback_preview_link/src/PreviewLinkExpiry.php +55 -0
  30. package/drupal/silverback_preview_link/src/PreviewLinkHooks.php +61 -0
  31. package/drupal/silverback_preview_link/src/PreviewLinkHost.php +70 -0
  32. package/drupal/silverback_preview_link/src/PreviewLinkHostInterface.php +49 -0
  33. package/drupal/silverback_preview_link/src/PreviewLinkStorage.php +99 -0
  34. package/drupal/silverback_preview_link/src/PreviewLinkStorageInterface.php +19 -0
  35. package/drupal/silverback_preview_link/src/PreviewLinkUtility.php +27 -0
  36. package/drupal/silverback_preview_link/src/QRCodeWithLogo.php +84 -0
  37. package/drupal/silverback_preview_link/src/QRMarkupSVGWithLogo.php +51 -0
  38. package/drupal/silverback_preview_link/src/Routing/PreviewLinkRouteProvider.php +61 -0
  39. package/drupal/silverback_preview_link/src/images/amazee-labs_logo-square-green.svg +13 -0
  40. package/drupal/silverback_preview_link/templates/preview-link.html.twig +39 -0
  41. package/package.json +13 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## 1.6.15 (2026-01-22)
7
+
8
+ **Note:** Version bump only for package @amazeelabs/silverback-preview-link
@@ -0,0 +1,195 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [1.6.14](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.13...@-amazeelabs/silverback_preview_link@1.6.14) (2025-09-09)
7
+
8
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
9
+
10
+
11
+
12
+
13
+
14
+ ## [1.6.13](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.12...@-amazeelabs/silverback_preview_link@1.6.13) (2025-08-21)
15
+
16
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
17
+
18
+
19
+
20
+
21
+
22
+ ## [1.6.12](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.11...@-amazeelabs/silverback_preview_link@1.6.12) (2025-05-14)
23
+
24
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
25
+
26
+
27
+
28
+
29
+
30
+ ## [1.6.11](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.10...@-amazeelabs/silverback_preview_link@1.6.11) (2025-05-12)
31
+
32
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
33
+
34
+
35
+
36
+
37
+
38
+ ## [1.6.10](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.9...@-amazeelabs/silverback_preview_link@1.6.10) (2025-05-06)
39
+
40
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
41
+
42
+
43
+
44
+
45
+
46
+ ## [1.6.9](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.8...@-amazeelabs/silverback_preview_link@1.6.9) (2025-04-09)
47
+
48
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
49
+
50
+
51
+
52
+
53
+
54
+ ## [1.6.8](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.7...@-amazeelabs/silverback_preview_link@1.6.8) (2025-03-18)
55
+
56
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
57
+
58
+
59
+
60
+
61
+
62
+ ## [1.6.7](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.6...@-amazeelabs/silverback_preview_link@1.6.7) (2025-03-10)
63
+
64
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
65
+
66
+
67
+
68
+
69
+
70
+ ## [1.6.6](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.5...@-amazeelabs/silverback_preview_link@1.6.6) (2025-03-09)
71
+
72
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
73
+
74
+
75
+
76
+
77
+
78
+ ## [1.6.5](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.4...@-amazeelabs/silverback_preview_link@1.6.5) (2025-01-27)
79
+
80
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
81
+
82
+
83
+
84
+
85
+
86
+ ## [1.6.4](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.3...@-amazeelabs/silverback_preview_link@1.6.4) (2024-08-20)
87
+
88
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
89
+
90
+
91
+
92
+
93
+
94
+ ## [1.6.3](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.2...@-amazeelabs/silverback_preview_link@1.6.3) (2024-08-15)
95
+
96
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
97
+
98
+
99
+
100
+
101
+
102
+ ## [1.6.2](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.1...@-amazeelabs/silverback_preview_link@1.6.2) (2024-08-14)
103
+
104
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
105
+
106
+
107
+
108
+
109
+
110
+ ## [1.6.1](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.0...@-amazeelabs/silverback_preview_link@1.6.1) (2024-08-14)
111
+
112
+
113
+ ### Bug Fixes
114
+
115
+ * **SLB-458:** branded preview link qr ([#1566](https://github.com/AmazeeLabs/silverback-mono/issues/1566)) ([f2585b6](https://github.com/AmazeeLabs/silverback-mono/commit/f2585b65a5166303a45d12249b5bbd0f5769dc53))
116
+
117
+
118
+
119
+
120
+
121
+ # [1.6.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.5.0...@-amazeelabs/silverback_preview_link@1.6.0) (2024-08-14)
122
+
123
+
124
+ ### Features
125
+
126
+ * **SLB-458:** branded preview qr ([#1565](https://github.com/AmazeeLabs/silverback-mono/issues/1565)) ([2330e1f](https://github.com/AmazeeLabs/silverback-mono/commit/2330e1f467e70f1508904e2d7c1778b6cdd43b73))
127
+
128
+
129
+
130
+
131
+
132
+ # [1.5.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.4.0...@-amazeelabs/silverback_preview_link@1.5.0) (2024-07-27)
133
+
134
+
135
+ ### Features
136
+
137
+ * **SLB-416:** re-remove branded qr code ([9f8518e](https://github.com/AmazeeLabs/silverback-mono/commit/9f8518e960a0ca93dab00430a1b059afb0478964))
138
+
139
+
140
+
141
+
142
+
143
+ # [1.4.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.3.0...@-amazeelabs/silverback_preview_link@1.4.0) (2024-07-27)
144
+
145
+
146
+ ### Features
147
+
148
+ * **SLB-416:** re-add branded qr code ([4efc4de](https://github.com/AmazeeLabs/silverback-mono/commit/4efc4de944de9f9fdf993eb723e8eed7d1b70400))
149
+
150
+
151
+
152
+
153
+
154
+ # [1.3.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.2.0...@-amazeelabs/silverback_preview_link@1.3.0) (2024-07-27)
155
+
156
+
157
+ ### Features
158
+
159
+ * **SLB-416:** revert branded qr code ([f941c81](https://github.com/AmazeeLabs/silverback-mono/commit/f941c819bc6013ef11cf2cfcfd5c05bcb7ebdb7c))
160
+
161
+
162
+
163
+
164
+
165
+ # [1.2.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.1.1...@-amazeelabs/silverback_preview_link@1.2.0) (2024-07-24)
166
+
167
+
168
+ ### Features
169
+
170
+ * **SLB-416:** branded QR ([399b102](https://github.com/AmazeeLabs/silverback-mono/commit/399b102728179e9330f6cec403643439cd6a77e9))
171
+ * **SLB-416:** copy preview link, refactor form ([3888116](https://github.com/AmazeeLabs/silverback-mono/commit/3888116ec334d6f01c1541e23187134f00ba9546))
172
+
173
+
174
+
175
+
176
+
177
+ ## [1.1.1](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.1.0...@-amazeelabs/silverback_preview_link@1.1.1) (2024-07-12)
178
+
179
+ **Note:** Version bump only for package @-amazeelabs/silverback_preview_link
180
+
181
+
182
+
183
+
184
+
185
+ # 1.1.0 (2024-07-12)
186
+
187
+
188
+ ### Bug Fixes
189
+
190
+ * **SLB-416:** remove drupal namespace ([#1548](https://github.com/AmazeeLabs/silverback-mono/issues/1548)) ([52b7fec](https://github.com/AmazeeLabs/silverback-mono/commit/52b7fec31a7b99ce9c409aa5943a90861988d467))
191
+
192
+
193
+ ### Features
194
+
195
+ * **SLB-416:** preview link ([#1542](https://github.com/AmazeeLabs/silverback-mono/issues/1542)) ([bd9d312](https://github.com/AmazeeLabs/silverback-mono/commit/bd9d31276d0ffb4da45cbe475ec03386d66cc722)), closes [#1547](https://github.com/AmazeeLabs/silverback-mono/issues/1547)
@@ -0,0 +1,30 @@
1
+ # Silverback Preview Link
2
+
3
+ Decoupled shareable preview with access token. Integrates with Silverback
4
+ autosave.
5
+
6
+ This module is inspired by
7
+ [Preview Link](https://www.drupal.org/project/preview_link) but does not depend
8
+ on it as the use case is different.
9
+
10
+ This module
11
+
12
+ - is suitable for a decoupled setup
13
+ - handles access based on GraphQL
14
+ - uses silverback_autosave to share instant preview updates
15
+ - integrates with the Gutenberg editor
16
+
17
+ Due to the decoupled nature, it does not cover additional logic brought by the
18
+ Preview Link module:
19
+
20
+ - Most of the route subscribers
21
+ - Entity canonical access control handlers
22
+ - Route provider and Controller for preview links
23
+ - Event subscribers for node canonical redirect
24
+ - ...
25
+
26
+ ## Configuration
27
+
28
+ - Enable entity types and bundles
29
+ `/admin/config/content/silverback_preview_link`
30
+ - Optionally change the default expiry time that is set to 1 day
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "amazeelabs/silverback_preview_link",
3
+ "type": "drupal-module",
4
+ "version": "dev-main",
5
+ "description": "Decoupled preview with access token.",
6
+ "homepage": "https://silverback.netlify.app",
7
+ "license": "GPL-2.0+",
8
+ "require": {
9
+ "php": ">=8.3",
10
+ "drupal/dynamic_entity_reference": "^3 || ^4",
11
+ "chillerlan/php-qrcode": "^5"
12
+ }
13
+ }
@@ -0,0 +1,3 @@
1
+ enabled_entity_types: {}
2
+ expiry_seconds: 86400
3
+ multiple_entities: false
@@ -0,0 +1,14 @@
1
+ silverback_preview_link.settings:
2
+ type: config_object
3
+ mapping:
4
+ enabled_entity_types:
5
+ type: sequence
6
+ sequence:
7
+ type: sequence
8
+ sequence:
9
+ type: string
10
+ expiry_seconds:
11
+ type: integer
12
+ multiple_entities:
13
+ label: Whether Preview Links can reference multiple entities.
14
+ type: boolean
@@ -0,0 +1,17 @@
1
+ .preview-link .preview-link__copy,
2
+ .preview-link p {
3
+ margin: 0;
4
+ }
5
+
6
+ .silverback-preview-link-entity-form .messages__header {
7
+ display: none;
8
+ }
9
+
10
+ .silverback-preview-link-entity-form .messages-list {
11
+ margin-block: 0;
12
+ }
13
+
14
+ .silverback-preview-link-entity-form .messages {
15
+ padding-block: 8px;
16
+ padding-inline: 0;
17
+ }
@@ -0,0 +1,39 @@
1
+ (function (Drupal) {
2
+ Drupal.behaviors.previewLinkCopyToClipBoard = {
3
+ attach: function (context) {
4
+ const copyText = document.querySelector('.preview-link__copy .form-text');
5
+ const copyButton = document.querySelector('.preview-link__copy button');
6
+
7
+ if (!copyText || !copyButton) {
8
+ return;
9
+ }
10
+
11
+ const setSuccessMessage = () => {
12
+ const originalLabel = copyButton.textContent;
13
+ const copySuccessLabel = Drupal.t('Copied ✨');
14
+ copyButton.textContent = copySuccessLabel;
15
+ setTimeout(() => {
16
+ copyButton.textContent = originalLabel;
17
+ }, 2000);
18
+ };
19
+ // Fallback for browsers that don't support navigator.clipboard.
20
+ let copy = () => {
21
+ copyText.select();
22
+ document.execCommand('copy');
23
+ setSuccessMessage();
24
+ };
25
+ if (navigator.clipboard) {
26
+ copy = () => {
27
+ navigator.clipboard.writeText(copyText.value).then(
28
+ () => setSuccessMessage(),
29
+ (err) => console.log('Error: ' + err),
30
+ );
31
+ };
32
+ }
33
+ copyButton.addEventListener('click', (event) => {
34
+ event.preventDefault();
35
+ copy();
36
+ });
37
+ },
38
+ };
39
+ })(Drupal);
@@ -0,0 +1,12 @@
1
+ name: 'Silverback Preview Link'
2
+ type: module
3
+ description:
4
+ 'Decoupled preview with access token. Integrates with Silverback autosave.'
5
+ package: Silverback
6
+ configure: silverback_preview_link.settings
7
+ core_version_requirement: ^10 || ^11
8
+ dependencies:
9
+ - dynamic_entity_reference:dynamic_entity_reference
10
+ - silverback_autosave:silverback_autosave
11
+ - silverback_gatsby:silverback_gatsby
12
+ - silverback_external_preview:silverback_external_preview
@@ -0,0 +1,6 @@
1
+ <?php
2
+
3
+ /**
4
+ * @file
5
+ * Install, update and uninstall functions for the Silverback Preview Link module.
6
+ */
@@ -0,0 +1,9 @@
1
+ copy:
2
+ version: VERSION
3
+ js:
4
+ js/copy.js: {}
5
+ modal:
6
+ version: VERSION
7
+ css:
8
+ theme:
9
+ css/modal.css: {}
@@ -0,0 +1,5 @@
1
+ silverback_preview_link.settings:
2
+ route_name: silverback_preview_link.settings
3
+ parent: system.admin_config_content
4
+ title: Silverback Preview Link
5
+ description: 'Manage preview link settings.'
@@ -0,0 +1,79 @@
1
+ <?php
2
+
3
+ use Drupal\Core\Access\AccessResult;
4
+ use Drupal\Core\Access\AccessResultInterface;
5
+ use Drupal\Core\Field\FieldDefinitionInterface;
6
+ use Drupal\Core\Field\FieldItemListInterface;
7
+ use Drupal\Core\Session\AccountInterface;
8
+ use Drupal\silverback_preview_link\PreviewLinkHooks;
9
+ use Drupal\silverback_preview_link\PreviewLinkUtility;
10
+ use Drupal\silverback_preview_link\Routing\PreviewLinkRouteProvider;
11
+
12
+ /**
13
+ * Implements hook_entity_type_alter().
14
+ */
15
+ function silverback_preview_link_entity_type_alter(array &$entity_types): void {
16
+ $supported_entity_types = array_filter(
17
+ $entity_types,
18
+ [PreviewLinkUtility::class, 'isEntityTypeSupported'],
19
+ );
20
+
21
+ /** @var \Drupal\Core\Entity\ContentEntityType $type */
22
+ foreach ($supported_entity_types as $type) {
23
+ $providers = $type->getRouteProviderClasses() ?: [];
24
+ if (count($providers['silverback_preview_link'] ?? []) === 0) {
25
+ $providers['silverback_preview_link'] = PreviewLinkRouteProvider::class;
26
+ $type->setHandlerClass('route_provider', $providers);
27
+ }
28
+
29
+ if (!$type->hasLinkTemplate('preview-link-generate')) {
30
+ $type->setLinkTemplate('preview-link-generate', $type->getLinkTemplate('canonical') . '/generate-preview-link');
31
+ }
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Implements hook_cron().
37
+ */
38
+ function silverback_preview_link_cron(): void {
39
+ \Drupal::classResolver(PreviewLinkHooks::class)->cron();
40
+ }
41
+
42
+ /**
43
+ * Implements hook_theme().
44
+ */
45
+ function silverback_preview_link_theme(array $existing, string $type, string $theme, string $path): array {
46
+ return [
47
+ 'preview_link' => [
48
+ 'path' => $path . '/templates',
49
+ 'template' => 'preview-link',
50
+ 'variables' => [
51
+ 'title' => NULL,
52
+ 'preview_link_has_expired' => FALSE,
53
+ 'preview_url' => NULL,
54
+ 'preview_qr_code_url' => NULL,
55
+ 'preview_qr_code_fallback' => NULL,
56
+ 'expiry_description' => NULL,
57
+ 'actions_description' => NULL,
58
+ 'display_gif' => FALSE,
59
+ ],
60
+ ],
61
+ ];
62
+ }
63
+
64
+ /**
65
+ * Implements hook_entity_field_access().
66
+ */
67
+ function silverback_preview_link_entity_field_access(string $operation, FieldDefinitionInterface $field_definition, AccountInterface $account, ?FieldItemListInterface $items = NULL): AccessResultInterface {
68
+ $storageDefinition = $field_definition->getFieldStorageDefinition();
69
+ if ($storageDefinition->getTargetEntityTypeId() !== 'silverback_preview_link') {
70
+ return AccessResult::neutral();
71
+ }
72
+
73
+ if ($storageDefinition->getName() === 'entities' && $operation === 'edit') {
74
+ return AccessResult::forbiddenIf(\Drupal::configFactory()->get('silverback_preview_link.settings')->get('multiple_entities') !== TRUE)
75
+ ->addCacheTags(['config:preview_link.settings']);
76
+ }
77
+
78
+ return AccessResult::neutral();
79
+ }
@@ -0,0 +1,9 @@
1
+ administer silverback preview link settings:
2
+ title: 'Administer Silverback preview link settings'
3
+ description: 'Allows the user to administer the preview link settings'
4
+ restrict access: TRUE
5
+
6
+ generate silverback preview links:
7
+ title: 'Generate Silverback preview links'
8
+ description:
9
+ 'Allows the user to generate a preview link for a piece of content'
@@ -0,0 +1,40 @@
1
+ silverback_preview_link.settings:
2
+ path: '/admin/config/content/silverback_preview_link'
3
+ defaults:
4
+ _form: '\Drupal\silverback_preview_link\Form\SettingsForm'
5
+ _title: 'Silverback preview link'
6
+ _description: 'Manage Preview link settings.'
7
+ requirements:
8
+ _permission: 'administer silverback preview link settings'
9
+
10
+ silverback_preview_link.preview.access:
11
+ path: '/preview/access'
12
+ defaults:
13
+ _controller: '\Drupal\silverback_preview_link\Controller\PreviewController::hasAccess'
14
+ methods: [POST]
15
+ requirements:
16
+ # Required for the refresh token.
17
+ _access: 'TRUE'
18
+ _format: 'json'
19
+ options:
20
+ _auth: ['oauth2']
21
+ no_cache: TRUE
22
+
23
+ silverback_preview_link.qr_code:
24
+ path: '/preview/qr-code/{base64_url}'
25
+ defaults:
26
+ _controller: '\Drupal\silverback_preview_link\Controller\PreviewController::getQRCode'
27
+ requirements:
28
+ # Keep it very generic, it's just to prevent anonymous access / bots.
29
+ _permission: 'access administration pages'
30
+
31
+ silverback_preview_link.preview_link.access:
32
+ path: '/preview/link-access'
33
+ defaults:
34
+ _controller: '\Drupal\silverback_preview_link\Controller\PreviewController::hasLinkAccess'
35
+ methods: [POST]
36
+ requirements:
37
+ _access: 'TRUE'
38
+ _format: 'json'
39
+ options:
40
+ no_cache: TRUE
@@ -0,0 +1,31 @@
1
+ services:
2
+ access_check.silverback_preview_link:
3
+ class: Drupal\silverback_preview_link\Access\PreviewLinkAccessCheck
4
+ arguments: ['@silverback_preview_link.host']
5
+ tags:
6
+ - { name: access_check, applies_to: _access_preview_link }
7
+ access_check.preview_enabled:
8
+ class: Drupal\silverback_preview_link\Access\PreviewEnabledAccessCheck
9
+ arguments: ['@config.factory']
10
+ tags:
11
+ - { name: access_check, applies_to: _access_preview_enabled }
12
+ silverback_preview_link.link_expiry:
13
+ class: Drupal\silverback_preview_link\PreviewLinkExpiry
14
+ arguments: ['@config.factory']
15
+ silverback_preview_link.host:
16
+ class: Drupal\silverback_preview_link\PreviewLinkHost
17
+ arguments:
18
+ - '@entity_type.manager'
19
+ - '@datetime.time'
20
+ logger.channel.silverback_preview_link:
21
+ parent: logger.channel_base
22
+ arguments: ['silverback_preview_link']
23
+ silverback_preview_link.authentication.preview_token:
24
+ class: Drupal\silverback_preview_link\Authentication\Provider\PreviewToken
25
+ tags:
26
+ - {
27
+ name: authentication_provider,
28
+ provider_id: 'preview_token',
29
+ priority: -10000,
30
+ global: TRUE,
31
+ }
@@ -0,0 +1,80 @@
1
+ <?php
2
+
3
+ declare(strict_types = 1);
4
+
5
+ namespace Drupal\silverback_preview_link\Access;
6
+
7
+ use Drupal\Core\Access\AccessResult;
8
+ use Drupal\Core\Access\AccessResultInterface;
9
+ use Drupal\Core\Config\ConfigFactoryInterface;
10
+ use Drupal\Core\Config\ImmutableConfig;
11
+ use Drupal\Core\Entity\EntityInterface;
12
+ use Drupal\Core\Routing\Access\AccessInterface;
13
+ use Drupal\Core\Routing\RouteMatchInterface;
14
+ use Symfony\Component\Routing\Route;
15
+
16
+ /**
17
+ * Generate preview link access check.
18
+ */
19
+ class PreviewEnabledAccessCheck implements AccessInterface {
20
+
21
+ protected ImmutableConfig $config;
22
+
23
+ /**
24
+ * PreviewEnabledAccessCheck constructor.
25
+ */
26
+ public function __construct(ConfigFactoryInterface $configFactory) {
27
+ $this->config = $configFactory->get('silverback_preview_link.settings');
28
+ }
29
+
30
+ /**
31
+ * Checks access to both the generate route and the preview route.
32
+ */
33
+ public function access(Route $route, RouteMatchInterface $route_match): AccessResultInterface {
34
+ // Get the entity for both the preview route and the generate preview link
35
+ // route.
36
+ $entity = match($route->getOption('silverback_preview_link.entity_type_id')) {
37
+ NULL => $route_match->getParameter('entity'),
38
+ default => $route_match->getParameter($route->getOption('silverback_preview_link.entity_type_id')),
39
+ };
40
+
41
+ return AccessResult::allowedIf($this->entityTypeAndBundleEnabled($entity))
42
+ ->addCacheableDependency($entity)
43
+ ->addCacheContexts(['route'])
44
+ ->addCacheableDependency($this->config);
45
+ }
46
+
47
+ /**
48
+ * Check if the entity type and bundle are enabled.
49
+ *
50
+ * @param \Drupal\Core\Entity\EntityInterface $entity
51
+ * The entity.
52
+ *
53
+ * @return bool
54
+ * TRUE if enabled, FALSE otherwise.
55
+ */
56
+ protected function entityTypeAndBundleEnabled(EntityInterface $entity): bool {
57
+ $enabled_entity_types = $this->config->get('enabled_entity_types');
58
+
59
+ // If no entity types are specified, fallback to allowing all.
60
+ if (count($enabled_entity_types) === 0) {
61
+ return TRUE;
62
+ }
63
+
64
+ // If the entity type exists in the configuration object.
65
+ if (isset($enabled_entity_types[$entity->getEntityTypeId()])) {
66
+ $enabled_bundles = $enabled_entity_types[$entity->getEntityTypeId()];
67
+ // If no bundles were specified, assume all bundles are enabled.
68
+ if (count($enabled_bundles) === 0) {
69
+ return TRUE;
70
+ }
71
+ // Otherwise fallback to requiring the specific bundle.
72
+ if (in_array($entity->bundle(), $enabled_bundles, TRUE)) {
73
+ return TRUE;
74
+ }
75
+ }
76
+
77
+ return FALSE;
78
+ }
79
+
80
+ }
@@ -0,0 +1,49 @@
1
+ <?php
2
+
3
+ declare(strict_types = 1);
4
+
5
+ namespace Drupal\silverback_preview_link\Access;
6
+
7
+ use Drupal\Core\Access\AccessResult;
8
+ use Drupal\Core\Access\AccessResultInterface;
9
+ use Drupal\Core\Entity\EntityInterface;
10
+ use Drupal\Core\Routing\Access\AccessInterface;
11
+ use Drupal\silverback_preview_link\PreviewLinkHostInterface;
12
+
13
+ /**
14
+ * Preview link access check.
15
+ */
16
+ class PreviewLinkAccessCheck implements AccessInterface {
17
+
18
+ /**
19
+ * PreviewLinkAccessCheck constructor.
20
+ */
21
+ public function __construct(
22
+ protected PreviewLinkHostInterface $previewLinkHost,
23
+ ) {
24
+ }
25
+
26
+ /**
27
+ * Checks access to the preview link.
28
+ */
29
+ public function access(EntityInterface $entity = NULL, string $preview_token = NULL): AccessResultInterface {
30
+ $neutral = AccessResult::neutral()->addCacheableDependency($entity);
31
+ if (!$preview_token || !$entity) {
32
+ return $neutral;
33
+ }
34
+
35
+ // If we can't find a valid preview link then ignore this.
36
+ if (!$this->previewLinkHost->hasPreviewLinks($entity)) {
37
+ return $neutral->setReason('This entity does not have a preview link.');
38
+ }
39
+
40
+ // If an entity has a preview link that doesn't match up,
41
+ // then explicitly deny access.
42
+ if (!$this->previewLinkHost->isToken($entity, [$preview_token])) {
43
+ return AccessResult::forbidden('Preview token is invalid.')->addCacheableDependency($entity);
44
+ }
45
+
46
+ return AccessResult::allowed()->addCacheableDependency($entity);
47
+ }
48
+
49
+ }