Api-platform : filtrer les résultats uniquement sur l’utilisateur connecté

api-platform-:-filtrer-les-resultats-uniquement-sur-l’utilisateur-connecte

Imaginez avoir dans votre projet plusieurs entités avec la relation author comme par exemple ces deux entités suivantes :



namespace AppEntity;

use ApiPlatformMetadataApiResource;
use AppRepositoryCourierFavoriteRepository;
use DoctrineORMMapping as ORM; 

#[ORMEntity(repositoryClass: CourierFavoriteRepository::class)]
#[ApiResource()]
class Book
{ 
    #[ORMId]
    #[ORMGeneratedValue]
    #[ORMColumn]
    private ?int $id = null;

    #[ORMManyToOne]
    #[ORMJoinColumn(nullable: false)] 
    private ?User $author = null; 

    #[ORMColumn(length: 255)] 
    private ?string $title = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getAuthor(): ?User
    {
        return $this->author;
    }

    public function setAuthor(?User $author): static
    {
        $this->author = $author;

        return $this;
    } 

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): self
    {
        $this->title = $title;

        return $this;
    }
}


namespace AppEntity;

use ApiPlatformMetadataApiResource;
use AppRepositoryTodoRepository; 
use DoctrineDBALTypesTypes;
use DoctrineORMMapping as ORM;

#[ORMEntity(repositoryClass: TodoRepository::class)]
#[ApiResource()]
class Todo
{
    #[ORMId]
    #[ORMGeneratedValue]
    #[ORMColumn]
    private ?int $id = null;

    #[ORMManyToOne]
    #[ORMJoinColumn(nullable: false)]
    private ?User $author = null;

    #[ORMColumn(type: Types::TEXT)]
    private ?string $content = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getAuthor(): ?User
    {
        return $this->author;
    }

    public function setAuthor(?User $author): static
    {
        $this->author = $author;

        return $this;
    }

    public function getContent(): ?string
    {
        return $this->content;
    }

    public function setContent(string $content): static
    {
        $this->content = $content;

        return $this;
    }
}

Nous voulons verrouiller les résultats des GET item et collection uniquement sur l’user connecté.

Nous allons créer une interface que nous implémenterons sur nos entités



namespace AppEntity;

interface CurrentUserIsAuthorInterface
{
    public function setAuthor(?User $author): static;
}

Maitenant nous allons faire une DoctrineExtension qui va ajouter la contrainte where dans le QueryBuilder sur l’utilisateur connecté.



namespace AppDoctrineExtension;

use ApiPlatformDoctrineOrmExtensionQueryCollectionExtensionInterface;
use ApiPlatformDoctrineOrmExtensionQueryItemExtensionInterface;
use ApiPlatformDoctrineOrmUtilQueryNameGeneratorInterface;
use ApiPlatformMetadataOperation;
use AppEntityCurrentUserIsAuthorInterface;
use DoctrineORMQueryBuilder;
use SymfonyBundleSecurityBundleSecurity;

class CurrentUserIsAuthorExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
{
    public function __construct(
        private Security $security,
    ) {
    }

    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
    {
        $this->currentUserIsAuthor($resourceClass, $queryBuilder);
    }

    public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, ?Operation $operation = null, array $context = []): void
    {
        $this->currentUserIsAuthor($resourceClass, $queryBuilder);
    }

    /**
     * @param string $resourceClass
     * @param QueryBuilder $queryBuilder
     * @return void
     * @throws ReflectionException
     */
    public function currentUserIsAuthor(string $resourceClass, QueryBuilder $queryBuilder): void
    {
        $reflectionClass = new ReflectionClass($resourceClass);
        if ($reflectionClass->implementsInterface(CurrentUserIsAuthorInterface::class)) {
            $alias = $queryBuilder->getRootAliases()[0];
            $queryBuilder->andWhere("$alias.author = :current_author")
                ->setParameter('current_author', $this->security->getUser()->getId());
        }
    }
}

Maintenant il nous reste à implémenter notre interface sur nos entités :



namespace AppEntity;

use ApiPlatformMetadataApiResource;
use AppRepositoryCourierFavoriteRepository;
use DoctrineORMMapping as ORM; 

#[ORMEntity(repositoryClass: CourierFavoriteRepository::class)]
#[ApiResource()]
class Book implements CurrentUserIsAuthorInterface
{ 
    // ...


namespace AppEntity;

use ApiPlatformMetadataApiResource;
use AppRepositoryTodoRepository; 
use DoctrineDBALTypesTypes;
use DoctrineORMMapping as ORM;

#[ORMEntity(repositoryClass: TodoRepository::class)]
#[ApiResource()]
class Todo implements CurrentUserIsAuthorInterface
{
    // ...

Et c’est tout. Pour chaque GET item ou collection vous aurez uniquement les entrées avec l’utilisateurs qui est connecté 🚀

Lisez aussi “comment enregistrer automatiquement l’utilisateur connecté” : https://dev.to/aratinau/automatisons-lenregistrement-du-user-sur-nimporte-quelle-entite-4f68

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
sunday-rewind:-how-accurate-is-your-ux-research-data?-by-martina-kuvalja

Sunday Rewind: How accurate is your UX research data? By Martina Kuvalja

Next Post
o-basico-de-mirror-do istio

O básico de mirror do Istio

Related Posts