Last active
March 23, 2023 08:46
-
-
Save zspine/dc04af513137e5264b0e5d639722bb95 to your computer and use it in GitHub Desktop.
API Platform custom ContextBuilder and Denormalizer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
######################################################################################################################## | |
### API PLATFORM | |
######################################################################################################################## | |
App\Serializer\ApiPlatform\SuperAdminGroupContextBuilder: | |
decorates: 'api_platform.serializer.context_builder' | |
arguments: [ '@App\Serializer\ApiPlatform\SuperAdminGroupContextBuilder.inner' ] | |
autoconfigure: false | |
App\Serializer\Denormalizer\UserDenormalizer: | |
tags: | |
- { name: serializer.normalizer} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Serializer\ApiPlatform; | |
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; | |
use Psr\Log\LoggerAwareInterface; | |
use Psr\Log\LoggerAwareTrait; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; | |
use App\Entity\User; | |
/** | |
* Class SuperAdminGroupContextBuilder | |
* @package App\Serializer\ApiPlatform | |
*/ | |
class SuperAdminGroupContextBuilder implements SerializerContextBuilderInterface, LoggerAwareInterface | |
{ | |
use LoggerAwareTrait; | |
/** | |
* @var SerializerContextBuilderInterface | |
*/ | |
private $decorated; | |
/** | |
* @var AuthorizationCheckerInterface | |
*/ | |
private $authorizationChecker; | |
/** | |
* AdminGroupContextBuilder constructor. | |
* @param SerializerContextBuilderInterface $decorated | |
* @param AuthorizationCheckerInterface $authorizationChecker | |
*/ | |
public function __construct( | |
SerializerContextBuilderInterface $decorated, | |
AuthorizationCheckerInterface $authorizationChecker | |
) { | |
$this->decorated = $decorated; | |
$this->authorizationChecker = $authorizationChecker; | |
} | |
/** | |
* @param Request $request | |
* @param bool $normalization | |
* @param array|null $extractedAttributes | |
* @return array | |
*/ | |
public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array | |
{ | |
$context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes); | |
$this->logger->debug(self::class, $context); | |
return $context; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Serializer\Denormalizer; | |
use App\Entity\User; | |
use App\Model\User\UserInterface; | |
use Psr\Log\LoggerAwareInterface; | |
use Psr\Log\LoggerAwareTrait; | |
use Symfony\Component\Security\Core\Security; | |
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; | |
use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface; | |
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface; | |
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait; | |
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; | |
/** | |
* Class UserDenormalizer | |
* @package App\Serializer\Denormalizer | |
*/ | |
class UserDenormalizer implements ContextAwareDenormalizerInterface, DenormalizerAwareInterface, LoggerAwareInterface | |
{ | |
use DenormalizerAwareTrait; | |
use LoggerAwareTrait; | |
/** | |
* @var string | |
*/ | |
private const ALREADY_CALLED = 'USER_DENORMALIZER_ALREADY_CALLED'; | |
/** | |
* @var Security | |
*/ | |
private $security; | |
/** | |
* UserDenormalizer constructor. | |
* @param Security $security | |
*/ | |
public function __construct(Security $security) | |
{ | |
$this->security = $security; | |
} | |
/**\ | |
* {@inheritDoc} | |
*/ | |
public function denormalize($data, $type, $format = null, array $context = []) | |
{ | |
$context['groups'] = ($context['groups']) ?? []; | |
if(isset($context['collection_operation_name'])) { | |
switch ($context['collection_operation_name']) { | |
case 'post': | |
$context['groups'][] = 'anon:write'; | |
break; | |
} | |
} | |
if(isset($context['item_operation_name'])) { | |
switch ($context['item_operation_name']) { | |
case 'put': | |
if($this->isSuperAdmin() || $this->isAllowed()) { | |
$context['groups'][] = 'me:write'; | |
} | |
break; | |
} | |
} | |
if($this->isSuperAdmin()) { | |
if(!in_array('super:write', $context['groups'], true)) { | |
$context['groups'][] = 'super:write'; | |
} | |
} | |
array_unique($context['groups']); | |
$context[self::ALREADY_CALLED] = true; | |
$this->logger->debug(self::class, $context); | |
return $this->denormalizer->denormalize($data, $type, $format, $context); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function supportsDenormalization($data, $type, $format = null, array $context = []) | |
{ | |
if (isset($context[self::ALREADY_CALLED])) { | |
return false; | |
} | |
return User::class === $type; | |
} | |
/** | |
* @return bool | |
*/ | |
public function isSuperAdmin() | |
{ | |
/** @var User|null $user */ | |
$user = $this->security->getUser(); | |
if(!($user instanceof UserInterface)) { | |
return false; | |
} | |
return $user->hasRole(User::ROLE_SUPER_ADMIN); | |
} | |
/** | |
* @return bool | |
* @todo make sure to replace this method with a service (dummy_placeholder) | |
*/ | |
public function isAllowed() | |
{ | |
/** @var User|null $user */ | |
$user = $this->security->getUser(); | |
if(!($user instanceof UserInterface)) { | |
return false; | |
} | |
return $user->hasRole(User::DEFAULT_ROLE); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment