forked from api-platform/core
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
550 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
// --- | ||
// slug: secure-a-resource-access | ||
// name: Secure a Resource Access | ||
// position: 4 | ||
// executable: true | ||
// --- | ||
|
||
namespace App\ApiResource; | ||
|
||
use ApiPlatform\Metadata\ApiResource; | ||
use ApiPlatform\Metadata\ApiProperty; | ||
use ApiPlatform\Metadata\Get; | ||
use ApiPlatform\Metadata\GetCollection; | ||
use ApiPlatform\Metadata\Post; | ||
use ApiPlatform\Metadata\Put; | ||
use Doctrine\ORM\Mapping as ORM; | ||
use Symfony\Component\Validator\Constraints as Assert; | ||
use App\Security\User; | ||
|
||
// We start by securing access to this resource to logged in users. | ||
#[ApiResource(security: "is_granted('ROLE_USER')")] | ||
#[Get] | ||
// To create a new resource using the Post operation, a user has to belong to the `ROLE_ADMIN` role. | ||
// We also customize the "Access Denied." message with the `securityMessage` property. | ||
#[Post(security: "is_granted('ROLE_ADMIN')", securityMessage: "Only an admin has access to that operation.")] | ||
// If a user **owns** the Book or has the `ROLE_ADMIN` role, he can update the object using the Put operation. Here we're | ||
// using the `object`'s owner. The supported variables within the access control expression are: | ||
// - user: the current logged in object, if any | ||
// - object: contains the value submitted by the user | ||
// - request: the current Request object | ||
#[Put(security: "is_granted('ROLE_ADMIN') or object.owner == user")] | ||
#[GetCollection] | ||
#[ORM\Entity] | ||
class Book | ||
{ | ||
#[ORM\Id, ORM\Column, ORM\GeneratedValue] | ||
public ?int $id = null; | ||
|
||
#[ORM\Column] | ||
#[Assert\NotBlank] | ||
public string $title; | ||
|
||
#[ORM\ManyToOne] | ||
public User $owner; | ||
|
||
// The security attribute is also available on [ApiProperty::security](/reference/Metadata/ApiProperty#security). | ||
// Access control checks in the security attribute are always executed before the denormalization step. | ||
// If you want the object after denormalization, use `securityPostDenormalize`. Using this access control variables have: | ||
// - object: the object after denormalization | ||
// - previous_object: a clone of the object before modifications were made | ||
/** | ||
* @var string Property viewable and writable only by users with ROLE_ADMIN | ||
*/ | ||
#[ApiProperty(security: "is_granted('ROLE_ADMIN')", securityPostDenormalize: "is_granted('UPDATE', object)")] | ||
public string $adminOnlyProperty; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<?php | ||
// --- | ||
// slug: secure-a-resource-with-custom-voters | ||
// name: Secure a Resource with Custom Voters | ||
// position: 10 | ||
// executable: true | ||
// --- | ||
|
||
namespace App\Security\Voter { | ||
use App\Entity\Book; | ||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; | ||
use Symfony\Component\Security\Core\Authorization\Voter\Voter; | ||
use Symfony\Component\Security\Core\Security; | ||
|
||
// First let's create a Voter, for example using the `bin/console make:voter` command: | ||
class BookVoter extends Voter | ||
{ | ||
private $security = null; | ||
|
||
public function __construct(Security $security) | ||
{ | ||
$this->security = $security; | ||
} | ||
|
||
protected function supports($attribute, $subject): bool | ||
{ | ||
// It supports several attributes related to our Resource access control. | ||
$supportsAttribute = in_array($attribute, ['BOOK_CREATE', 'BOOK_READ', 'BOOK_EDIT', 'BOOK_DELETE']); | ||
$supportsSubject = $subject instanceof Book; | ||
|
||
return $supportsAttribute && $supportsSubject; | ||
} | ||
|
||
/** | ||
* @param string $attribute | ||
* @param Book $subject | ||
* @param TokenInterface $token | ||
* @return bool | ||
*/ | ||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool | ||
{ | ||
/** ... check if the user is anonymous ... **/ | ||
|
||
switch ($attribute) { | ||
case 'BOOK_CREATE': | ||
if ( $this->security->isGranted(Role::ADMIN) ) { return true; } // only admins can create books | ||
break; | ||
case 'BOOK_READ': | ||
/** ... other autorization rules ... **/ | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} | ||
|
||
namespace App\ApiResource { | ||
use ApiPlatform\Metadata\ApiResource; | ||
use ApiPlatform\Metadata\Delete; | ||
use ApiPlatform\Metadata\Get; | ||
use ApiPlatform\Metadata\GetCollection; | ||
use ApiPlatform\Metadata\Post; | ||
use ApiPlatform\Metadata\Put; | ||
|
||
#[ApiResource(security: "is_granted('ROLE_USER')")] | ||
// We can then use the `is_granted` expression with our access control attributes: | ||
#[Get(security: "is_granted('BOOK_READ', object)")] | ||
#[Put(security: "is_granted('BOOK_EDIT', object)")] | ||
#[Delete(security: "is_granted('BOOK_DELETE', object)")] | ||
// On a collection, you need to [implement a Provider](provide-the-resource-state) to filter the collection manually. | ||
#[GetCollection] | ||
// `object` is empty uppon creation, we use `securityPostDenormalize` to get the denormalized object. | ||
#[Post(securityPostDenormalize: "is_granted('BOOK_CREATE', object)")] | ||
class Book | ||
{ | ||
// ... | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<?php | ||
// --- | ||
// slug: secure-a-resource-with-custom-voters | ||
// name: Secure a Resource with Custom Voters | ||
// position: 10 | ||
// executable: true | ||
// --- | ||
|
||
namespace App\OpenApi { | ||
use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface; | ||
use ApiPlatform\OpenApi\OpenApi; | ||
use ApiPlatform\OpenApi\Model; | ||
|
||
final class OpenApiFactory implements OpenApiFactoryInterface | ||
{ | ||
private $decorated; | ||
|
||
public function __construct(OpenApiFactoryInterface $decorated) | ||
{ | ||
$this->decorated = $decorated; | ||
} | ||
|
||
public function __invoke(array $context = []): OpenApi | ||
{ | ||
$openApi = $this->decorated->__invoke($context); | ||
$pathItem = $openApi->getPaths()->getPath('/api/grumpy_pizzas/{id}'); | ||
$operation = $pathItem->getGet(); | ||
|
||
$openApi->getPaths()->addPath('/api/grumpy_pizzas/{id}', $pathItem->withGet( | ||
$operation->withParameters(array_merge( | ||
$operation->getParameters(), | ||
[new Model\Parameter('fields', 'query', 'Fields to remove of the output')] | ||
)) | ||
)); | ||
|
||
$openApi = $openApi->withInfo((new Model\Info('New Title', 'v2', 'Description of my custom API'))->withExtensionProperty('info-key', 'Info value')); | ||
$openApi = $openApi->withExtensionProperty('key', 'Custom x-key value'); | ||
$openApi = $openApi->withExtensionProperty('x-value', 'Custom x-value value'); | ||
|
||
return $openApi; | ||
} | ||
} | ||
} | ||
|
||
namespace App\Configurator { | ||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; | ||
|
||
function configure(ContainerConfigurator $configurator) { | ||
$services = $configurator->services(); | ||
$services->set(App\OpenApi\OpenApiFactory::class)->decorate('api_platform.openapi.factory'); | ||
}; | ||
} | ||
|
||
// namespace App\Tests { | ||
// class ApiTestCase extends ApiTestCase { | ||
// | ||
// } | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Metadata | ||
|
||
explain metadata system, metadata factories |
Oops, something went wrong.