Encode password easyadmin v3 - passwords

I have my user that I can manage from my administration panel, I can change the password, but the problem is that in the database it is not encrypted. It is in clear in the database, Save you how I could do it so that it is not anymore? I give you my user entity as well as the crud user And I use the easyadmin v3 and symfony 5 bundle.
My entity User
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\Entity(repositoryClass=UserRepository::class)
*/
class User implements UserInterface
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=180, unique=true)
*/
private $email;
/**
* #ORM\Column(type="json")
*/
private $roles = [];
/**
* #var string The hashed password
* #ORM\Column(type="string")
*/
private $password;
/**
* #ORM\Column(type="string", length=255)
*/
private $prenom;
/**
* #ORM\Column(type="string", length=255)
*/
private $nom;
/**
* #ORM\Column(type="string", length=255)
*/
private $telephone;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $aPropos;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $facebook;
/**
* #ORM\OneToMany(targetEntity=Realisation::class, mappedBy="user", orphanRemoval=true)
*/
private $realisations;
public function __construct()
{
$this->realisations = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* #see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* #see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returning a salt is only needed, if you are not using a modern
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
*
* #see UserInterface
*/
public function getSalt(): ?string
{
return null;
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getPrenom(): ?string
{
return $this->prenom;
}
public function setPrenom(string $prenom): self
{
$this->prenom = $prenom;
return $this;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(string $nom): self
{
$this->nom = $nom;
return $this;
}
public function getTelephone(): ?string
{
return $this->telephone;
}
public function setTelephone(string $telephone): self
{
$this->telephone = $telephone;
return $this;
}
public function getAPropos(): ?string
{
return $this->aPropos;
}
public function setAPropos(?string $aPropos): self
{
$this->aPropos = $aPropos;
return $this;
}
public function getFacebook(): ?string
{
return $this->facebook;
}
public function setFacebook(?string $facebook): self
{
$this->facebook = $facebook;
return $this;
}
/**
* #return Collection|Realisation[]
*/
public function getRealisations(): Collection
{
return $this->realisations;
}
public function addRealisation(Realisation $realisation): self
{
if (!$this->realisations->contains($realisation)) {
$this->realisations[] = $realisation;
$realisation->setUser($this);
}
return $this;
}
public function removeRealisation(Realisation $realisation): self
{
if ($this->realisations->removeElement($realisation)) {
// set the owning side to null (unless already changed)
if ($realisation->getUser() === $this) {
$realisation->setUser(null);
}
}
return $this;
}
public function __toString()
{
return $this->nom;
}
/* public function __toString(){
return $this->nom;
}*/
}
<?php
namespace App\Controller\Admin;
use App\Entity\User;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class UserCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return User::class;
}
public function configureFields(string $pageName): iterable
{
return [
IntegerField::new('id','ID')->onlyOnIndex(),
TextField::new('email'),
TextField::new('password'),
TextField::new('nom'),
TextField::new('telephone'),
TextField::new('aPropos'),
TextField::new('facebook'),
];
}
}

This could be helpful ...
<?php
namespace App\Event\Subscriber;
use App\Entity\BackendUser;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
class EasyAdminHooksSubscriber implements EventSubscriberInterface {
/**
* #var UserPasswordEncoderInterface
*/
private $passwordEncoder;
/**
* #var ContainerInterface
*/
private $container;
/**
* EasyAdminSubscriber constructor.
*
* #param UserPasswordEncoderInterface $passwordEncoder
* #param ContainerInterface $container
*/
public function __construct(UserPasswordEncoderInterface $passwordEncoder, ContainerInterface $container) {
$this->passwordEncoder = $passwordEncoder;
$this->container = $container;
}
public static function getSubscribedEvents(): array {
return array(
BeforeEntityUpdatedEvent::class => array('preUpdateEntity')
);
}
/**
* #param BeforeEntityUpdatedEvent $event
*
* #noinspection PhpUnused
*/
public function preUpdateEntity(BeforeEntityUpdatedEvent $event) {
$entity = $event->getEntityInstance();
if($entity instanceof BackendUser) {
$this->preUpdateBackendUser($entity);
}
}
/**
* #param BackendUser $be_user
*/
private function preUpdateBackendUser(BackendUser &$be_user) {
$plain_password = $be_user->getPlainPassword();
if(!empty($plain_password)) {
$new_password = $this->passwordEncoder->encodePassword($be_user, $plain_password);
$be_user->setPassword($new_password);
$be_user->setPlainPassword();
}
}
}

