Add explicit controller definition requirement for APIs

Updated API creation to require an explicit controller definition. This change has been reflected in the ChillMainExtension and ChillPersonExtension files. Also, it has introduced a new exception, the InvalidCrudConfiguration, which will be thrown when a new API or CRUD is created without this explicit controller definition.
This commit is contained in:
Julien Fastré 2024-04-08 15:38:05 +02:00
parent 78a3dfd65e
commit 76fdd6d889
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
16 changed files with 253 additions and 29 deletions

View File

@ -46,4 +46,72 @@
]);
```
- to keep cleaner definition in container's dependency injection and framework bundle, the definition of crud or api
requires to define explicitly a controller.
Before:
```php
$container->prependExtensionConfig('chill_main', [
'apis' => [
[
'class' => ThirdParty::class,
'name' => 'thirdparty',
'base_path' => '/api/1.0/thirdparty/thirdparty',
'actions' => [
'_entity' => [
'methods' => [
Request::METHOD_GET => true,
Request::METHOD_HEAD => true,
Request::METHOD_POST => true,
Request::METHOD_PUT => true,
Request::METHOD_PATCH => true,
],
'roles' => [
Request::METHOD_GET => ThirdPartyVoter::SHOW,
Request::METHOD_HEAD => ThirdPartyVoter::SHOW,
Request::METHOD_POST => ThirdPartyVoter::CREATE,
Request::METHOD_PUT => ThirdPartyVoter::CREATE,
Request::METHOD_PATCH => ThirdPartyVoter::CREATE,
],
],
],
],
],
]);
After:
```php
$container->prependExtensionConfig('chill_main', [
'apis' => [
[
'class' => ThirdParty::class,
'controller' => ThirdPartyApiController::class,
'name' => 'thirdparty',
'base_path' => '/api/1.0/thirdparty/thirdparty',
'actions' => [
'_entity' => [
'methods' => [
Request::METHOD_GET => true,
Request::METHOD_HEAD => true,
Request::METHOD_POST => true,
Request::METHOD_PUT => true,
Request::METHOD_PATCH => true,
],
'roles' => [
Request::METHOD_GET => ThirdPartyVoter::SHOW,
Request::METHOD_HEAD => ThirdPartyVoter::SHOW,
Request::METHOD_POST => ThirdPartyVoter::CREATE,
Request::METHOD_PUT => ThirdPartyVoter::CREATE,
Request::METHOD_PATCH => ThirdPartyVoter::CREATE,
],
],
],
],
],
]);
```

View File

