Merge branch '1.9' into 1.10

* 1.9:
  [API] set api as disabled by default
  [API] kernel request event redirects to 404 for disabled api
  [API] RouteResolver throws 404 when api is disabled
  [API] add tests for disabling api
  [API] set api as disabled by default
  [API] kernel request event redirects to 404 for disabled api
  [Docs] add info how to enable api
  [API] RouteResolver throws 404 when api is disabled
  [API] add tests for disabling api
This commit is contained in:
Adam Kasperczak 2021-07-07 15:01:49 +02:00
commit 3e1f3b2484
14 changed files with 259 additions and 0 deletions

View file

@ -110,6 +110,8 @@ and its first argument `NormalizerInterface $objectNormalizer` has been removed
### New API
1. Api is disabled by default, to enable it you need to set flag ``sylius_api.enabled`` to ``true`` in ``app/config/packages/_sylius.yaml``.
1. Adjust your `config/packages/security.yaml`.
* Parameters from `config/packages/security.yaml` has been moved to separated bundles.

View file

@ -10,6 +10,9 @@ imports:
parameters:
sylius_core.public_dir: '%kernel.project_dir%/public'
sylius_api:
enabled: false
sylius_shop:
product_grid:
include_all_descendants: true

View file

@ -0,0 +1,2 @@
sylius_api:
enabled: true

View file

@ -0,0 +1,2 @@
sylius_api:
enabled: true

View file

@ -5,6 +5,7 @@ Introduction
The new, unified Sylius API is still under development, that's why the whole ``ApiBundle`` is tagged with ``@experimental``.
This means that all code from ``ApiBundle`` is excluded from :doc:`Backward Compatibility Promise </book/organization/backward-compatibility-promise>`.
You can enable entire API by changing the flag ``sylius_api.enabled`` to ``true`` in ``app/config/packages/_sylius.yaml``.
We have decided that we should rebuild our API and use API Platform to build a truly mature, multi-purpose API
which can define a new standard for headless e-commerce backends.

View file

@ -118,6 +118,7 @@
<referencedMethod name="Symfony\Component\HttpKernel\Event\KernelEvent::isMasterRequest" /> <!-- deprecated in Symfony 5.3 -->
<referencedMethod name="Symfony\Component\Security\Core\User\UserInterface::getUsername" /> <!-- deprecated in Symfony 5.3 -->
<referencedMethod name="Symfony\Component\Security\Core\User\UserProviderInterface::loadUserByUsername" /> <!-- deprecated in Symfony 5.3 -->
<referencedMethod name="Faker\Generator::__get"/>
</errorLevel>
</DeprecatedMethod>

View file

@ -27,6 +27,14 @@ final class Configuration implements ConfigurationInterface
/** @var ArrayNodeDefinition $rootNode */
$rootNode = $treeBuilder->getRootNode();
$rootNode
->children()
->booleanNode('enabled')
->defaultTrue()
->end()
->end()
;
return $treeBuilder;
}
}

View file

@ -26,6 +26,8 @@ final class SyliusApiExtension extends Extension
$config = $this->processConfiguration($this->getConfiguration([], $container), $configs);
$loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$container->setParameter('sylius_api.enabled', $config['enabled']);
$loader->load('services.xml');
}
}

View file

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\EventSubscriber;
use ApiPlatform\Core\EventListener\EventPriorities;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
/** @experimental */
final class KernelRequestEventSubscriber implements EventSubscriberInterface
{
/** @var bool */
private $apiEnabled;
/** @var string */
private $apiRoute;
public function __construct(bool $apiEnabled, string $apiRoute)
{
$this->apiEnabled = $apiEnabled;
$this->apiRoute = $apiRoute;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['validateApi', EventPriorities::PRE_VALIDATE],
];
}
public function validateApi(RequestEvent $event): void
{
$pathInfo = $event->getRequest()->getPathInfo();
if ($this->apiEnabled === false && strpos($pathInfo, $this->apiRoute) !== false) {
throw new NotFoundHttpException('Route not found');
}
}
}

View file