Here's a solution I found while trying to create/edit users from my web app's admin dashboard (Symfony 5.3 and EasyAdmin v3). I found it in the EasyAdmin issue tracker over on Github.
You will need to add a plain password field to you User class and set the appropriate getter & setter methods.
/**
* #var string
*/
private $plainPassword;
/**
* #return string
*/
public function getPlainPassword(): string
{
return $this->plainPassword;
}
Add event listeners to listen to create/edit form submission events, extract the plain password from the submitted form data and then hash it.
/** #var UserPasswordHasherInterface */
private $hasher;
public function createEditFormBuilder(EntityDto $entityDto, KeyValueStore $keyValueStore, AdminContext $context): FormBuilderInterface
{
$formBuilder = parent::createEditFormBuilder($entityDto, $keyValueStore, $context);
$this->addEncodePasswordEventListener($formBuilder);
return $formBuilder;
}
public function createNewFormBuilder(EntityDto $entityDto, KeyValueStore $formOptions, AdminContext $context): FormBuilderInterface
{
$formBuilder = parent::createNewFormBuilder($entityDto, $formOptions, $context);
$this->addEncodePasswordEventListener($formBuilder);
return $formBuilder;
}
/**
* #param FormBuilderInterface $formBuilder
*/
public function addEncodePasswordEventListener(FormBuilderInterface $formBuilder)
{
$formBuilder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event){
/** #var User $user */
$user = $event->getData();
if ($user->getPlainPassword()) {
$user->setPassword($this->hasher->hashPassword($user, $user->getPlainPassword()));
}
});
}
Then finally you need to render the appropriate form fields.
public function configureFields(string $pageName): iterable
{
return [
# other fields
Field::new('plainPassword', 'New Password')->onlyOnForms()
->setFormType(RepeatedType::class)
->setFormTypeOptions([
'type' => PasswordType::class,
'first_options' => ['label' => 'New password'],
'second_options' => ['label' => 'Repeat Password']
])->setRequired(true)
];
}
Hope someone finds this useful.

You can add plain password field in User entity:
private ?string $plainPassword= '';
public function getPlainPassword(): ?string
{
return $this->plainPassword;
}
public function setPlainPassword(?string $plainPassword): void
{
$this->plainPassword = $plainPassword;
}
Add password updater in User repo:
public function setNewPassword(PasswordAuthenticatedUserInterface $user, string $plainPassword): void
{
$hashedPassword = $this->hasher->hashPassword($user, $plainPassword);
$user->setPassword($hashedPassword);
$this->_em->persist($user);
$this->_em->flush();
}
And override update/persist methods In UserCrudController:
public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$this->updatePassword($entityInstance);
parent::updateEntity($entityManager, $entityInstance);
}
public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
{
$this->updatePassword($entityInstance);
parent::persistEntity($entityManager, $entityInstance);
}
private function updatePassword(User $user): void
{
if ($user->getPlainPassword() == '') return;
$this->userRepository->setNewPassword($user, $user->getPlainPassword());
}
It's work in Symfony 5.4.2 / EasyAdmin 3.5.19

Related

Stuck with SQL query in Symfony 4