@ -11,31 +11,6 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\Controller;
use Chill\DocStoreBundle\Entity\StoredObject;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Chill\MainBundle\CRUD\Controller\ApiController;
class StoredObjectApiController
{
public function __construct(private readonly Security $security) {}
#[Route(path: '/api/1.0/doc-store/stored-object/{uuid}/is-ready')]
public function isDocumentReady(StoredObject $storedObject): Response
{
if (!$this->security->isGranted('ROLE_USER')) {
throw new AccessDeniedHttpException();
}
return new JsonResponse(
[
'id' => $storedObject->getId(),
'filename' => $storedObject->getFilename(),
'status' => $storedObject->getStatus(),
'type' => $storedObject->getType(),
]
);
}
}
class StoredObjectApiController extends ApiController {}

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\DocStoreBundle\Controller;
use Chill\DocStoreBundle\Entity\StoredObject;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
class StoredObjectStatusApiController
{
public function __construct(private readonly Security $security) {}
#[Route(path: '/api/1.0/doc-store/stored-object/{uuid}/is-ready')]
public function isDocumentReady(StoredObject $storedObject): Response
{
if (!$this->security->isGranted('ROLE_USER')) {
throw new AccessDeniedHttpException();
}
return new JsonResponse(
[
'id' => $storedObject->getId(),
'filename' => $storedObject->getFilename(),
'status' => $storedObject->getStatus(),
'type' => $storedObject->getType(),
]
);
}
}

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\DependencyInjection;
use Chill\DocStoreBundle\Controller\StoredObjectApiController;
use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter;
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
use Symfony\Component\Config\FileLocator;
@ -57,6 +58,7 @@ class ChillDocStoreExtension extends Extension implements PrependExtensionInterf
'apis' => [
[
'class' => \Chill\DocStoreBundle\Entity\StoredObject::class,
'controller' => StoredObjectApiController::class,
'name' => 'stored_object',
'base_path' => '/api/1.0/docstore/stored-object',
'base_role' => 'ROLE_USER',

View File

@ -11,6 +11,9 @@ declare(strict_types=1);
namespace Chill\MainBundle\CRUD\CompilerPass;
use Chill\MainBundle\CRUD\Controller\ApiController;
use Chill\MainBundle\CRUD\Controller\CRUDController;
use Chill\MainBundle\CRUD\Exception\InvalidCrudConfiguration;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@ -38,6 +41,9 @@ class CRUDControllerCompilerPass implements CompilerPassInterface
private function configureCrudController(ContainerBuilder $container, array $crudEntry, string $apiOrCrud): void
{
$controllerClass = $crudEntry['controller'];
if (ApiController::class === $controllerClass || CRUDController::class === $controllerClass) {
throw InvalidCrudConfiguration::configurationRequiresControllerDefinition($crudEntry['class'], $apiOrCrud);
}
$controllerServiceName = 'cs'.$apiOrCrud.'_'.$crudEntry['name'].'_controller';
// create config parameter in container

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\CRUD\Exception;
class InvalidCrudConfiguration extends \RuntimeException
{
public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
public static function configurationRequiresControllerDefinition(string $class, string $apiOrCrud): self
{
return new self(sprintf('The definition requires that a controller definition exists in container configuration. Add a `controller` key to your %s definition, for class %s', $apiOrCrud, $class), 48);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
class CountryApiController extends ApiController {}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
class GeographicalUnitApiController extends ApiController {}

View File

@ -15,7 +15,9 @@ use Chill\MainBundle\Controller\AddressApiController;
use Chill\MainBundle\Controller\CenterController;
use Chill\MainBundle\Controller\CivilityApiController;
use Chill\MainBundle\Controller\CivilityController;
use Chill\MainBundle\Controller\CountryApiController;
use Chill\MainBundle\Controller\CountryController;
use Chill\MainBundle\Controller\GeographicalUnitApiController;
use Chill\MainBundle\Controller\LanguageController;
use Chill\MainBundle\Controller\LocationController;
use Chill\MainBundle\Controller\LocationTypeController;
@ -667,6 +669,7 @@ class ChillMainExtension extends Extension implements
],
[
'class' => Country::class,
'controller' => CountryApiController::class,
'name' => 'country',
'base_path' => '/api/1.0/main/country',
'base_role' => 'ROLE_USER',
@ -787,6 +790,7 @@ class ChillMainExtension extends Extension implements
],
[
'class' => GeographicalUnitLayer::class,
'controller' => GeographicalUnitApiController::class,
'name' => 'geographical-unit-layer',
'base_path' => '/api/1.0/main/geographical-unit-layer',
'base_role' => 'ROLE_USER',

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
class AccompanyingPeriodCommentApiController extends ApiController {}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
class AccompanyingPeriodResourceApiController extends ApiController {}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
class RelationApiController extends ApiController {}

View File

@ -17,11 +17,10 @@ use Chill\PersonBundle\Repository\Relationships\RelationshipRepository;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class RelationshipApiController extends ApiController
{
public function __construct(private readonly ValidatorInterface $validator, private readonly RelationshipRepository $repository) {}
public function __construct(private readonly RelationshipRepository $repository) {}
/**
* @ParamConverter("person", options={"id": "person_id"})

View File

@ -13,7 +13,10 @@ namespace Chill\PersonBundle\DependencyInjection;
use Chill\MainBundle\DependencyInjection\MissingBundleException;
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
use Chill\PersonBundle\Controller\AccompanyingPeriodCommentApiController;
use Chill\PersonBundle\Controller\AccompanyingPeriodResourceApiController;
use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController;
use Chill\PersonBundle\Controller\RelationApiController;
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter;
@ -537,6 +540,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
],
[
'class' => AccompanyingPeriod\Comment::class,
'controller' => AccompanyingPeriodCommentApiController::class,
'name' => 'accompanying_period_comment',
'base_path' => '/api/1.0/person/accompanying-period/comment',
'base_role' => 'ROLE_USER',
@ -556,6 +560,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
],
[
'class' => AccompanyingPeriod\Resource::class,
'controller' => AccompanyingPeriodResourceApiController::class,
'name' => 'accompanying_period_resource',
'base_path' => '/api/1.0/person/accompanying-period/resource',
'base_role' => 'ROLE_USER',
@ -874,6 +879,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
],
[
'class' => \Chill\PersonBundle\Entity\Relationships\Relation::class,
'controller' => RelationApiController::class,
'name' => 'relations',
'base_path' => '/api/1.0/relations/relation',
'base_role' => 'ROLE_USER',

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ThirdPartyBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
class ThirdPartyApiController extends ApiController {}

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\ThirdPartyBundle\DependencyInjection;
use Chill\ThirdPartyBundle\Controller\ThirdPartyApiController;
use Chill\ThirdPartyBundle\Controller\ThirdPartyCategoryController;
use Chill\ThirdPartyBundle\Controller\ThirdPartyController;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
@ -128,6 +129,7 @@ class ChillThirdPartyExtension extends Extension implements PrependExtensionInte
'apis' => [
[
'class' => ThirdParty::class,
'controller' => ThirdPartyApiController::class,
'name' => 'thirdparty',
'base_path' => '/api/1.0/thirdparty/thirdparty',
// 'base_role' => \Chill\ThirdPartyBundle\Security\Authorization\ThirdPartyVoter::SHOW,