@ -16,6 +16,11 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<services>
<service id="sylius.api.kerner_request_event_subscriber" class="Sylius\Bundle\ApiBundle\EventSubscriber\KernelRequestEventSubscriber">
<argument>%sylius_api.enabled%</argument>
<argument>%sylius.security.new_api_route%</argument>
<tag name="kernel.event_subscriber" />
</service>
<service id="sylius.api.product_slug_event_subscriber" class="Sylius\Bundle\ApiBundle\EventSubscriber\ProductSlugEventSubscriber">
<argument type="service" id="sylius.generator.slug" />
<tag name="kernel.event_subscriber" />

View file

@ -0,0 +1,87 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\EventSubscriber;
use PhpSpec\ObjectBehavior;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
final class KernelRequestEventSubscriberSpec extends ObjectBehavior
{
function let(): void
{
$this->beConstructedWith(true, '/api/v2');
}
function it_does_nothing_if_api_is_enabled(
RequestEvent $event,
Request $request,
HttpKernelInterface $kernel
): void {
$event->getRequest()->willReturn($request);
$request->getPathInfo()->willReturn('/api/v2/any-endpoint');
$this->validateApi(new RequestEvent(
$kernel->getWrappedObject(),
$request->getWrappedObject(),
HttpKernelInterface::MASTER_REQUEST
));
}
function it_throws_not_found_exception_if_api_is_disabled(
RequestEvent $event,
Request $request,
HttpKernelInterface $kernel
): void {
$this->beConstructedWith(false, '/api/v2');
$event->getRequest()->willReturn($request);
$request->getPathInfo()->willReturn('/api/v2/any-endpoint');
$this
->shouldThrow(NotFoundHttpException::class)
->during(
'validateApi',
[
new RequestEvent(
$kernel->getWrappedObject(),
$request->getWrappedObject(),
HttpKernelInterface::MASTER_REQUEST
)
]
);
}
function it_does_nothing_for_non_api_endpoints_when_api_is_disabled(
RequestEvent $event,
Request $request,
HttpKernelInterface $kernel
): void {
$this->beConstructedWith(false, '/api/v2');
$event->getRequest()->willReturn($request);
$request->getPathInfo()->willReturn('/');
$this->validateApi(new RequestEvent(
$kernel->getWrappedObject(),
$request->getWrappedObject(),
HttpKernelInterface::MASTER_REQUEST
));
}
}

View file

@ -14,6 +14,9 @@ api_platform:
- '%kernel.api_bundle_path%/Resources/config/api_resources'
- '%kernel.project_dir%/config/api_resources'
sylius_api:
enabled: '%env(bool:SYLIUS_API_ENABLED)%'
framework:
assets: ~
secret: "ch4mb3r0f5ecr3ts"

View file

@ -0,0 +1,89 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\Application\Tests;
use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class DisablingApiTest extends ApiTestCase
{
use SetUpTestsTrait;
public function setUp(): void
{
$this->setFixturesFiles([]);
$this->setUpTest();
}
/** @test */
public function it_gets_collection_if_api_is_enabled(): void
{
static::createClient()->request(
'GET',
'api/v2/admin/orders',
['auth_bearer' => $this->JWTAdminUserToken]
);
$this->assertResponseIsSuccessful();
}
/** @test */
public function it_returns_route_not_found_if_api_is_disabled(): void
{
$this->disableApi();
$this->expectException(NotFoundHttpException::class);
static::createClient()->request(
'GET',
'api/v2/admin/orders',
['auth_bearer' => $this->JWTAdminUserToken]
);
$this->assertResponseStatusCodeSame(404);
$this->enableApi();
static::createClient()->request(
'GET',
'api/v2/admin/orders',
['auth_bearer' => $this->JWTAdminUserToken]
);
$this->assertResponseIsSuccessful();
}
/** @test */
public function it_throws_not_found_exception_for_any_api_endpoint(): void
{
$this->disableApi();
$this->expectException(NotFoundHttpException::class);
static::createClient()->request(
'GET',
'api/v2/',
);
$this->assertResponseStatusCodeSame(404);
}
private function disableApi(): void
{
$_ENV['SYLIUS_API_ENABLED'] = false;
}
private function enableApi(): void
{
$_ENV['SYLIUS_API_ENABLED'] = true;
}
}

View file

@ -53,5 +53,7 @@ trait SetUpTestsTrait
$adminUser = $this->objects['admin'];
$this->JWTAdminUserToken = $JWTManager->create($adminUser);
$_ENV['SYLIUS_API_ENABLED'] = true;
}
}