I try to list the 3 most liked user in a table.
Here is the entitys that i have :
$User, $Post, $PostLike.
The user can aswer to a question by posting a $Post, each post can be like or dislike by users.
In $Post i have : the User can posted, the question the post is answering.
In $PostLike i have : The User that liked or disliked, the Post, and a bolean (1 if like,0 for dislike)
So i think i can get all the PostLike where the bolean == 1 then group them by $Post then Groupe the result by User and get the length of all Like or Dislike an user get.
I'm stuck with the sql query.
Anyone can help me please?
Here's the entity code :
class StackUser
{
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $username;
public function getId(): ?int
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
}
.
class Post
{
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="posts")
* #ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* #ORM\Column(type="text")
*/
private $ThePostHimself;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\PostLike", mappedBy="Post")
*/
private $postLikes;
public function __construct()
{
$this->postLikes = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getThePostHimself(): ?string
{
return $this->ThePostHimself;
}
public function setThePostHimself(string $ThePostHimself): self
{
$this->ThePostHimself = $ThePostHimself;
return $this;
}
/**
* #return Collection|PostLike[]
*/
public function getPostLikes(): Collection
{
return $this->postLikes;
}
public function addPostLike(PostLike $postLike): self
{
if (!$this->postLikes->contains($postLike)) {
$this->postLikes[] = $postLike;
$postLike->addPost($this);
}
return $this;
}
public function removePostLike(PostLike $postLike): self
{
if ($this->postLikes->contains($postLike)) {
$this->postLikes->removeElement($postLike);
$postLike->removePost($this);
}
return $this;
}
}
.
class PostLike
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="boolean")
*/
private $LikeDislike;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Post", inversedBy="postLikes")
*/
private $Post;
public function __construct()
{
$this->Post = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getLikeDislike(): ?bool
{
return $this->LikeDislike;
}
public function setLikeDislike(bool $LikeDislike): self
{
$this->LikeDislike = $LikeDislike;
return $this;
}
/**
* #return Collection|Post[]
*/
public function getPost(): Collection
{
return $this->Post;
}
public function addPost(Post $post): self
{
if (!$this->Post->contains($post)) {
$this->Post[] = $post;
}
return $this;
}
public function removePost(Post $post): self
{
if ($this->Post->contains($post)) {
$this->Post->removeElement($post);
}
return $this;
}
}

Serialize data from database

I have problem with my Symfony rest API. I have this controller:
<?php
namespace App\Controller;
use App\Entity\Post;
use App\Service\ErrorDecoratorService;
use App\Service\PostService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Serializer\SerializerInterface;
class PostController extends AbstractController
{
private $postService;
private $errorDecoratorService;
public function __construct(PostService $postService, ErrorDecoratorService $errorDecoratorService)
{
$this->postService = $postService;
$this->errorDecoratorService = $errorDecoratorService;
}
/**
* #Route("/post/{postId}", methods={"GET"})
* #param $postId
* #param SerializerInterface $serializer
* #return JsonResponse
*/
public function getPost($postId, SerializerInterface $serializer)
{
$result = $this->postService->getPost($postId);
if ($result instanceof Post) {
$data = $serializer->serialize($result,'json');
$status = JsonResponse::HTTP_OK;
} else {
$status = JsonResponse::HTTP_NOT_FOUND;
$data = $this->errorDecoratorService->decorateError($status, $result);
}
return new JsonResponse($data, $status);
}
}
When I have from database serialize to JSON format, then I receive this error:
Could not normalize object of type App\Entity\Post, no supporting
normalizer found. (500 Internal Server Error)
It's my entity
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\PostRepository")
*/
class Post
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank()
*/
private $title;
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank()
*/
private $content;
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank()
*/
private $author;
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getAuthor(): ?string
{
return $this->author;
}
public function setAuthor(string $author): self
{
$this->author = $author;
return $this;
}
}
Where is my mistake? I have tried Symfony Serializer, JMS Serializer but I still get the same error.
Once you enable the Normalizer the Serializer will produce a json encoded string with this line:
$data = $serializer->serialize($result,'json');
// "{\"id\":1,\"title\":\"qwerty\",\"content\":\"Lorem ipsum sit dolor amet\",\"author\":\"Pawel\"}"
The JsonResponse construct json encodes the first parameter, usually an array or object, but in your case just a string. You need to either decode the string when you pass it to the constructor, or preferably use the JsonResponse::fromJsonString() method.
Should work:
return new JsonResponse(json_decode($data), $status);
Preferred method:
return new JsonResponse::fromJsonString($data, $status);
https://symfony.com/doc/current/components/http_foundation.html#creating-a-json-response

Symfony 4 JWT : I can't get response from controller when accessing api

