api-platform
api-platform copied to clipboard
Graphql Input DTO does not respect serialization groups
API Platform version(s) affected: 2.6.8
Description
Converting an User entity from graphql only to both REST/graphql.
Created an input DTO to replace a WriteStage code that hashed the password and created email confirmation token.
All properties that are set to public on the input DTO will show on the createUserInput,
regardless of the serialization group.
It seems to respect the serialization groups for REST ( see bottom).
How to reproduce
App\Entity\User
.....
graphql:[
'item_query' => ['normalization_context' => ['groups' => ['get-admin']]],
'collection_query' => [
'security' => "is_granted('ROLE_ADMIN')",
'normalization_context' => ['groups' => ['get-admin']]
],
'update' => [
'security' => "is_granted('ROLE_USER') and object.owner == user is_granted('ROLE_ADMIN')",
'denormalization_context' => ['groups' => ['put-profile-change', 'put']],
'validation_groups' => ['put-profile-change', 'put']
],
'create' => [
'denormalization_context' => ['groups' => ['post']],
'validation_groups' => ['post']
]
],
.....
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(["get", "get-admin", "get-owner"])]
public int $id;
#[ORM\Column(type: 'string', length:180)]
#[Groups(["post", "post-social-register-google", "put", "put-profile-change", "get-owner", "get-admin"])]
private string $email;
#[ORM\Column(type: 'string', length:180, unique:true)]
#[Groups(["post", "post-social-register-google", "get", "get-admin", "get-owner", "put-register-social"])]
private string $username;
#[ORM\Column(type:'string', length:180)]
#[Groups(["post"])]
private string $password;
#[Groups(["post"])]
private string $passwordConfirmation;
#[ORM\Column(type:'json')]
#[Groups(["get-admin", "get-owner"])]
private array $roles = [];
#[ORM\Column(type: 'datetime_immutable')]
#[Groups(["get-admin", "get-owner"])]
private \DateTimeImmutable $createdAt;
#[ORM\Column(type: 'datetime_immutable', nullable:true)]
#[Groups(["get-admin"])]
private \DateTimeImmutable $passwordChangedAt;
#[ORM\Column(type: 'boolean')]
#[Groups(["get-admin"])]
private bool $isEnabled;
#[ORM\Column(type:'string', length:40, nullable:true)]
private string|null $confirmationToken;
........
On App\Dto\UserInput
class UserInput
{
/**
* @var string
*/
#[Groups(["post", "post-social-register-google", "put", "put-profile-change", "get-owner", "get-admin"])]
#[Assert\NotBlank(groups:["post", "post-social-register-google"])]
#[Assert\Email(groups:["post", "post-social-register-google"])]
public string $email;
/**
* @var string
*/
#[Groups(["post", "post-social-register-google", "get", "get-admin", "get-owner", "put-register-social"])]
#[Assert\NotBlank(groups:["post"])]
#[Assert\Length(min:10, max:50, groups:["post", "post-social-register-google", "put-register-social"])]
public string $username;
/**
* @var string $password
* The hashed password
*/
#[Groups(["post"])]
#[Assert\NotBlank(groups:["post"])]
#[Assert\Regex(
pattern:"/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{10,50}$)/",
groups:["post"]
)]
public string $password;
/**
* @var string
*
*/
#[Groups(["post"])]
public string $passwordConfirmation;
#[Groups(["get-admin", "get-owner"])]
public array $roles = [];
/**
* @var \DateTimeImmutable $createdAt
*
*/
#[Groups(["get-admin", "get-owner"])]
public \DateTimeImmutable $createdAt;
/**
* @var \DateTimeImmutable $passwordChangedAt
*
*/
#[Groups(["get-admin"])]
private \DateTimeImmutable $passwordChangedAt;
/**
* @var bool $isEnabled
*
*/
#[Groups(["get-admin"])]
public bool $isEnabled;
So, the intended input to create user is:
email
username
password
paswordConfirmation
The createUserInput will look like this for above:
While for REST:
#[ApiResource(
collectionOperations: [
'post' => [
'denormalization_context' => [
'groups' => ["post"],
'validation_groups' => ["post"]
]
]
],
Input will be as intended:

Possible Solution
Additional Context