diff --git a/src/Controller/ExperienceBuilderController.php b/src/Controller/ExperienceBuilderController.php index 94dfed3125141ee3c2256b1c01377ca7e5901be8..a9935755bd3fae29a0ef5fa07777e316db9b1f04 100644 --- a/src/Controller/ExperienceBuilderController.php +++ b/src/Controller/ExperienceBuilderController.php @@ -13,10 +13,14 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Field\WidgetPluginManager; use Drupal\Core\Render\HtmlResponse; use Drupal\Core\Render\RendererInterface; +use Drupal\Core\Session\AccountInterface; use Drupal\Core\Template\Attribute; use Drupal\Core\Theme\ThemeInitializationInterface; use Drupal\Core\Theme\ThemeManagerInterface; use Drupal\experience_builder\AssetRenderer; +use Drupal\experience_builder\Entity\JavaScriptComponent; +use Drupal\experience_builder\Entity\PageRegion; +use Drupal\experience_builder\Entity\Pattern; use Symfony\Component\DependencyInjection\Attribute\Autowire; final class ExperienceBuilderController { @@ -31,6 +35,7 @@ final class ExperienceBuilderController { private readonly LibraryDiscoveryInterface $libraryDiscovery, private readonly RendererInterface $renderer, private readonly ThemeInitializationInterface $themeInitialization, + private readonly AccountInterface $currentUser, ) {} private const HTML = <<<HTML @@ -110,6 +115,11 @@ HTML; 'jsFooter' => $this->assetRenderer->renderJsFooterAssets($preview_assets), ], 'xbModulePath' => $xb_module_path, + 'permissions' => [ + 'globalRegions' => $this->currentUser->hasPermission(PageRegion::ADMIN_PERMISSION), + 'sections' => $this->currentUser->hasPermission(Pattern::ADMIN_PERMISSION), + 'codeComponents' => $this->currentUser->hasPermission(JavaScriptComponent::ADMIN_PERMISSION), + ], ], ], // Note: the tokens here are under our control, and this accepts no user diff --git a/src/Entity/JavaScriptComponent.php b/src/Entity/JavaScriptComponent.php index 74c8399d8516022badb2ab816be6db6ecd55cc54..be41cd3e00ba9fcda0cc3ab2bc64a6ab98d964ed 100644 --- a/src/Entity/JavaScriptComponent.php +++ b/src/Entity/JavaScriptComponent.php @@ -18,7 +18,7 @@ use Drupal\experience_builder\ClientSideRepresentation; * label_singular = @Translation("code component"), * label_plural = @Translation("code components"), * label_collection = @Translation("Code components"), - * admin_permission = "administer code components", + * admin_permission = \Drupal\experience_builder\Entity\JavaScriptComponent::ADMIN_PERMISSION, * handlers = { * "storage" = \Drupal\experience_builder\EntityHandlers\JavascriptComponentStorage::class, * "access" = \Drupal\experience_builder\EntityHandlers\XbConfigEntityAccessControlHandler::class, @@ -49,6 +49,7 @@ final class JavaScriptComponent extends ConfigEntityBase implements XbAssetInter use XbAssetLibraryTrait; public const string ENTITY_TYPE_ID = 'js_component'; + public const ADMIN_PERMISSION = 'administer code components'; private const string ASSETS_DIRECTORY = 'assets://astro-island/'; /** diff --git a/src/Entity/PageRegion.php b/src/Entity/PageRegion.php index c5eeef1b91e34eb54d8d96c1e393723caf1deeb2..11665ece6933abe702a263993bb488b7bdaaf31b 100644 --- a/src/Entity/PageRegion.php +++ b/src/Entity/PageRegion.php @@ -23,7 +23,7 @@ use Drupal\experience_builder\Plugin\Field\FieldType\ComponentTreeItemInstantiat * label_singular = @Translation("page region"), * label_plural = @Translation("page region"), * label_collection = @Translation("Page region"), - * admin_permission = "administer page template", + * admin_permission = \Drupal\experience_builder\Entity\PageRegion::ADMIN_PERMISSION, * handlers = { * "access" = \Drupal\experience_builder\EntityHandlers\XbConfigEntityAccessControlHandler::class * }, @@ -45,6 +45,7 @@ use Drupal\experience_builder\Plugin\Field\FieldType\ComponentTreeItemInstantiat final class PageRegion extends ConfigEntityBase implements ComponentTreeEntityInterface { public const PLUGIN_ID = 'page_region'; + public const ADMIN_PERMISSION = 'administer page template'; use ComponentTreeItemInstantiatorTrait; use ClientServerConversionTrait; diff --git a/src/Entity/Pattern.php b/src/Entity/Pattern.php index b2ce7b99610c0679b195b862463c4847b16676e7..eeebe2d957b8c8f5cf90f174e96093926915dc48 100644 --- a/src/Entity/Pattern.php +++ b/src/Entity/Pattern.php @@ -17,12 +17,12 @@ use Drupal\experience_builder\Plugin\Field\FieldType\ComponentTreeItemInstantiat /** * @ConfigEntityType( - * id = "pattern", + * id = \Drupal\experience_builder\Entity\Pattern::PLUGIN_ID, * label = @Translation("Pattern"), * label_singular = @Translation("pattern"), * label_plural = @Translation("patterns"), * label_collection = @Translation("Patterns"), - * admin_permission = "administer patterns", + * admin_permission = \Drupal\experience_builder\Entity\Pattern::ADMIN_PERMISSION, * handlers = { * "access" = \Drupal\experience_builder\EntityHandlers\ContentCreatorVisibleXbConfigEntityAccessControlHandler::class * }, @@ -39,6 +39,9 @@ use Drupal\experience_builder\Plugin\Field\FieldType\ComponentTreeItemInstantiat */ final class Pattern extends ConfigEntityBase implements XbHttpApiEligibleConfigEntityInterface, ComponentTreeEntityInterface { + public const PLUGIN_ID = 'pattern'; + public const ADMIN_PERMISSION = 'administer patterns'; + use ComponentTreeItemInstantiatorTrait; use ClientServerConversionTrait; diff --git a/tests/src/Kernel/Controller/ExperienceBuilderControllerTest.php b/tests/src/Kernel/Controller/ExperienceBuilderControllerTest.php index 33211b2ca208459eb4af4bd6b17c01351012f438..7ac0d508812e6fdc884433b66d8d716c296b6b13 100644 --- a/tests/src/Kernel/Controller/ExperienceBuilderControllerTest.php +++ b/tests/src/Kernel/Controller/ExperienceBuilderControllerTest.php @@ -4,7 +4,11 @@ declare(strict_types=1); namespace Drupal\Tests\experience_builder\Kernel\Controller; +use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Url; +use Drupal\experience_builder\Entity\JavaScriptComponent; +use Drupal\experience_builder\Entity\PageRegion; +use Drupal\experience_builder\Entity\Pattern; use Drupal\KernelTests\KernelTestBase; use Drupal\Tests\experience_builder\Kernel\Traits\PageTrait; use Drupal\Tests\experience_builder\Kernel\Traits\RequestTrait; @@ -41,6 +45,12 @@ final class ExperienceBuilderControllerTest extends KernelTestBase { $this->installEntitySchema('path_alias'); } + public function register(ContainerBuilder $container): void { + // Enable debug_cacheability_headers, so we can test cacheability. + $container->setParameter('http.response.debug_cacheability_headers', TRUE); + parent::register($container); + } + /** * Tests controller output when adding or editing an entity. * @@ -75,7 +85,18 @@ final class ExperienceBuilderControllerTest extends KernelTestBase { 'entity' => $sut->id(), ])->toString(); self::assertEquals("/xb/$entity_type/{$sut->id()}", $edit_url); - $this->request(Request::create($edit_url)); + + /** @var \Drupal\Core\Render\HtmlResponse $response */ + $response = $this->request(Request::create($edit_url)); + + self::assertSame([ + 'user.permissions', + 'languages:language_interface', + 'theme', + ], $response->getCacheableMetadata()->getCacheContexts()); + self::assertSame([ + 'http_response' + ], $response->getCacheableMetadata()->getCacheTags()); $this->assertExperienceBuilderMount($entity_type, $sut); } @@ -101,4 +122,80 @@ final class ExperienceBuilderControllerTest extends KernelTestBase { ]; } + /** + * Tests controller exposed permissions. + * + * @param array $permissions + * The permissions. + * @param array $expectedPermissionFlags + * The expected flags. + * + * @dataProvider permissionsData + */ + public function testControllerExposedPermissions(array $permissions, array $expectedPermissionFlags): void { + $this->installEntitySchema('xb_page'); + + $this->setUpCurrentUser([], $permissions); + + $add_url = Url::fromRoute('experience_builder.experience_builder', [ + 'entity_type' => 'xb_page', + 'entity' => '', + ])->toString(); + self::assertEquals("/xb/xb_page", $add_url); + $this->request(Request::create($add_url)); + + $this->assertEqualsCanonicalizing($expectedPermissionFlags, $this->drupalSettings['xb']['permissions']); + } + + public static function permissionsData(): array { + return [ + [ + [ + 'administer xb_page', + ], + [ + 'globalRegion' => FALSE, + 'sections' => FALSE, + 'codeComponents' => FALSE, + ], + ], + [ + [ + 'administer xb_page', + JavaScriptComponent::ADMIN_PERMISSION, + ], + [ + 'globalRegion' => FALSE, + 'sections' => FALSE, + 'codeComponents' => TRUE, + ], + ], + [ + [ + 'administer xb_page', + Pattern::ADMIN_PERMISSION, + PageRegion::ADMIN_PERMISSION, + ], + [ + 'globalRegion' => TRUE, + 'sections' => TRUE, + 'codeComponents' => FALSE, + ], + ], + [ + [ + 'administer xb_page', + Pattern::ADMIN_PERMISSION, + PageRegion::ADMIN_PERMISSION, + JavaScriptComponent::ADMIN_PERMISSION, + ], + [ + 'globalRegion' => TRUE, + 'sections' => TRUE, + 'codeComponents' => TRUE, + ], + ], + ]; + } + }