0

hi im trying to encode My password for My app user So i tried to encrypted in my setPassword function
unfortunately i get this error that i don't understand: Call to a member function encodePassword() on null error pic

  <?php

 namespace App\Entity;
 use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
 use Gedmo\Mapping\Annotation as Gedmo;
 use Vich\UploaderBundle\Mapping\Annotation as Vich;
 use Symfony\Component\HttpFoundation\File\File;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Security\Core\User\UserInterface;

/**
 * Admin
 *@Vich\Uploadable
 * @ORM\Table(name="admin")
 * @ORM\Entity
 */
 class Admin implements UserInterface 
 {
  /**
 * @var int
 *
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
private $id;

/**
 * Undocumented variable
 *
 * @var UserPasswordEncoderInterface
 */
 private $passwordEncoder ;

    /**
 * @see UserInterface
 */
public function getPassword(): string
{
    return (string) $this->password;
}

public function setPassword(string $password): self

    {
     $hash= $this->passwordEncoder->encodePassword($this,$password);
     $this->password=$hash;
     return $this ;
    }
     ....... 

whats wrong, and how can i fix it ! thnx

  • 2
    Symfony container is not aware of doctrine entities, so it won't inject services (eg. `UserPasswordEncoder`) into them. If you _really_ want to do it you have to pass the dependency yourself. But that's discouraged, the preferred approach is to get the service from outside and set the already encoded password. – msg Oct 19 '20 at 00:41
  • hi @msg thnx for the comment, im using Easyadmin 3, and i couldn't find a way to manage My passwords encryption..im trying to google it the past 30mn – oussema harrabi Oct 19 '20 at 01:31
  • Does this answer your question? [Symfony 4 EasyAdmin how to encrypt passwords?](https://stackoverflow.com/questions/54744836/symfony-4-easyadmin-how-to-encrypt-passwords) – msg Oct 19 '20 at 01:50
  • That link seems to be for EA2, but the idea should be the same, do it [in the controller](https://symfony.com/doc/current/bundles/EasyAdminBundle/crud.html#creating-persisting-and-deleting-entities), or use the [event system](https://symfony.com/doc/current/bundles/EasyAdminBundle/events.html) to encode the password before saving the user. Unfortunately there's not much documentation yet. – msg Oct 19 '20 at 03:23
  • I agree with @msg, I would not not encourage to inject the dependency. Infact, I wouldn't put so much business (pw encryption) in an Entity. However, if your **really** want it, can you make `->encodePassword` a static method? – agoldev Oct 19 '20 at 10:29
  • @agoldev And making it static would do what exactly? – Cerad Oct 19 '20 at 11:55
  • @Cerad when you make `encodePassword` a static method (e.g. declare it with public static function) you can access it with `PasswordEncoder::encodePassword()` and then it is not necessary to inject PasswordEncoder as a dependency to the Entity. For helper functions this is a valid solution, but you cannot access other props or functions with $this in this method. Please read about static methods, also. – agoldev Oct 20 '20 at 07:58
  • I know that PasswordEncoder is an interface, so, you need a wrapper class for that. – agoldev Oct 20 '20 at 08:02
  • @agoldev Thanks for the hint but this is a Symfony question. You can't change the interface. Symfony supports multiple password encoders so a single static interface will not work. Notice that the code actually uses UserPasswordEncoderInterface which actually determines which specific password encoder to use based on the user type. The issue here is trying to encode the password in the user entity. There is simply no clean way to do that. And as you see from the user's 'answers', they seem to be determined to do things the hard way. – Cerad Oct 20 '20 at 12:57

3 Answers3

1

but this one work

<?php
namespace App\Controller\Admin;

use App\Entity\User;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class UserCrudController extends AbstractCrudController
{
    /** @var UserPasswordEncoderInterface */
    private $passwordEncoder;

    public static function getEntityFqcn(): string
    {
        return User::class;
    }

    public function configureFields(string $pageName): iterable
    {
        return [
            FormField::addPanel('Change password')->setIcon('fa fa-key'),
            Field::new('plainPassword', 'New password')->onlyOnForms()
                ->setFormType(RepeatedType::class)
                ->setFormTypeOptions([
                    'type' => PasswordType::class,
                    'first_options' => ['label' => 'New password'],
                    'second_options' => ['label' => 'Repeat password'],
                ]),
        ];
    }

    public function createEditFormBuilder(EntityDto $entityDto, KeyValueStore $formOptions, AdminContext $context): FormBuilderInterface
    {
        $formBuilder = parent::createEditFormBuilder($entityDto, $formOptions, $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;
    }

    /**
     * @required
     */
    public function setEncoder(UserPasswordEncoderInterface $passwordEncoder): void
    {
        $this->passwordEncoder = $passwordEncoder;
    }

    protected function addEncodePasswordEventListener(FormBuilderInterface $formBuilder)
    {
        $formBuilder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
            /** @var User $user */
            $user = $event->getData();
            if ($user->getPlainPassword()) {
                $user->setPassword($this->passwordEncoder->encodePassword($user, $user->getPlainPassword()));
            }
        });
    }
}
0

i tried to add an Event listener so i create this class

  <?php
  namespace App\Controller\Admin;
  use App\Entity\Admin;
  use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  use EasyCorp\Bundle\EasyAdminBundle\EventListener\AdminContextListener;

 class AdminController extends AdminContextListener
 {
 /**
 * @var UserPasswordEncoderInterface
 */
 private $encoder ;
 public function __construct(UserPasswordEncoderInterface $encoder)
 {
   $this->encoder=$encoder;
  }
 public static function getSetPasswordEvent()
 {
    return [
        BeforeEntityPersistedEvent::class => ['setPassword'],
    ];
}
public function setPassword(BeforeEntityPersistedEvent $event)
{
    $entity = $event->getEntityInstance();
    if (!($entity instanceof Admin)) {
        return;
    }
    $encoded = $this->encoder->encodePassword($entity, $entity->getPassword());
    $entity->setPassword($encoded);
   }
  }

and it didn't work too

0

You should do that when User register, so add this before doing flush(); for new user:

    $user = new UserEntity();
    $user->setEmail($request->getEmail());

    if ($request->getPassword())
    {
        $createUser->setPassword($this->encoder->encodePassword($user, $request->getPassword()));
    }

    $this->entityManager->persist($createUser);
    $this->entityManager->flush();
    $this->entityManager->clear();

Notice: $request containe payload comes form frontend {"email": "", "passwprd": ""}.

Notice: $createUser is a user object to flush.

Nano
  • 64
  • 1
  • 1
  • 8