Skip to content

Commit

Permalink
IBX-6485: Forced RichText\Rendererto utilize PermissionResolver i…
Browse files Browse the repository at this point in the history
…nstead of `AuthorizationChecker`

For more details see https://issues.ibexa.co/browse/IBX-6485 and  #239

Key changes:

* Refactored `RichText\Renderer`to utilize `PermissionResolver` instead of `AuthorizationChecker`
  • Loading branch information
barw4 authored Oct 2, 2023
1 parent 938d2b3 commit ad8aed2
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 217 deletions.
35 changes: 0 additions & 35 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
20 changes: 10 additions & 10 deletions src/bundle/Resources/config/fieldtype_services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
117 changes: 39 additions & 78 deletions src/bundle/eZ/RichText/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -452,30 +421,23 @@ 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();
}

// 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();
}
Expand All @@ -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)
{
Expand All @@ -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();
Expand Down
Loading

0 comments on commit ad8aed2

Please sign in to comment.