From 92ddec13c47648221b91e97c0158e1b431da2507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Fri, 7 Oct 2016 14:29:44 +0200 Subject: [PATCH 01/12] Add documentation about doctrine query extensions --- core/extensions.md | 165 +++++++++++++++++++++ core/filters.md | 2 +- core/serialization-groups-and-relations.md | 2 +- index.md | 33 +++-- 4 files changed, 185 insertions(+), 17 deletions(-) create mode 100644 core/extensions.md diff --git a/core/extensions.md b/core/extensions.md new file mode 100644 index 00000000000..d41e65ddbd8 --- /dev/null +++ b/core/extensions.md @@ -0,0 +1,165 @@ +# Extensions + +API Platform Core provides a system to extends queries on items and collections readings. +You can create custom extension that fit your needs. + +## Custom Extension + +If Doctrine ORM support is enabled, adding extension is as easy as registering a service in your `app/config/services.yml` file and create the extension you need. + +Custom extension can be written by implementing the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface` +and / or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface` +interfaces, depending on your whether you asking for a collection of items or just an item. + +If you use [custom data providers](data-providers.md), they must support extensions and be aware of active extensions to work +properly. + +## Filter upon the current user + +In the following example, we will see how to always get the offers owned by the current user. We will set up an exception, whenever the user possesses the `ROLE_ADMIN`. +Given these two entities : + +```php +propertyMetadataFactory = $propertyMetadataFactory; + $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; + $this->token = $token; + $this->authorizationChecker = $checker; + } + + /** + * {@inheritdoc} + */ + public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null) + { + $this->addWhere($queryBuilder, $resourceClass); + } + + /** + * {@inheritdoc} + */ + public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null) + { + $this->addWhere($queryBuilder, $resourceClass); + } + + /** + * Add where condition + * + * @param QueryBuilder $queryBuilder + * @param string $resourceClass + */ + private function addWhere(QueryBuilder $queryBuilder, string $resourceClass) + { + if (Offer::class !== $resourceClass || $this->authorizationChecker->isGranted('ROLE_ADMIN')) { + return; + } + + $classMetadata = $queryBuilder->getEntityManager()->getClassMetadata($resourceClass); + $user = $this->token->getToken()->getUser(); + + foreach ($classMetadata->getAssociationNames() as $i => $association) { + $mapping = $classMetadata->associationMappings[$association]; + + if (User::class === $mapping['targetEntity']) { + $queryBuilder->andWhere('o.'.$association.' = '.$user->getId()); + return; + } + } + } +} + +``` + +Finally register the custom extension: + +```yaml +# app/config/services.yml + +services: + app.doctrine.orm.query_extension.current_user: + class: AppBundle\Doctrine\ORM\Extension\CurrentUserExtension + public: false + arguments: + - '@api_platform.metadata.property.name_collection_factory' + - '@api_platform.metadata.property.metadata_factory' + - '@security.token_storage' + - '@security.authorization_checker' + tags: + - { name: api_platform.doctrine.orm.query_extension.collection, priority: 64 } + - { name: api_platform.doctrine.orm.query_extension.item, priority: 64 } +``` + +Having the item related tag and interface, allows you to customize the query when trying to get/read a specific Item. +Having the collection related tag and interface, allows you to customize the query when trying to get/read a collection of items. + +Previous chapter: [Filters](filters.md) + +Next chapter: [Serialization Groups and Relations](serialization-groups-and-relations.md) \ No newline at end of file diff --git a/core/filters.md b/core/filters.md index e157039b672..1de1240be88 100644 --- a/core/filters.md +++ b/core/filters.md @@ -402,4 +402,4 @@ services: Previous chapter: [Operations](operations.md) -Next chapter: [Serialization Groups and Relations](serialization-groups-and-relations.md) +Next chapter: [Extensions](extensions.md) diff --git a/core/serialization-groups-and-relations.md b/core/serialization-groups-and-relations.md index 5850eee4a6e..93693cdc209 100644 --- a/core/serialization-groups-and-relations.md +++ b/core/serialization-groups-and-relations.md @@ -333,7 +333,7 @@ final class BookContextBuilder implements SerializerContextBuilderInterface { $context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes); $subject = $request->attributes->get('data'); - + if ($subject instanceof Book && $this->authorizationChecker->isGranted('ROLE_ADMIN') && false === $normalization) { $context['groups'][] = 'admin_input'; } diff --git a/index.md b/index.md index 7bbdd0fbc09..ce4656048fe 100644 --- a/index.md +++ b/index.md @@ -30,7 +30,10 @@ 8. [Creating Custom Filters](core/filters.md#creating-custom-filters) 1. [Creating Custom Doctrine ORM Filters](core/filters.md#creating-custom-doctrine-orm-filters) 2. [Overriding Extraction of Properties from the Request](core/filters.md#overriding-extraction-of-properties-from-the-request) -6. [Serialization Groups and Relations](core/serialization-groups-and-relations.md) +6. [Extensions](core/extensions.md) + 1. [Custom Extension](core/extensions.md#custom-extension) + 2. [Filter upon the current user](core/extensions.md#filter-upon-the-current-user) +7. [Serialization Groups and Relations](core/serialization-groups-and-relations.md) 1. [Configuration](core/serialization-groups-and-relations.md#configuration) 2. [Using Different Serialization Groups per Operation](core/serialization-groups-and-relations.md#embedding-relations) 3. [Embedding Relations](core/serialization-groups-and-relations.md#embedding-relations) @@ -41,40 +44,40 @@ 5. [Entity Identifier Case](core/serialization-groups-and-relations.md#entity-identifier-case) 6. [Writable Entity Identifier](core/serialization-groups-and-relations.md#writable-entity-identifier) 7. [Embedding the Context](core/serialization-groups-and-relations.md#embedding-the-context) -7. [Validation](core/validation.md) +8. [Validation](core/validation.md) 1. [Using Validation Groups](core/validation.md#using-validation-groups) 2. [Dynamic Validation Groups](core/validation.md#dynamic-validation-groups) -8. [Pagination](core/pagination.md) +9. [Pagination](core/pagination.md) 1. [Disabling the Pagination](core/pagination.md#disabling-the-pagination) 2. [Changing the Number of Items per Page](core/pagination.md#changing-the-number-of-items-per-page) -9. [The Event System](core/events.md) -10. [Content Negotiation](core/content-negotiation.md) +10. [The Event System](core/events.md) +11. [Content Negotiation](core/content-negotiation.md) 1. [Enabling Several Formats](core/content-negotiation.md#enabling-several-formats) 2. [Registering a Custom Serializer](core/content-negotiation.md#registering-a-custom-serializer) 3. [Creating a Responder](core/content-negotiation.md#creating-a-responder) -11. [Using External JSON-LD Vocabularies](core/external-vocabularies.md) -12. [Extending JSON-LD context](core/extending-jsonld-context.md) -13. [Data Providers](core/data-providers.md) +12. [Using External JSON-LD Vocabularies](core/external-vocabularies.md) +13. [Extending JSON-LD context](core/extending-jsonld-context.md) +14. [Data Providers](core/data-providers.md) 1. [Custom Collection Data Provider](core/data-providers.md#creating-a-custom-data-provider#custom-collection-data-provider) 2. [Custom Item Data Provider](core/data-providers.md#returning-a-paged-collection#custom-item-data-provider) -14. [Security](core/security.md) -15. [Performance](core/performance.md) +15. [Security](core/security.md) +16. [Performance](core/performance.md) 1. [Enabling the Metadata Cache](core/performance.md#enabling-the-metadata-cache) 2. [Using PPM (PHP-PM)](core/performance.md#using-ppm-php-pm) 3. [Doctrine Queries and Indexes](core/performance.md#doctrine-queries-and-indexes) 1. [Search Filter](core/performance.md#search-filter) 2. [Unserialized Properties Hydratation](core/performance.md#unserialized-properties-hydratation) -16. [Operation Path Naming](core/operation-path-naming.md) +17. [Operation Path Naming](core/operation-path-naming.md) 1. [Configuration](core/operation-path-naming.md#configuration) 2. [Create a Custom Operation Path Naming](core/operation-path-naming.md#create-a-custom-operation-path-resolver) 1. [Defining the Operation Path Naming](core/operation-path-naming.md#defining-the-operation-path-resolver) 2. [Registering the Service](core/operation-path-naming.md#registering-the-service) 3. [Configure it](core/operation-path-naming.md#configure-it) -17. [Accept `application/x-www-form-urlencoded` Form Data] (core/form-data.md) -18. [FOSUserBundle Integration](core/fosuser-bundle.md) +18. [Accept `application/x-www-form-urlencoded` Form Data] (core/form-data.md) +19. [FOSUserBundle Integration](core/fosuser-bundle.md) 1. [Creating a `User` Entity with Serialization Groups](core/fosuser-bundle.md#creating-a-user-entity-with-serialization-groups) -19. [NelmioApiDocBundle integration](core/nelmio-api-doc.md) -20. [AngularJS Integration](core/angularjs-integration.md) +20. [NelmioApiDocBundle integration](core/nelmio-api-doc.md) +21. [AngularJS Integration](core/angularjs-integration.md) 1. [Restangular](core/angularjs-integration.md#restangular) 2. [ng-admin](core/angularjs-integration.md#ng-admin) From ffef6c82560de5cc50375dd6f93d0eef21e92844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Fri, 7 Oct 2016 16:30:27 +0200 Subject: [PATCH 02/12] Update extensions.md --- core/extensions.md | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/core/extensions.md b/core/extensions.md index d41e65ddbd8..5980f4e3670 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -73,7 +73,6 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use AppBundle\Entity\Offer; -use AppBundle\Entity\User; use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\Query\Expr; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; @@ -118,20 +117,10 @@ final class CurrentUserExtension implements QueryCollectionExtensionInterface, Q */ private function addWhere(QueryBuilder $queryBuilder, string $resourceClass) { - if (Offer::class !== $resourceClass || $this->authorizationChecker->isGranted('ROLE_ADMIN')) { - return; - } - - $classMetadata = $queryBuilder->getEntityManager()->getClassMetadata($resourceClass); - $user = $this->token->getToken()->getUser(); - - foreach ($classMetadata->getAssociationNames() as $i => $association) { - $mapping = $classMetadata->associationMappings[$association]; - - if (User::class === $mapping['targetEntity']) { - $queryBuilder->andWhere('o.'.$association.' = '.$user->getId()); - return; - } + if (Offer::class === $resourceClass && !$this->authorizationChecker->isGranted('ROLE_ADMIN')) { + $user = $this->token->getToken()->getUser(); + $rootAlias = $queryBuilder->getRootAliases()[0]; + $queryBuilder->andWhere(sprintf('%s.user = ', $rootAlias).$user->getId()); } } } From e768e62cc07392e7e4b1ff1c7c202c99ce76e93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Fri, 7 Oct 2016 16:48:05 +0200 Subject: [PATCH 03/12] Update extensions.md --- core/extensions.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/core/extensions.md b/core/extensions.md index 5980f4e3670..ae921fe5ab0 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -1,23 +1,22 @@ # Extensions -API Platform Core provides a system to extends queries on items and collections readings. -You can create custom extension that fit your needs. +API Platform Core provides a system to extend queries on items and collections. ## Custom Extension -If Doctrine ORM support is enabled, adding extension is as easy as registering a service in your `app/config/services.yml` file and create the extension you need. +If Doctrine ORM support is enabled, adding an extension is as easy as registering a service in your `app/config/services.yml` file and create the class you need. -Custom extension can be written by implementing the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface` +Custom extension must implement the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface` and / or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface` -interfaces, depending on your whether you asking for a collection of items or just an item. +interfaces, depending if you are asking for a collection of items or just an item. If you use [custom data providers](data-providers.md), they must support extensions and be aware of active extensions to work properly. ## Filter upon the current user -In the following example, we will see how to always get the offers owned by the current user. We will set up an exception, whenever the user possesses the `ROLE_ADMIN`. -Given these two entities : +In the following example, we will see how to always get the offers owned by the current user. We will set up an exception, whenever the user has the `ROLE_ADMIN`. +Given these two entities: ```php authorizationChecker->isGranted('ROLE_ADMIN')) { - $user = $this->token->getToken()->getUser(); + $user = $this->token->getToken()->getUser(); + if ($user instanceof User && Offer::class === $resourceClass && !$this->authorizationChecker->isGranted('ROLE_ADMIN')) { $rootAlias = $queryBuilder->getRootAliases()[0]; - $queryBuilder->andWhere(sprintf('%s.user = ', $rootAlias).$user->getId()); + $queryBuilder->andWhere(sprintf('%s.user = :current_user', $rootAlias)); + $queryBuilder->setParameter('current_user', $user->getId()); } } } @@ -146,8 +146,8 @@ services: - { name: api_platform.doctrine.orm.query_extension.item, priority: 64 } ``` -Having the item related tag and interface, allows you to customize the query when trying to get/read a specific Item. -Having the collection related tag and interface, allows you to customize the query when trying to get/read a collection of items. +Thanks to the api_platform.doctrine.orm.query_extension.collection tag, API Platform will register this service as a collection extension. +The api_platform.doctrine.orm.query_extension.item do the same thing for items. Previous chapter: [Filters](filters.md) From a9b640e7a82e12d1fcdda9ac45ef3c4b947bc4be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Fri, 7 Oct 2016 17:11:45 +0200 Subject: [PATCH 04/12] Update extensions.md --- core/extensions.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/extensions.md b/core/extensions.md index ae921fe5ab0..ac18135ae0c 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -2,9 +2,12 @@ API Platform Core provides a system to extend queries on items and collections. +Extensions are specific to Doctrine, and therefor, the Doctrine ORM support must be enabled. +If you use custom providers, they should support extensions and be aware of active extensions OR implement their own extension systems. + ## Custom Extension -If Doctrine ORM support is enabled, adding an extension is as easy as registering a service in your `app/config/services.yml` file and create the class you need. +Adding an extension is as easy as registering a service in your `app/config/services.yml` file and create the class you need. Custom extension must implement the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface` and / or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface` From 46e0a5c712920f9b93661d8004b8bad61128480d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Sat, 8 Oct 2016 14:10:10 +0200 Subject: [PATCH 05/12] adds explanations about priorities on extensions.md --- core/extensions.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/extensions.md b/core/extensions.md index ac18135ae0c..a1454e6f78d 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -145,13 +145,18 @@ services: - '@security.token_storage' - '@security.authorization_checker' tags: - - { name: api_platform.doctrine.orm.query_extension.collection, priority: 64 } - - { name: api_platform.doctrine.orm.query_extension.item, priority: 64 } + - { name: api_platform.doctrine.orm.query_extension.collection, priority: 9 } + - { name: api_platform.doctrine.orm.query_extension.item } ``` Thanks to the api_platform.doctrine.orm.query_extension.collection tag, API Platform will register this service as a collection extension. The api_platform.doctrine.orm.query_extension.item do the same thing for items. +Notice the priority level for the Collection tag. +There is a case, when an extension implements the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface` or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface` and supports to immediately return results, +any lower priority extension will not be executed. +In our case, since the pagination is activated by default ([see how to disable the pagination](pagination.md#disabling-the-pagination)) and the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension` is declared with a priority 8, we must declare a priority to at least 9 to ensure it's execution. + Previous chapter: [Filters](filters.md) Next chapter: [Serialization Groups and Relations](serialization-groups-and-relations.md) \ No newline at end of file From 03b71532358d81cf8ff102d77b0f75b809336495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Thu, 13 Oct 2016 13:51:12 +0200 Subject: [PATCH 06/12] Rephrasing, cleaning and adding security --- core/extensions.md | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/core/extensions.md b/core/extensions.md index a1454e6f78d..58497a394f3 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -2,8 +2,8 @@ API Platform Core provides a system to extend queries on items and collections. -Extensions are specific to Doctrine, and therefor, the Doctrine ORM support must be enabled. -If you use custom providers, they should support extensions and be aware of active extensions OR implement their own extension systems. +Extensions are specific to Doctrine, and therefore, the Doctrine ORM support must be enabled to use this feature. +If you use custom providers it's up to you to implement your own extension system or not. ## Custom Extension @@ -16,7 +16,7 @@ interfaces, depending if you are asking for a collection of items or just an ite If you use [custom data providers](data-providers.md), they must support extensions and be aware of active extensions to work properly. -## Filter upon the current user +## Example In the following example, we will see how to always get the offers owned by the current user. We will set up an exception, whenever the user has the `ROLE_ADMIN`. Given these two entities: @@ -36,7 +36,6 @@ class User { // ... } - ``` ```php @@ -60,7 +59,6 @@ class Offer //... } - ``` ```php @@ -149,13 +147,38 @@ services: - { name: api_platform.doctrine.orm.query_extension.item } ``` -Thanks to the api_platform.doctrine.orm.query_extension.collection tag, API Platform will register this service as a collection extension. -The api_platform.doctrine.orm.query_extension.item do the same thing for items. +Thanks to the `api_platform.doctrine.orm.query_extension.collection` tag, API Platform will register this service as a collection extension. +The `api_platform.doctrine.orm.query_extension.item` do the same thing for items. -Notice the priority level for the Collection tag. -There is a case, when an extension implements the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface` or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface` and supports to immediately return results, +Notice the priority level for the `api_platform.doctrine.orm.query_extension.collection` tag. +When an extension implements the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface` or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface` interface to return results by itself, any lower priority extension will not be executed. -In our case, since the pagination is activated by default ([see how to disable the pagination](pagination.md#disabling-the-pagination)) and the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension` is declared with a priority 8, we must declare a priority to at least 9 to ensure it's execution. +Because the pagination is enabled by default with a priority of 8, the priority of the `app.doctrine.orm.query_extension.current_user` service must be at least 9 to ensure its execution. + +### Note + +This example adds a WHERE condition only when a fully authenticated user without ROLE_ADMIN tries to access to a resource. +That mean it return without restriction any item or collection for every other user. +You need to ensure that your user is authenticated to access the two endpoints. + +A way of doing it, is with the access control : + +```yaml +# app/config/security.yml + +security: + # ... + + firewalls: + # ... + default: + # ... + + access_control: + # ... + - { path: ^/offers, roles: IS_AUTHENTICATED_FULLY } + - { path: ^/users, roles: IS_AUTHENTICATED_FULLY } +``` Previous chapter: [Filters](filters.md) From 4583492084dcc856d8ff1d36a7a4e721313b6c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Fri, 14 Oct 2016 14:06:31 +0200 Subject: [PATCH 07/12] style: improve .md style --- core/extensions.md | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/core/extensions.md b/core/extensions.md index 58497a394f3..8276c58bd0c 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -2,23 +2,18 @@ API Platform Core provides a system to extend queries on items and collections. -Extensions are specific to Doctrine, and therefore, the Doctrine ORM support must be enabled to use this feature. -If you use custom providers it's up to you to implement your own extension system or not. +Extensions are specific to Doctrine, and therefore, the Doctrine ORM support must be enabled to use this feature. If you use custom providers it's up to you to implement your own extension system or not. ## Custom Extension -Adding an extension is as easy as registering a service in your `app/config/services.yml` file and create the class you need. +Custom extensions must implement the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface` and / or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface` interfaces, to be run when querying for a collection of items and when querying for an item respectively. -Custom extension must implement the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface` -and / or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface` -interfaces, depending if you are asking for a collection of items or just an item. - -If you use [custom data providers](data-providers.md), they must support extensions and be aware of active extensions to work -properly. +If you use [custom data providers](data-providers.md), they must support extensions and be aware of active extensions to work properly. ## Example In the following example, we will see how to always get the offers owned by the current user. We will set up an exception, whenever the user has the `ROLE_ADMIN`. + Given these two entities: ```php @@ -147,19 +142,13 @@ services: - { name: api_platform.doctrine.orm.query_extension.item } ``` -Thanks to the `api_platform.doctrine.orm.query_extension.collection` tag, API Platform will register this service as a collection extension. -The `api_platform.doctrine.orm.query_extension.item` do the same thing for items. +Thanks to the `api_platform.doctrine.orm.query_extension.collection` tag, API Platform will register this service as a collection extension. The `api_platform.doctrine.orm.query_extension.item` do the same thing for items. -Notice the priority level for the `api_platform.doctrine.orm.query_extension.collection` tag. -When an extension implements the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface` or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface` interface to return results by itself, -any lower priority extension will not be executed. -Because the pagination is enabled by default with a priority of 8, the priority of the `app.doctrine.orm.query_extension.current_user` service must be at least 9 to ensure its execution. +Notice the priority level for the `api_platform.doctrine.orm.query_extension.collection` tag. When an extension implements the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface` or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface` interface to return results by itself, any lower priority extension will not be executed. Because the pagination is enabled by default with a priority of 8, the priority of the `app.doctrine.orm.query_extension.current_user` service must be at least 9 to ensure its execution. ### Note -This example adds a WHERE condition only when a fully authenticated user without ROLE_ADMIN tries to access to a resource. -That mean it return without restriction any item or collection for every other user. -You need to ensure that your user is authenticated to access the two endpoints. +This example adds a WHERE condition only when a fully authenticated user without ROLE_ADMIN tries to access to a resource. That mean it return without restriction any item or collection for every other user. You need to ensure that your user is authenticated to access the two endpoints. A way of doing it, is with the access control : From f016600390db42f76bd7493a1bf174a76fd3e6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Mon, 17 Oct 2016 14:41:29 +0200 Subject: [PATCH 08/12] Update extensions.md --- core/extensions.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/core/extensions.md b/core/extensions.md index 8276c58bd0c..af3f5710610 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -146,11 +146,11 @@ Thanks to the `api_platform.doctrine.orm.query_extension.collection` tag, API Pl Notice the priority level for the `api_platform.doctrine.orm.query_extension.collection` tag. When an extension implements the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultCollectionExtensionInterface` or the `ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface` interface to return results by itself, any lower priority extension will not be executed. Because the pagination is enabled by default with a priority of 8, the priority of the `app.doctrine.orm.query_extension.current_user` service must be at least 9 to ensure its execution. -### Note +### Blocking Anonymous Users -This example adds a WHERE condition only when a fully authenticated user without ROLE_ADMIN tries to access to a resource. That mean it return without restriction any item or collection for every other user. You need to ensure that your user is authenticated to access the two endpoints. +This example adds a `WHERE` clause condition only when a fully authenticated user without `ROLE_ADMIN` tries to access to a resource. It means that anonymous users will be able to access to all data. To prevent this potential security issue, the API must ensure that the current user is authenticated. -A way of doing it, is with the access control : +To secure the access to endpoints, use the following access control rule: ```yaml # app/config/security.yml @@ -158,11 +158,6 @@ A way of doing it, is with the access control : security: # ... - firewalls: - # ... - default: - # ... - access_control: # ... - { path: ^/offers, roles: IS_AUTHENTICATED_FULLY } From 2d805d7af347a22033610965eebd5ef989fc654d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Thu, 20 Oct 2016 20:01:19 +0200 Subject: [PATCH 09/12] style: new break line on extension chapter and fix index --- core/serialization-groups-and-relations.md | 2 +- index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/serialization-groups-and-relations.md b/core/serialization-groups-and-relations.md index 93693cdc209..838c90305b7 100644 --- a/core/serialization-groups-and-relations.md +++ b/core/serialization-groups-and-relations.md @@ -445,6 +445,6 @@ class Book } ``` -Previous chapter: [Filters](filters.md) +Previous chapter: [Extensions](extensions.md) Next chapter: [Validation](validation.md) diff --git a/index.md b/index.md index ce4656048fe..9e4bf777544 100644 --- a/index.md +++ b/index.md @@ -32,7 +32,7 @@ 2. [Overriding Extraction of Properties from the Request](core/filters.md#overriding-extraction-of-properties-from-the-request) 6. [Extensions](core/extensions.md) 1. [Custom Extension](core/extensions.md#custom-extension) - 2. [Filter upon the current user](core/extensions.md#filter-upon-the-current-user) + 2. [Filter upon the current user](core/extensions.md#example) 7. [Serialization Groups and Relations](core/serialization-groups-and-relations.md) 1. [Configuration](core/serialization-groups-and-relations.md#configuration) 2. [Using Different Serialization Groups per Operation](core/serialization-groups-and-relations.md#embedding-relations) From 7775488c640fa8c82843f7687fabe885fd379030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Mon, 24 Oct 2016 14:40:47 +0200 Subject: [PATCH 10/12] style: move extension.md TOC further --- core/data-providers.md | 2 +- core/extensions.md | 4 +-- core/filters.md | 2 +- core/security.md | 2 +- core/serialization-groups-and-relations.md | 2 +- index.md | 36 +++++++++++----------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/core/data-providers.md b/core/data-providers.md index 46ca7595370..d472610820d 100644 --- a/core/data-providers.md +++ b/core/data-providers.md @@ -115,4 +115,4 @@ services: Previous chapter: [Extending JSON-LD context](extending-jsonld-context.md) -Next chapter: [Security](security.md) +Next chapter: [Extensions](core/extensions.md) diff --git a/core/extensions.md b/core/extensions.md index af3f5710610..7d32ab4e315 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -164,6 +164,6 @@ security: - { path: ^/users, roles: IS_AUTHENTICATED_FULLY } ``` -Previous chapter: [Filters](filters.md) +Previous chapter: [Data Providers](core/data-providers.md) -Next chapter: [Serialization Groups and Relations](serialization-groups-and-relations.md) \ No newline at end of file +Next chapter: [Security](core/security.md) \ No newline at end of file diff --git a/core/filters.md b/core/filters.md index 1de1240be88..ccc9cf11802 100644 --- a/core/filters.md +++ b/core/filters.md @@ -402,4 +402,4 @@ services: Previous chapter: [Operations](operations.md) -Next chapter: [Extensions](extensions.md) +Next chapter: [Serialization Groups and Relations](core/serialization-groups-and-relations.md) diff --git a/core/security.md b/core/security.md index 357784be931..42bb8b8db37 100644 --- a/core/security.md +++ b/core/security.md @@ -9,6 +9,6 @@ For instance, if you wish to restrict the access of some endpoints, you can use It is also possible to use the [event system](events.md) for more advanced logic or even [custom actions](operations.md#creating-custom-operations-and-controllers) if you really need to. -Previous chapter: [Data Providers](data-providers.md) +Previous chapter: [Extensions](core/extensions.md) Next chapter: [Performance](performance.md) diff --git a/core/serialization-groups-and-relations.md b/core/serialization-groups-and-relations.md index 838c90305b7..a98de6b3dd7 100644 --- a/core/serialization-groups-and-relations.md +++ b/core/serialization-groups-and-relations.md @@ -445,6 +445,6 @@ class Book } ``` -Previous chapter: [Extensions](extensions.md) +Previous chapter: [Filters](core/filters.md) Next chapter: [Validation](validation.md) diff --git a/index.md b/index.md index 9e4bf777544..824b7a92f4f 100644 --- a/index.md +++ b/index.md @@ -30,10 +30,7 @@ 8. [Creating Custom Filters](core/filters.md#creating-custom-filters) 1. [Creating Custom Doctrine ORM Filters](core/filters.md#creating-custom-doctrine-orm-filters) 2. [Overriding Extraction of Properties from the Request](core/filters.md#overriding-extraction-of-properties-from-the-request) -6. [Extensions](core/extensions.md) - 1. [Custom Extension](core/extensions.md#custom-extension) - 2. [Filter upon the current user](core/extensions.md#example) -7. [Serialization Groups and Relations](core/serialization-groups-and-relations.md) +6. [Serialization Groups and Relations](core/serialization-groups-and-relations.md) 1. [Configuration](core/serialization-groups-and-relations.md#configuration) 2. [Using Different Serialization Groups per Operation](core/serialization-groups-and-relations.md#embedding-relations) 3. [Embedding Relations](core/serialization-groups-and-relations.md#embedding-relations) @@ -44,40 +41,43 @@ 5. [Entity Identifier Case](core/serialization-groups-and-relations.md#entity-identifier-case) 6. [Writable Entity Identifier](core/serialization-groups-and-relations.md#writable-entity-identifier) 7. [Embedding the Context](core/serialization-groups-and-relations.md#embedding-the-context) -8. [Validation](core/validation.md) +7. [Validation](core/validation.md) 1. [Using Validation Groups](core/validation.md#using-validation-groups) 2. [Dynamic Validation Groups](core/validation.md#dynamic-validation-groups) -9. [Pagination](core/pagination.md) +8. [Pagination](core/pagination.md) 1. [Disabling the Pagination](core/pagination.md#disabling-the-pagination) 2. [Changing the Number of Items per Page](core/pagination.md#changing-the-number-of-items-per-page) -10. [The Event System](core/events.md) -11. [Content Negotiation](core/content-negotiation.md) +9. [The Event System](core/events.md) +10. [Content Negotiation](core/content-negotiation.md) 1. [Enabling Several Formats](core/content-negotiation.md#enabling-several-formats) 2. [Registering a Custom Serializer](core/content-negotiation.md#registering-a-custom-serializer) 3. [Creating a Responder](core/content-negotiation.md#creating-a-responder) -12. [Using External JSON-LD Vocabularies](core/external-vocabularies.md) -13. [Extending JSON-LD context](core/extending-jsonld-context.md) -14. [Data Providers](core/data-providers.md) +11. [Using External JSON-LD Vocabularies](core/external-vocabularies.md) +12. [Extending JSON-LD context](core/extending-jsonld-context.md) +13. [Data Providers](core/data-providers.md) 1. [Custom Collection Data Provider](core/data-providers.md#creating-a-custom-data-provider#custom-collection-data-provider) 2. [Custom Item Data Provider](core/data-providers.md#returning-a-paged-collection#custom-item-data-provider) -15. [Security](core/security.md) -16. [Performance](core/performance.md) +14. [Extensions](core/extensions.md) + 1. [Custom Extension](core/extensions.md#custom-extension) + 2. [Filter upon the current user](core/extensions.md#example) +16. [Security](core/security.md) +17. [Performance](core/performance.md) 1. [Enabling the Metadata Cache](core/performance.md#enabling-the-metadata-cache) 2. [Using PPM (PHP-PM)](core/performance.md#using-ppm-php-pm) 3. [Doctrine Queries and Indexes](core/performance.md#doctrine-queries-and-indexes) 1. [Search Filter](core/performance.md#search-filter) 2. [Unserialized Properties Hydratation](core/performance.md#unserialized-properties-hydratation) -17. [Operation Path Naming](core/operation-path-naming.md) +18. [Operation Path Naming](core/operation-path-naming.md) 1. [Configuration](core/operation-path-naming.md#configuration) 2. [Create a Custom Operation Path Naming](core/operation-path-naming.md#create-a-custom-operation-path-resolver) 1. [Defining the Operation Path Naming](core/operation-path-naming.md#defining-the-operation-path-resolver) 2. [Registering the Service](core/operation-path-naming.md#registering-the-service) 3. [Configure it](core/operation-path-naming.md#configure-it) -18. [Accept `application/x-www-form-urlencoded` Form Data] (core/form-data.md) -19. [FOSUserBundle Integration](core/fosuser-bundle.md) +19. [Accept `application/x-www-form-urlencoded` Form Data] (core/form-data.md) +20. [FOSUserBundle Integration](core/fosuser-bundle.md) 1. [Creating a `User` Entity with Serialization Groups](core/fosuser-bundle.md#creating-a-user-entity-with-serialization-groups) -20. [NelmioApiDocBundle integration](core/nelmio-api-doc.md) -21. [AngularJS Integration](core/angularjs-integration.md) +21. [NelmioApiDocBundle integration](core/nelmio-api-doc.md) +22. [AngularJS Integration](core/angularjs-integration.md) 1. [Restangular](core/angularjs-integration.md#restangular) 2. [ng-admin](core/angularjs-integration.md#ng-admin) From c325bbc662db3ecfbc003f38478b778a3a1c6ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Mon, 24 Oct 2016 14:44:34 +0200 Subject: [PATCH 11/12] style: move extension.md TOC further --- core/data-providers.md | 2 +- core/extensions.md | 2 +- core/filters.md | 2 +- core/security.md | 2 +- core/serialization-groups-and-relations.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/data-providers.md b/core/data-providers.md index d472610820d..819e4175c28 100644 --- a/core/data-providers.md +++ b/core/data-providers.md @@ -115,4 +115,4 @@ services: Previous chapter: [Extending JSON-LD context](extending-jsonld-context.md) -Next chapter: [Extensions](core/extensions.md) +Next chapter: [Extensions](extensions.md) diff --git a/core/extensions.md b/core/extensions.md index 7d32ab4e315..c7b883c652b 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -164,6 +164,6 @@ security: - { path: ^/users, roles: IS_AUTHENTICATED_FULLY } ``` -Previous chapter: [Data Providers](core/data-providers.md) +Previous chapter: [Data Providers](data-providers.md) Next chapter: [Security](core/security.md) \ No newline at end of file diff --git a/core/filters.md b/core/filters.md index ccc9cf11802..e157039b672 100644 --- a/core/filters.md +++ b/core/filters.md @@ -402,4 +402,4 @@ services: Previous chapter: [Operations](operations.md) -Next chapter: [Serialization Groups and Relations](core/serialization-groups-and-relations.md) +Next chapter: [Serialization Groups and Relations](serialization-groups-and-relations.md) diff --git a/core/security.md b/core/security.md index 42bb8b8db37..d820daed427 100644 --- a/core/security.md +++ b/core/security.md @@ -9,6 +9,6 @@ For instance, if you wish to restrict the access of some endpoints, you can use It is also possible to use the [event system](events.md) for more advanced logic or even [custom actions](operations.md#creating-custom-operations-and-controllers) if you really need to. -Previous chapter: [Extensions](core/extensions.md) +Previous chapter: [Extensions](extensions.md) Next chapter: [Performance](performance.md) diff --git a/core/serialization-groups-and-relations.md b/core/serialization-groups-and-relations.md index a98de6b3dd7..93693cdc209 100644 --- a/core/serialization-groups-and-relations.md +++ b/core/serialization-groups-and-relations.md @@ -445,6 +445,6 @@ class Book } ``` -Previous chapter: [Filters](core/filters.md) +Previous chapter: [Filters](filters.md) Next chapter: [Validation](validation.md) From 7e2565219ca31f8086e8203141c4db67fe494de2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20H=C3=A9bert?= Date: Mon, 24 Oct 2016 14:45:38 +0200 Subject: [PATCH 12/12] style: move extension.md TOC further --- core/extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/extensions.md b/core/extensions.md index c7b883c652b..a3c33672756 100644 --- a/core/extensions.md +++ b/core/extensions.md @@ -166,4 +166,4 @@ security: Previous chapter: [Data Providers](data-providers.md) -Next chapter: [Security](core/security.md) \ No newline at end of file +Next chapter: [Security](security.md) \ No newline at end of file