From 822152799debdd309807e19a7b71b44cd04895d5 Mon Sep 17 00:00:00 2001 From: David Gebler Date: Mon, 16 Jun 2025 14:41:07 +0100 Subject: [PATCH 1/3] update docs to add throw_on_access_denied details to security pages --- symfony/security.md | 48 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/symfony/security.md b/symfony/security.md index e2e97988025..d3f693ff3d1 100644 --- a/symfony/security.md +++ b/symfony/security.md @@ -158,7 +158,53 @@ Additionally, in some cases you need to perform security checks on the original The value in the `previous_object` variable is cloned from the original object. Note that, by default, this clone is not a deep one (it doesn't clone relationships, relationships are references). -To make a deep clone, [implement `__clone` method](https://www.php.net/manual/en/language.oop5.cloning.php) in the concerned resource class. +To make a deep clone, [implement `__clone` method](https://www.php.net/manual/en/language.oop5.cloning.php) in the concerned resource class.i + +## Controlling the response on `securityPostDenormalize` + +By default, when a request for a write operation is made that doesn't meet the `securityPostDenormalize` requirements (i.e. the expression returns `false`), the values of those protected properties in the +request data are silently discarded and not set on the object. Any properties the user does have permission to update will be updated and the request succeeds. + +You can optionally instruct API Platform to instead return a 403 Access Denied response in such cases, by adding `throw_on_access_denied` as an extra property with a value of `true`: + + + +```php + true] +)] +class Book +{ + // ... +} +``` + +```yaml +# api/config/api_platform/resources.yaml +resources: + App\Entity\Book: + operations: + ApiPlatform\Metadata\Get: ~ + ApiPlatform\Metadata\GetCollectionPut: + securityPostDenormalize: "is_granted('ROLE_ADMIN') or (object.owner == user and previous_object.owner == user)" + extraProperties: + throw_on_access_denied: true + # ... +``` + + + ## Hooking Custom Permission Checks Using Voters From fbc29cb4dd8d39fbf6b74c9a79334233e5c8c88d Mon Sep 17 00:00:00 2001 From: David Gebler Date: Thu, 26 Jun 2025 11:30:01 +0100 Subject: [PATCH 2/3] remove trailing space (lint) --- symfony/security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony/security.md b/symfony/security.md index d3f693ff3d1..5f8c4e5abff 100644 --- a/symfony/security.md +++ b/symfony/security.md @@ -162,7 +162,7 @@ To make a deep clone, [implement `__clone` method](https://www.php.net/manual/en ## Controlling the response on `securityPostDenormalize` -By default, when a request for a write operation is made that doesn't meet the `securityPostDenormalize` requirements (i.e. the expression returns `false`), the values of those protected properties in the +By default, when a request for a write operation is made that doesn't meet the `securityPostDenormalize` requirements (i.e. the expression returns `false`), the values of those protected properties in the request data are silently discarded and not set on the object. Any properties the user does have permission to update will be updated and the request succeeds. You can optionally instruct API Platform to instead return a 403 Access Denied response in such cases, by adding `throw_on_access_denied` as an extra property with a value of `true`: From a4ad3f869c76f4a3485a89bf9dc0187c80236503 Mon Sep 17 00:00:00 2001 From: David Gebler Date: Thu, 26 Jun 2025 16:16:03 +0100 Subject: [PATCH 3/3] add XML example --- symfony/security.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/symfony/security.md b/symfony/security.md index 5f8c4e5abff..1f7c61b3b35 100644 --- a/symfony/security.md +++ b/symfony/security.md @@ -174,11 +174,9 @@ You can optionally instruct API Platform to instead return a 403 Access Denied r // api/src/Entity/Book.php namespace App\Entity; -use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\Put; -#[ApiResource] #[Get] #[Put( securityPostDenormalize: "is_granted('ROLE_ADMIN') or (object.owner == user and previous_object.owner == user)", @@ -203,6 +201,28 @@ resources: # ... ``` +```xml + + + + + + + + + is_granted('ROLE_ADMIN') or (object.owner == user and previous_object.owner == user) + + + + + + + +``` +