diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 61341fa8..5574fdc7 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -200,11 +200,6 @@ parameters: count: 1 path: src/bundle/eZ/RichText/Renderer.php - - - message: "#^Method EzSystems\\\\EzPlatformRichTextBundle\\\\eZ\\\\RichText\\\\Renderer\\:\\:checkContentPermissions\\(\\) has no return type specified\\.$#" - count: 1 - path: src/bundle/eZ/RichText/Renderer.php - - message: "#^Method EzSystems\\\\EzPlatformRichTextBundle\\\\eZ\\\\RichText\\\\Renderer\\:\\:getEmbedTemplateName\\(\\) has parameter \\$isDenied with no type specified\\.$#" count: 1 @@ -1630,36 +1625,6 @@ parameters: count: 1 path: tests/bundle/eZ/RichText/RendererTest.php - - - message: "#^Property EzSystems\\\\Tests\\\\EzPlatformRichTextBundle\\\\eZ\\\\RichText\\\\RendererTest\\:\\:\\$authorizationCheckerMock \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\Security\\\\Core\\\\Authorization\\\\AuthorizationCheckerInterface\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" - count: 1 - path: tests/bundle/eZ/RichText/RendererTest.php - - - - message: "#^Property EzSystems\\\\Tests\\\\EzPlatformRichTextBundle\\\\eZ\\\\RichText\\\\RendererTest\\:\\:\\$configResolverMock \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Psr\\\\Log\\\\LoggerInterface\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" - count: 1 - path: tests/bundle/eZ/RichText/RendererTest.php - - - - message: "#^Property EzSystems\\\\Tests\\\\EzPlatformRichTextBundle\\\\eZ\\\\RichText\\\\RendererTest\\:\\:\\$loaderMock \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Twig\\\\Loader\\\\LoaderInterface\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" - count: 1 - path: tests/bundle/eZ/RichText/RendererTest.php - - - - message: "#^Property EzSystems\\\\Tests\\\\EzPlatformRichTextBundle\\\\eZ\\\\RichText\\\\RendererTest\\:\\:\\$loggerMock \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Psr\\\\Log\\\\LoggerInterface\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" - count: 1 - path: tests/bundle/eZ/RichText/RendererTest.php - - - - message: "#^Property EzSystems\\\\Tests\\\\EzPlatformRichTextBundle\\\\eZ\\\\RichText\\\\RendererTest\\:\\:\\$repositoryMock \\(eZ\\\\Publish\\\\API\\\\Repository\\\\Repository&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" - count: 1 - path: tests/bundle/eZ/RichText/RendererTest.php - - - - message: "#^Property EzSystems\\\\Tests\\\\EzPlatformRichTextBundle\\\\eZ\\\\RichText\\\\RendererTest\\:\\:\\$templateEngineMock \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\Templating\\\\EngineInterface\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" - count: 1 - path: tests/bundle/eZ/RichText/RendererTest.php - - message: "#^Cannot access property \\$id on eZ\\\\Publish\\\\API\\\\Repository\\\\Values\\\\Content\\\\Field\\|null\\.$#" count: 1 diff --git a/src/bundle/Resources/config/fieldtype_services.yaml b/src/bundle/Resources/config/fieldtype_services.yaml index 02f17d26..b374408b 100644 --- a/src/bundle/Resources/config/fieldtype_services.yaml +++ b/src/bundle/Resources/config/fieldtype_services.yaml @@ -33,16 +33,16 @@ services: ezrichtext.renderer: class: EzSystems\EzPlatformRichTextBundle\eZ\RichText\Renderer arguments: - - '@ezpublish.api.repository' - - '@security.authorization_checker' - - '@ezpublish.config.resolver' - - '@twig' - - '%ezrichtext.tag.namespace%' - - '%ezrichtext.style.namespace%' - - '%ezrichtext.embed.namespace%' - - '@?logger' - - '%ezplatform.ezrichtext.custom_tags%' - - '%ezplatform.ezrichtext.custom_styles%' + $repository: '@ezpublish.api.repository' + $configResolver: '@ezpublish.config.resolver' + $templateEngine: '@twig' + $permissionResolver: '@eZ\Publish\API\Repository\PermissionResolver' + $tagConfigurationNamespace: '%ezrichtext.tag.namespace%' + $styleConfigurationNamespace: '%ezrichtext.style.namespace%' + $embedConfigurationNamespace: '%ezrichtext.embed.namespace%' + $logger: '@?logger' + $customTagsConfiguration: '%ezplatform.ezrichtext.custom_tags%' + $customStylesConfiguration: '%ezplatform.ezrichtext.custom_styles%' ezrichtext.converter.link: class: EzSystems\EzPlatformRichText\eZ\RichText\Converter\Link diff --git a/src/bundle/eZ/RichText/Renderer.php b/src/bundle/eZ/RichText/Renderer.php index d52ffcd5..44368461 100644 --- a/src/bundle/eZ/RichText/Renderer.php +++ b/src/bundle/eZ/RichText/Renderer.php @@ -8,13 +8,12 @@ namespace EzSystems\EzPlatformRichTextBundle\eZ\RichText; +use eZ\Publish\API\Repository\PermissionResolver; use eZ\Publish\API\Repository\Repository; use eZ\Publish\API\Repository\Values\Content\Content; use eZ\Publish\Core\MVC\ConfigResolverInterface; use EzSystems\EzPlatformRichText\eZ\RichText\RendererInterface; use Psr\Log\NullLogger; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; -use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute as AuthorizationAttribute; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use eZ\Publish\API\Repository\Exceptions\NotFoundException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -30,84 +29,54 @@ class Renderer implements RendererInterface const RESOURCE_TYPE_CONTENT = 0; const RESOURCE_TYPE_LOCATION = 1; - /** - * @var \eZ\Publish\Core\Repository\Repository - */ + /** @var \eZ\Publish\Core\Repository\Repository */ protected $repository; - /** - * @var \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface - */ - private $authorizationChecker; + /** @var \eZ\Publish\Core\MVC\ConfigResolverInterface */ + protected $configResolver; - /** - * @var string - */ + /** @var \Twig\Environment */ + protected $templateEngine; + + /** @var \eZ\Publish\API\Repository\PermissionResolver */ + private $permissionResolver; + + /** @var string */ protected $tagConfigurationNamespace; - /** - * @var string - */ + /** @var string */ protected $styleConfigurationNamespace; - /** - * @var string - */ + /** @var string */ protected $embedConfigurationNamespace; - /** - * @var ConfigResolverInterface - */ - protected $configResolver; - - /** - * @var \Twig\Environment - */ - protected $templateEngine; - /** * @var \Psr\Log\LoggerInterface|null */ protected $logger; - /** - * @var array - */ + /** @var array */ private $customTagsConfiguration; - /** - * @var array - */ + /** @var array */ private $customStylesConfiguration; - /** - * @param \eZ\Publish\API\Repository\Repository $repository - * @param \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface $authorizationChecker - * @param \eZ\Publish\Core\MVC\ConfigResolverInterface $configResolver - * @param \Twig\Environment $templateEngine - * @param string $tagConfigurationNamespace - * @param string $styleConfigurationNamespace - * @param string $embedConfigurationNamespace - * @param \Psr\Log\LoggerInterface|null $logger - * @param array $customTagsConfiguration - * @param array $customStylesConfiguration - */ public function __construct( Repository $repository, - AuthorizationCheckerInterface $authorizationChecker, ConfigResolverInterface $configResolver, Environment $templateEngine, - $tagConfigurationNamespace, - $styleConfigurationNamespace, - $embedConfigurationNamespace, + PermissionResolver $permissionResolver, + string $tagConfigurationNamespace, + string $styleConfigurationNamespace, + string $embedConfigurationNamespace, LoggerInterface $logger = null, array $customTagsConfiguration = [], array $customStylesConfiguration = [] ) { $this->repository = $repository; - $this->authorizationChecker = $authorizationChecker; $this->configResolver = $configResolver; $this->templateEngine = $templateEngine; + $this->permissionResolver = $permissionResolver; $this->tagConfigurationNamespace = $tagConfigurationNamespace; $this->styleConfigurationNamespace = $styleConfigurationNamespace; $this->embedConfigurationNamespace = $embedConfigurationNamespace; @@ -452,20 +421,15 @@ protected function getEmbedTemplateName($resourceType, $isInline, $isDenied) /** * Check embed permissions for the given Content. * - * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException - * - * @param \eZ\Publish\API\Repository\Values\Content\Content $content + * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ - protected function checkContentPermissions(Content $content) + protected function checkContentPermissions(Content $content): void { // Check both 'content/read' and 'content/view_embed'. if ( - !$this->authorizationChecker->isGranted( - new AuthorizationAttribute('content', 'read', ['valueObject' => $content]) - ) - && !$this->authorizationChecker->isGranted( - new AuthorizationAttribute('content', 'view_embed', ['valueObject' => $content]) - ) + !$this->permissionResolver->canUser('content', 'read', $content) + && !$this->permissionResolver->canUser('content', 'view_embed', $content) ) { throw new AccessDeniedException(); } @@ -473,9 +437,7 @@ protected function checkContentPermissions(Content $content) // Check that Content is published, since sudo allows loading unpublished content. if ( !$content->getVersionInfo()->isPublished() - && !$this->authorizationChecker->isGranted( - new AuthorizationAttribute('content', 'versionread', ['valueObject' => $content]) - ) + && !$this->permissionResolver->canUser('content', 'versionread', $content) ) { throw new AccessDeniedException(); } @@ -484,11 +446,12 @@ protected function checkContentPermissions(Content $content) /** * Checks embed permissions for the given Location $id and returns the Location. * - * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException - * * @param int|string $id * * @return \eZ\Publish\API\Repository\Values\Content\Location + * + * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException */ protected function checkLocation($id) { @@ -501,19 +464,17 @@ function (Repository $repository) use ($id) { // Check both 'content/read' and 'content/view_embed'. if ( - !$this->authorizationChecker->isGranted( - new AuthorizationAttribute( - 'content', - 'read', - ['valueObject' => $location->contentInfo, 'targets' => [$location]] - ) + !$this->permissionResolver->canUser( + 'content', + 'read', + $location->contentInfo, + [$location] ) - && !$this->authorizationChecker->isGranted( - new AuthorizationAttribute( - 'content', - 'view_embed', - ['valueObject' => $location->contentInfo, 'targets' => [$location]] - ) + && !$this->permissionResolver->canUser( + 'content', + 'view_embed', + $location->contentInfo, + [$location] ) ) { throw new AccessDeniedException(); diff --git a/tests/bundle/eZ/RichText/RendererTest.php b/tests/bundle/eZ/RichText/RendererTest.php index 39e943e0..fe064cbe 100644 --- a/tests/bundle/eZ/RichText/RendererTest.php +++ b/tests/bundle/eZ/RichText/RendererTest.php @@ -8,7 +8,8 @@ namespace EzSystems\Tests\EzPlatformRichTextBundle\eZ\RichText; -use eZ\Publish\Core\Repository\Repository; +use eZ\Publish\API\Repository\PermissionResolver; +use eZ\Publish\API\Repository\Repository; use eZ\Publish\API\Repository\Values\Content\Location; use eZ\Publish\API\Repository\Values\Content\Content; use eZ\Publish\API\Repository\Values\Content\ContentInfo; @@ -18,22 +19,39 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use eZ\Publish\Core\Base\Exceptions\NotFoundException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Exception; use PHPUnit\Framework\TestCase; use Twig\Environment; use Twig\Loader\LoaderInterface; -class RendererTest extends TestCase +final class RendererTest extends TestCase { + /** @var \PHPUnit\Framework\MockObject\MockObject&\eZ\Publish\API\Repository\Repository */ + private $repositoryMock; + + /** @var \eZ\Publish\Core\MVC\ConfigResolverInterface&\PHPUnit\Framework\MockObject\MockObject */ + private $configResolverMock; + + /** @var \Twig\Environment&\PHPUnit\Framework\MockObject\MockObject */ + private $templateEngineMock; + + /** @var \eZ\Publish\API\Repository\PermissionResolver&\PHPUnit\Framework\MockObject\MockObject */ + private $permissionResolverMock; + + /** @var \Psr\Log\LoggerInterface&\PHPUnit\Framework\MockObject\MockObject */ + private $loggerMock; + + /** @var \Twig\Loader\LoaderInterface&\PHPUnit\Framework\MockObject\MockObject */ + private $loaderMock; + public function setUp(): void { - $this->repositoryMock = $this->getRepositoryMock(); - $this->authorizationCheckerMock = $this->getAuthorizationCheckerMock(); - $this->configResolverMock = $this->getConfigResolverMock(); - $this->templateEngineMock = $this->getTemplateEngineMock(); - $this->loggerMock = $this->getLoggerMock(); - $this->loaderMock = $this->getLoaderMock(); + $this->repositoryMock = $this->createMock(Repository::class); + $this->configResolverMock = $this->createMock(ConfigResolverInterface::class); + $this->templateEngineMock = $this->createMock(Environment::class); + $this->permissionResolverMock = $this->createMock(PermissionResolver::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->loaderMock = $this->createMock(LoaderInterface::class); parent::setUp(); } @@ -406,8 +424,7 @@ public function testRenderContentEmbed() $renderer ->expects($this->once()) ->method('checkContentPermissions') - ->with($contentMock) - ->willReturn($contentMock); + ->with($contentMock); $renderer ->expects($this->once()) @@ -462,8 +479,7 @@ public function testRenderContentEmbedNoTemplateConfigured() $renderer ->expects($this->once()) ->method('checkContentPermissions') - ->with($contentMock) - ->willReturn($contentMock); + ->with($contentMock); $renderer ->expects($this->never()) @@ -987,8 +1003,7 @@ public function testRenderContentWithTemplate( $renderer ->expects($this->once()) ->method('checkContentPermissions') - ->with($contentMock) - ->willReturn($contentMock); + ->with($contentMock); } if (!isset($renderTemplate)) { @@ -1707,9 +1722,9 @@ protected function getMockedRenderer(array $methods = []) ->setConstructorArgs( [ $this->repositoryMock, - $this->authorizationCheckerMock, $this->configResolverMock, $this->templateEngineMock, + $this->permissionResolverMock, 'test.name.space.tag', 'test.name.space.style', 'test.name.space.embed', @@ -1720,84 +1735,6 @@ protected function getMockedRenderer(array $methods = []) ->getMock(); } - /** - * @var \eZ\Publish\API\Repository\Repository|\PHPUnit\Framework\MockObject\MockObject - */ - protected $repositoryMock; - - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function getRepositoryMock() - { - return $this->createMock(Repository::class); - } - - /** - * @var \Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface|\PHPUnit\Framework\MockObject\MockObject - */ - protected $authorizationCheckerMock; - - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function getAuthorizationCheckerMock() - { - return $this->createMock(AuthorizationCheckerInterface::class); - } - - /** - * @var \Psr\Log\LoggerInterface|\PHPUnit\Framework\MockObject\MockObject - */ - protected $configResolverMock; - - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function getConfigResolverMock() - { - return $this->createMock(ConfigResolverInterface::class); - } - - /** - * @var \Symfony\Component\Templating\EngineInterface|\PHPUnit\Framework\MockObject\MockObject - */ - protected $templateEngineMock; - - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function getTemplateEngineMock() - { - return $this->createMock(Environment::class); - } - - /** - * @var \Psr\Log\LoggerInterface|\PHPUnit\Framework\MockObject\MockObject - */ - protected $loggerMock; - - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function getLoggerMock() - { - return $this->createMock(LoggerInterface::class); - } - - /** - * @var \Twig\Loader\LoaderInterface|\PHPUnit\Framework\MockObject\MockObject - */ - protected $loaderMock; - - /** - * @return \PHPUnit\Framework\MockObject\MockObject - */ - protected function getLoaderMock() - { - return $this->createMock(LoaderInterface::class); - } - protected function getContentMock($mainLocationId) { $contentInfoMock = $this->createMock(ContentInfo::class);