Skip to content

Commit

Permalink
Merge pull request from GHSA-vr2x-7687-h6qv
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Feb 27, 2023
1 parent 1c9a025 commit 5723d68
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 11 deletions.
22 changes: 22 additions & 0 deletions features/authorization/deny.feature
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,25 @@ Feature: Authorization checking
Then the response status code should be 200
And the response should contain "ownerOnlyProperty"
And the JSON node "ownerOnlyProperty" should be equal to the string "updated"

Scenario: A user retrieves a resource with an admin only viewable property
When I add "Accept" header equal to "application/json"
And I add "Authorization" header equal to "Basic ZHVuZ2xhczprZXZpbg=="
And I send a "GET" request to "/secured_dummies"
Then the response status code should be 200
And the response should contain "ownerOnlyProperty"

Scenario: A user retrieves a resource with an admin only viewable property
When I add "Accept" header equal to "application/hal+json"
And I add "Authorization" header equal to "Basic ZHVuZ2xhczprZXZpbg=="
And I send a "GET" request to "/secured_dummies"
Then the response status code should be 200
And the response should contain "ownerOnlyProperty"

Scenario: A user retrieves a resource with an admin only viewable property
Given I add "Accept" header equal to "application/vnd.api+json"
And I add "Authorization" header equal to "Basic ZHVuZ2xhczprZXZpbg=="
And I send a "GET" request to "/secured_dummies"
Then the response status code should be 200
And the response should contain "ownerOnlyProperty"

8 changes: 4 additions & 4 deletions src/Hal/Serializer/ItemNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ public function normalize($object, $format = null, array $context = [])
return parent::normalize($object, $format, $context);
}

if (!isset($context['cache_key'])) {
$context['cache_key'] = $this->getCacheKey($format, $context);
}

if ($this->resourceClassResolver->isResourceClass($resourceClass)) {
$resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null);
}
Expand All @@ -75,6 +71,10 @@ public function normalize($object, $format = null, array $context = [])
$context['iri'] = $iri;
$context['api_normalize'] = true;

if (!isset($context['cache_key'])) {
$context['cache_key'] = $this->getCacheKey($format, $context);
}

$data = parent::normalize($object, $format, $context);
if (!\is_array($data)) {
return $data;
Expand Down
10 changes: 5 additions & 5 deletions src/JsonApi/Serializer/ItemNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,7 @@ public function normalize($object, $format = null, array $context = [])
return parent::normalize($object, $format, $context);
}

if (!isset($context['cache_key'])) {
$context['cache_key'] = $this->getCacheKey($format, $context);
}

if ($isResourceClass = $this->resourceClassResolver->isResourceClass($resourceClass)) {
if ($this->resourceClassResolver->isResourceClass($resourceClass)) {
$resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null);
}

Expand All @@ -91,6 +87,10 @@ public function normalize($object, $format = null, array $context = [])
$context['iri'] = $iri;
$context['api_normalize'] = true;

if (!isset($context['cache_key'])) {
$context['cache_key'] = $this->getCacheKey($format, $context);
}

$data = parent::normalize($object, $format, $context);
if (!\is_array($data)) {
return $data;
Expand Down
6 changes: 6 additions & 0 deletions src/Serializer/AbstractItemNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use ApiPlatform\Exception\InvalidValueException;
use ApiPlatform\Exception\ItemNotFoundException;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\CollectionOperationInterface;
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
Expand Down Expand Up @@ -207,6 +208,11 @@ public function normalize($object, $format = null, array $context = [])
$context = $this->initContext($resourceClass, $context);
}

if (isset($context['operation']) && $context['operation'] instanceof CollectionOperationInterface) {
unset($context['operation']);
unset($context['iri']);
}

$iri = null;
if (isset($context['iri'])) {
$iri = $context['iri'];
Expand Down
14 changes: 12 additions & 2 deletions src/Serializer/CacheKeyTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@

namespace ApiPlatform\Serializer;

/**
* Used to override Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer::getCacheKey which is private
* We need the cache_key in JsonApi and Hal before it is computed in Symfony.
*
* @see https://github.com/symfony/symfony/blob/49b6ab853d81e941736a1af67845efa3401e7278/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php#L723 which isn't protected
*/
trait CacheKeyTrait
{
/**
Expand All @@ -24,11 +30,15 @@ private function getCacheKey(?string $format, array $context)
unset($context[$key]);
}
unset($context[self::EXCLUDE_FROM_CACHE_KEY]);
unset($context[self::OBJECT_TO_POPULATE]);
unset($context['cache_key']); // avoid artificially different keys

try {
return md5($format.serialize($context));
} catch (\Exception $exception) {
return hash('xxh128', $format.serialize([
'context' => $context,
'ignored' => $context[self::IGNORED_ATTRIBUTES] ?? $this->defaultContext[self::IGNORED_ATTRIBUTES],
]));
} catch (\Exception) {
// The context cannot be serialized, skip the cache
return false;
}
Expand Down

0 comments on commit 5723d68

Please sign in to comment.