I'm working on this tutorial : Implementing JWT Authentication to your API Platform application
and I'm trying to get a protected access to the api action controller :
public function api()
{
return new Response(sprintf('Logged in as %s', $this->getUser()->getUsername()));
}
For reminder here is the security.yaml :
security:
encoders:
App\Entity\User:
algorithm: bcrypt
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
entity_provider:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
# main:
# anonymous: true
login:
pattern: ^/login
stateless: true
anonymous: true
json_login:
check_path: /login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
register:
pattern: ^/register
stateless: true
anonymous: true
api:
pattern: ^/api
stateless: true
anonymous: false
provider: entity_provider
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
# activate different ways to authenticate
# http_basic: true
# https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
# form_login: true
# https://symfony.com/doc/current/security/form_login_setup.html
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
And the routes.yaml :
register:
path: /register
controller: App\Controller\AuthController::register
methods: POST
api:
path: /api
controller: App\Controller\AuthController::api
login_check:
path: /login_check
methods: [POST]
I have the same code excepted the User entity :
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiSubresource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
/**
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* #ApiResource(normalizationContext={"groups"={"user"}})
* #ApiFilter(SearchFilter::class, properties={"centres.id": "exact"})
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups({"user"})
*/
private $id;
/**
* #ORM\Column(type="string", length=50, unique=true)
* #Groups({"user"})
*/
private $username;
/**
* #ORM\Column(type="string", length=64)
* #Groups({"user"})
*/
private $password;
/**
* #ORM\Column(type="string", length=50, nullable=true)
* #Groups({"user"})
*/
private $prenom;
/**
* #ORM\Column(type="string", length=50, nullable=true)
* #Groups({"user"})
*/
private $nom;
/**
* #ORM\Column(type="string", length=80, unique=true)
* #Groups({"user"})
*/
private $email;
/**
* #ORM\Column(type="array")
* #Groups({"user"})
*/
private $roles = [];
/**
* #ORM\Column(type="datetime", nullable=true)
* #Groups({"user"})
*/
private $dateNaissance;
/**
* #ORM\Column(type="datetime")
* #Groups({"user"})
*/
private $dateEnregistrement;
/**
* #ORM\Column(type="datetime", nullable=true)
* #Groups({"user"})
*/
private $dateDernierePartie;
/**
* #ORM\Column(type="boolean")
* #Groups({"user"})
*/
private $actif;
/**
* #ORM\Column(type="integer")
* #Groups({"user"})
*/
private $niveau;
/**
* #ORM\Column(type="integer")
* #Groups({"user"})
*/
private $experience;
/**
* #ORM\Column(type="integer")
* #Groups({"user"})
*/
private $nbVictimes;
/**
* #ORM\Column(type="integer")
* #Groups({"user"})
*/
private $nbMorts;
/**
* #ORM\Column(type="integer", nullable=true)
* #Groups({"user"})
*/
private $justesse;
/**
* #ORM\Column(type="integer", nullable=true)
* #Groups({"user"})
*/
private $nbParties;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Carte", mappedBy="client")
* #Groups({"user"})
* #var Collection
*/
private $cartes;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Equipe", inversedBy="joueurs")
* #ORM\JoinColumn(nullable=true)
* #Groups({"user"})
*/
private $equipe;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Centre", inversedBy="clients")
* #ORM\JoinTable(name="users_centres")
* #var Collection
* #Groups({"user"})
*/
private $centres;
public function __construct()
{
$this->cartes = new ArrayCollection();
$this->centres = new ArrayCollection();
$this->actif = true;
$this->niveau = 1;
$this->experience = 0;
$this->nbVictimes = 0;
$this->nbMorts = 0;
$this->justesse = 0;
$this->nbParties = 0;
$this->dateEnregistrement = new \DateTime();
}
/**
* #param int|null $id
* #param string $username
* #param string $email
* #param string $password
* #param array $roles
* #param \DateTime|null $dateEnregistrement
* #return User
*/
static public function creer(
?int $id = null,
string $username,
string $email,
string $password,
array $roles,
?\DateTime $dateEnregistrement = null
)
{
$user = new self();
$user->id = $id;
$user->username = $username;
$user->email = $email;
$user->password = $password;
$user->roles = $roles;
$user->dateEnregistrement = $dateEnregistrement;
return $user;
}
public function addCarte(Carte $carte)
{
if ($this->cartes->contains($carte)) {
return;
}
$this->cartes->add($carte);
$carte->setClient($this);
}
public function addCentre(Centre $centre)
{
if ($this->centres->contains($centre)) {
return;
}
$this->centres->add($centre);
//$centre->inscrireJoueur($this);
}
public function ajouterNbVictimes(int $nbVictimes)
{
$this->nbVictimes += $nbVictimes;
}
public function ajouterJustesse(int $justesse)
{
$this->justesse += $justesse;
}
public function diminuerJustesse(int $justesse)
{
$this->justesse -= $justesse;
}
public function ajouterNbMorts(int $nbMorts)
{
$this->nbMorts += $nbMorts;
}
public function getId(): ?int
{
return $this->id;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getPrenom(): ?string
{
return $this->prenom;
}
public function setPrenom(string $prenom): self
{
$this->prenom = $prenom;
return $this;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(string $nom): self
{
$this->nom = $nom;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getRoles(): ?array
{
return $this->roles;
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
public function getDateNaissance(): ?\DateTimeInterface
{
return $this->dateNaissance;
}
public function setDateNaissance(\DateTimeInterface $dateNaissance): self
{
$this->dateNaissance = $dateNaissance;
return $this;
}
public function getDateEnregistrement(): ?\DateTimeInterface
{
return $this->dateEnregistrement;
}
public function setDateEnregistrement(\DateTimeInterface $dateEnregistrement): self
{
$this->dateEnregistrement = $dateEnregistrement;
return $this;
}
public function getDateDernierePartie(): ?\DateTimeInterface
{
return $this->dateDernierePartie;
}
public function setDateDernierePartie(?\DateTimeInterface $dateDernierePartie): self
{
$this->dateDernierePartie = $dateDernierePartie;
return $this;
}
public function getActif(): ?bool
{
return $this->actif;
}
public function setActif(bool $actif): self
{
$this->actif = $actif;
return $this;
}
public function getNiveau(): ?int
{
return $this->niveau;
}
public function setNiveau(int $niveau): self
{
$this->niveau = $niveau;
return $this;
}
public function getExperience(): ?int
{
return $this->experience;
}
public function setExperience(int $experience): self
{
$this->experience = $experience;
return $this;
}
public function getNbVictimes(): ?int
{
return $this->nbVictimes;
}
public function setNbVictimes(int $nbVictimes): self
{
$this->nbVictimes = $nbVictimes;
return $this;
}
public function getNbMorts(): ?int
{
return $this->nbMorts;
}
public function setNbMorts(int $nbMorts): self
{
$this->nbMorts = $nbMorts;
return $this;
}
public function getJustesse(): ?int
{
return $this->justesse;
}
public function setJustesse(int $justesse): self
{
$this->justesse = $justesse;
return $this;
}
/**
* #return mixed
*/
public function getNbParties()
{
return $this->nbParties;
}
/**
* #param mixed $nbParties
*/
public function setNbParties($nbParties): void
{
$this->nbParties = $nbParties;
}
/**
* #return mixed
*/
public function getCartes()
{
return $this->cartes;
}
/**
* #param mixed $cartes
*/
public function setCartes($cartes): void
{
$this->cartes = $cartes;
}
/**
* #return mixed
*/
public function getEquipe()
{
return $this->equipe;
}
/**
* #param mixed $equipe
*/
public function setEquipe($equipe): void
{
$this->equipe = $equipe;
}
/**
* #return mixed
*/
public function getCentres()
{
return $this->centres;
}
/**
* #param mixed $centre
*/
public function setCentres($centres): void
{
$this->centres = $centres;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
return null;
}
/**
* Returns the username used to authenticate the user.
*
* #return string The username
*/
public function getUsername()
{
return $this->username;
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
}
}
I have also a Carte entity, a Centre entity, an Equipe entity and a Partie entity.
I'm using curl or Postamn to make requests :
I've made curl -H "Authorization: Bearer [TOKEN]" http://localhost:8000/api but the result is :
{"#context":"\/api\/contexts\/Entrypoint","#id":"\/api","#type":"Entrypoint","user":"\/api\/users","carte":"\/api\/cartes","equipe":"\/api\/equipes","centre":"\/api\/centres","partie":"\/api\/parties"}
Or with Postman :
{
"#context": "/api/contexts/Entrypoint",
"#id": "/api",
"#type": "Entrypoint",
"user": "/api/users",
"carte": "/api/cartes",
"equipe": "/api/equipes",
"centre": "/api/centres",
"partie": "/api/parties"
}
I don't get the message Logged in as [username] as expected.
How to get it ?
Thanks for help.
I had this same issue and to solve this I had to comment/remove this line from this file: config/routes/api_platform.yaml
api_platform:
resource: .
type: api_platform
# prefix: /api

Symfony 3. Problems with join and the VichUploaderBundle

I load several pictures with the Vichuploaderbundle and the EntryImg Entity.
That is successful!
I have also an Entity named Entries.
Each Entry should be linked with one or more Images
I want to join both Entities in the Repository.
What is the error?
Here is my Entries Entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
//use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\EntriesRepository")
* #ORM\Table(name="entries")
*/
class Entries
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
* #ORM\OneToMany(targetEntity="AppBundle\Entity\EntryImg", mappedBy="entries")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
/**
* #ORM\Column(type="text")
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
* #ORM\JoinColumn()
*/
private $user;
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function getDescription()
{
return $this->description();
}
public function setDescription($description)
{
$this->description = $description;
return $this;
}
public function getUser()
{
return $this->user;
}
public function setUser(User $user)
{
$this->user = $user;
}
}
My Image Entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
//use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity
* #ORM\Table(name="`entry_img`")
* #Vich\Uploadable
*/
class EntryImg
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
* #var string
*/
private $image;
/**
* #Assert\File(maxSize="2000k",mimeTypes={"image/png", "image/jpeg", "image/pjpeg"})
* #Vich\UploadableField(mapping="entry_images", fileNameProperty="image")
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="datetime")
* #var \DateTime
*/
private $updatedAt;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Entries")
* #ORM\JoinColumn(name="entries_id",referencedColumnName="id",nullable=true)
*/
private $entry;
public function setImageFile(File $image = null)
{
$this->imageFile = $image;
// VERY IMPORTANT:
// It is required that at least one field changes if you are using Doctrine,
// otherwise the event listeners won't be called and the file is lost
if ($image) {
// if 'updatedAt' is not defined in your entity, use another property
$this->updatedAt = new \DateTime('now');
}
}
public function getImageFile()
{
return $this->imageFile;
}
public function setImage($image)
{
$this->image = $image;
}
public function getImage()
{
return $this->image;
}
public function getId()
{
return $this->id;
}
public function getEntry(){
return $this->entry();
}
public function setEntry(Entries $entry){
$this->entry = $entry;
}
}
and my repository
<?php
namespace AppBundle\Repository;
use AppBundle\Entity\Entries;
use AppBundle\Entity\EntryImg;
use Doctrine\ORM\EntityRepository;
class EntriesRepository extends EntityRepository
{
public function findAllEntries($e_ids)
{
$query = $this->createQueryBuilder('e')
->leftJoin('e.id','entry_img');
$i = 0;
foreach($e_ids as $e_id){
if($i==0){
//var_dump($e_id);
$query->where('e.id = :entries_'.$i)
->setParameter('entries_'.$i,$e_id['entry']);
}else if($i>0){
$query->orWhere('e.id = :entries_'.$i)
->setParameter('entries_'.$i,$e_id['entry']);
}
$i++;
}
$result = $query->getQuery()->execute();
return $result;
}
In your class Entries, you have this line:
#ORM\OneToMany(targetEntity="AppBundle\Entity\EntryImg", mappedBy="entries")
But in your EntryImg class, there isn't any $entries property.
Also, if 1 Entries can have many EntryImg, you need to use arraycollection.
I think you should rewrite your Entries class like this:
use Doctrine\Common\Collections\ArrayCollection; //don't forget this line for the constructor
class Entries
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
//look here I remove the relation and put it on $entriesImg property
*/
private $id;
/**
* #ORM\Column(type="array")
* #ORM\OneToMany(targetEntity="AppBundle\Entity\EntryImg", mappedBy="entry") //look here I changed "entries" by "entry" which is the actual property in your EntryImg class. (you did not have any $entries property)
*/
private $entriesImg;
.. the rest of your properties
public function __construct()
{
$this->entriesImg= new ArrayCollection();
}
public function addEntryImg(\AppBundle\Entity\EntryImg $entryImg)
{
$this->entriesImg[] = $entryImg;
return $this;
}
public function removeEntryImg(\AppBundle\Entity\EntryImg $entryImg)
{
$this->entriesImg->removeElement($entryImg);
}
// also don't forget to implement classic getters and setters for the $entriesImg property
Don't forget to implement a toString method for both your entities, you will need it for Crud operation.
Then, later in your repository, you forgot to use the ->addSelect(); method like this
class EntriesRepository extends EntityRepository
{
public function findAllEntries()
{
$query = $this->createQueryBuilder('e')
->leftJoin('e.entriesImg','i');
->addSelect('i')
// whatever from your logic ....

Create login with groups (with roles) and users with revoke roles - Symfony2

I there,
I Want create a custom authentication that provides user roles, groups and roles groups. The login that i want to create is the next:
Users have groups and groups have roles;
Users have roles. This roles is for to revoke roles from groups.
ie:
Groups:
Group1: ROLE_WRITE, ROLE_READ
Group2: ROLE_CHECK, ROLE_NEW
Users:
Groups:
Group1
Group2
Roles
ROLE_CHECK
With above example the user can only use 3 roles ROLE_WRITE, ROLE_READ and ROLE_NEW
I made the following classes
Roles.php
namespace Test\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\Role\RoleInterface;
/**
* Test\OverSkyBundle\Entity\Roles
*
* #ORM\Table(name="roles")
* #ORM\Entity()
*/
class Roles implements RoleInterface{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=70, unique=true)
*/
private $role;
public function __construct( $role )
{
$this->role = $role;
}
public function getId(){
return $this->id;
}
public function getRole(){
return $this->role;
}
public function setRole($role){
$this->role = $role;
}
public function __toString()
{
return (string) $this->role;
}
}
Groups.php
namespace Test\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Test\OverSkyBundle\Entity\Groups
*
* #ORM\Table(name="groups")
* #ORM\Entity()
*/
class Groups {
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=70, unique=true)
*/
private $groupname;
/**
* #ORM\ManyToMany(targetEntity="Roles")
*
*/
private $roles;
public function __construct()
{
$this->roles = new ArrayCollection();
}
public function __toString()
{
return $this->groupname;
}
public function getId(){
return $this->id;
}
public function getRoles()
{
return $this->roles->toArray();
}
public function setRoles($roles)
{
$this->roles = $roles;
}
}
Users.php
<?php
namespace Test\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Test\OverSkyBundle\Entity\Users
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Test\UserBundle\Entity\UsersRepository")
*/
class Users implements UserInterface, \Serializable{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\ManyToMany(targetEntity="Roles")
*
*/
private $roles;
/**
* #ORM\ManyToMany(targetEntity="Groups")
*
*/
private $groups;
/**
* #ORM\Column(type="string", length=32)
*/
private $salt;
/**
* #ORM\Column(type="string", length=140)
*/
private $password;
/**
* #ORM\Column(type="string", length=140, unique=true)
*/
private $email;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
public function __toString()
{
return $this->name;
}
public function __construct() {
$this->roles = new ArrayCollection();
$this->groups = new ArrayCollection();
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}
public function getId()
{
return $this->id;
}
public function getRoles()
{
return $this->roles->toArray();
}
public function setRoles($roles)
{
$this->roles = $roles;
}
public function getGroups()
{
return $this->groups->toArray();
}
public function setGroups($groups)
{
$this->groups = $groups;
}
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
}
public function getSalt()
{
return $this->salt;
}
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function getEmail()
{
return $this->email;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function getIsActive()
{
return $this->isActive;
}
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
public function eraseCredentials() {
}
public function serialize() {
return serialize(array(
$this->id,
));
}
public function unserialize($serialized) {
list (
$this->id,
) = unserialize($serialized);
}
}
index.html.twig
{% if is_granted('ROLE_ZAP') %}
dasdsa
{% endif %}
{% for groups in app.user.groups %}
<li> groups </li>
{% endfor %}
In twig file i can access to user roles but not the groups roles. How can i merge both and revoke with the roles present in users?
If i try to execute for groups in app.user.groups.roles,I receive an error that roles is not found.
When execute if is_granted, i recieve the user roles.
is_granted() calls the user's getRoles() method and checks wether the given argument role is inside the returned array of roles. ( simplified - the security provider calls getRoles and adds them to the security-context then is_granted checks the security-context to be more precise )
Now if you want to return the roles inherited from the user's groups you will have to merge those.
Though i don't know why you're trying to revoke the user's roles from those provided by the groups ...
( normally user's roles extend their group-provided roles - if you don't want certain roles, don't add the user to the group )
... you can do something like this:
Users.php
public function getRoles()
{
$groupRoles = array();
// add all roles provided by groups
foreach ($this->getGroups() as $group) {
foreach ($group->getRoles() as $role) {
$groupRoles[] = $role;
}
}
// - remove dublicates
// - revoke user's roles
// - return remaining roles
return array_unique(array_diff($groupRoles, $this->getRoles()));
}