Skip to content

Commit

Permalink
Merge 264075a into cecd948
Browse files Browse the repository at this point in the history
  • Loading branch information
Joe Bennett committed Mar 2, 2021
2 parents cecd948 + 264075a commit 8791983
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 11 deletions.
5 changes: 4 additions & 1 deletion features/filter/filter_validation.feature
@@ -1,5 +1,8 @@
Feature: Validate filters based upon filter description

Background:
Given I add "Accept" header equal to "application/json"

@createSchema
Scenario: Required filter should not throw an error if set
When I am on "/filter_validators?required=foo&required-allow-empty=&arrayRequired[foo]="
Expand All @@ -13,7 +16,7 @@ Feature: Validate filters based upon filter description
Scenario: Required filter should throw an error if not set
When I am on "/filter_validators"
Then the response status code should be 400
Then the JSON node "detail" should match '/^Query parameter "required" is required\nQuery parameter "required-allow-empty" is required$/'
And the JSON node "detail" should match '/^Query parameter "required" is required\nQuery parameter "required-allow-empty" is required$/'

Scenario: Required filter should not throw an error if set
When I am on "/array_filter_validators?arrayRequired[]=foo&indexedArrayRequired[foo]=foo"
Expand Down
20 changes: 17 additions & 3 deletions features/main/content_negotiation.feature
Expand Up @@ -22,7 +22,7 @@ Feature: Content Negotiation support
<response><description/><dummy/><dummyBoolean/><dummyDate/><dummyFloat/><dummyPrice/><relatedDummy/><relatedDummies/><jsonData/><arrayData/><name_converted/><relatedOwnedDummy/><relatedOwningDummy/><id>1</id><name>XML!</name><alias/><foo/></response>
"""

Scenario: Retrieve a collection in XML
Scenario: Retrieve a collection in XML
When I add "Accept" header equal to "text/xml"
And I send a "GET" request to "/dummies"
Then the response status code should be 200
Expand All @@ -34,7 +34,7 @@ Feature: Content Negotiation support
<response><item key="0"><description/><dummy/><dummyBoolean/><dummyDate/><dummyFloat/><dummyPrice/><relatedDummy/><relatedDummies/><jsonData/><arrayData/><name_converted/><relatedOwnedDummy/><relatedOwningDummy/><id>1</id><name>XML!</name><alias/><foo/></item></response>
"""

Scenario: Retrieve a collection in XML using the .xml URL
Scenario: Retrieve a collection in XML using the .xml URL
When I send a "GET" request to "/dummies.xml"
Then the response status code should be 200
And the header "Content-Type" should be equal to "application/xml; charset=utf-8"
Expand All @@ -45,7 +45,7 @@ Feature: Content Negotiation support
<response><item key="0"><description/><dummy/><dummyBoolean/><dummyDate/><dummyFloat/><dummyPrice/><relatedDummy/><relatedDummies/><jsonData/><arrayData/><name_converted/><relatedOwnedDummy/><relatedOwningDummy/><id>1</id><name>XML!</name><alias/><foo/></item></response>
"""

Scenario: Retrieve a collection in JSON
Scenario: Retrieve a collection in JSON
When I add "Accept" header equal to "application/json"
And I send a "GET" request to "/dummies"
Then the response status code should be 200
Expand Down Expand Up @@ -155,3 +155,17 @@ Feature: Content Negotiation support
id,name
1,Kevin
"""

Scenario: Get a security response in JSON
Given there are 1 SecuredDummy objects
And I add "Accept" header equal to "application/json"
When I send a "GET" request to "/secured_dummies"
Then the response status code should be 401
And the header "Content-Type" should be equal to "application/json"
And the response should be in JSON
And the JSON should be equal to:
"""
{
"message": "Authentication Required"
}
"""
4 changes: 2 additions & 2 deletions src/Bridge/Symfony/Bundle/Resources/config/api.xml
Expand Up @@ -150,15 +150,15 @@

<!-- Event listeners -->

<!-- kernel.request priority must be < 8 to be executed after the Firewall -->
<service id="api_platform.listener.request.add_format" class="ApiPlatform\Core\EventListener\AddFormatListener">
<argument type="service" id="api_platform.negotiator" />
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument>%api_platform.formats%</argument>

<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="7" />
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="28" />
</service>

<!-- kernel.request priority must be < 8 to be executed after the Firewall -->
<service id="api_platform.listener.request.read" class="ApiPlatform\Core\EventListener\ReadListener">
<argument type="service" id="api_platform.collection_data_provider" />
<argument type="service" id="api_platform.item_data_provider" />
Expand Down
10 changes: 5 additions & 5 deletions src/EventListener/AddFormatListener.php
Expand Up @@ -65,11 +65,11 @@ public function __construct(Negotiator $negotiator, $resourceMetadataFactory, ar
public function onKernelRequest(RequestEvent $event): void
{
$request = $event->getRequest();
if (
!($request->attributes->has('_api_resource_class')
|| $request->attributes->getBoolean('_api_respond', false)
|| $request->attributes->getBoolean('_graphql', false))
) {
if (!(
$request->attributes->has('_api_resource_class')
|| $request->attributes->getBoolean('_api_respond', false)
|| $request->attributes->getBoolean('_graphql', false)
)) {
return;
}

Expand Down
49 changes: 49 additions & 0 deletions tests/Fixtures/TestBundle/Security/AuthenticationEntryPoint.php
@@ -0,0 +1,49 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Tests\Fixtures\TestBundle\Security;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;

final class AuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
private $router;

public function __construct(RouterInterface $router)
{
$this->router = $router;
}

public function start(Request $request, AuthenticationException $authException = null): Response
{
if ('html' === $request->getRequestFormat()) {
return new RedirectResponse($this->router->generate('api_doc', [], UrlGeneratorInterface::ABSOLUTE_URL));
}
if ('json' === $request->getRequestFormat()) {
return new JsonResponse(
['message' => 'Authentication Required'],
Response::HTTP_UNAUTHORIZED,
['WWW-Authenticate' => 'Bearer realm="example"']
);
}

return new Response('', Response::HTTP_UNAUTHORIZED);
}
}
1 change: 1 addition & 0 deletions tests/Fixtures/app/AppKernel.php
Expand Up @@ -168,6 +168,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
'http_basic' => null,
'anonymous' => null,
'stateless' => true,
'entry_point' => 'app.security.authentication_entrypoint',
],
],
'access_control' => [
Expand Down
4 changes: 4 additions & 0 deletions tests/Fixtures/app/config/config_common.yml
Expand Up @@ -359,3 +359,7 @@ services:
tags:
- { name: 'api_platform.data_transformer' }

app.security.authentication_entrypoint:
class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Security\AuthenticationEntryPoint'
arguments:
$router: '@router'

0 comments on commit 8791983

Please sign in to comment.