mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-19 07:12:26 +02:00
SDK Form demonstrator
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\PasswordHasher\EventListener;
|
||||
|
||||
use Symfony\Component\Form\Exception\InvalidConfigurationException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
|
||||
/**
|
||||
* @author Sébastien Alfaiate <s.alfaiate@webarea.fr>
|
||||
* @author Gábor Egyed <gabor.egyed@gmail.com>
|
||||
*/
|
||||
class PasswordHasherListener
|
||||
{
|
||||
private array $passwords = [];
|
||||
|
||||
public function __construct(
|
||||
private UserPasswordHasherInterface $passwordHasher,
|
||||
private ?PropertyAccessorInterface $propertyAccessor = null,
|
||||
) {
|
||||
$this->propertyAccessor ??= PropertyAccess::createPropertyAccessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function registerPassword(FormEvent $event)
|
||||
{
|
||||
if (null === $event->getData() || '' === $event->getData()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->assertNotMapped($event->getForm());
|
||||
|
||||
$this->passwords[] = [
|
||||
'form' => $event->getForm(),
|
||||
'property_path' => $event->getForm()->getConfig()->getOption('hash_property_path'),
|
||||
'password' => $event->getData(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function hashPasswords(FormEvent $event)
|
||||
{
|
||||
$form = $event->getForm();
|
||||
|
||||
if (!$form->isRoot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($form->isValid()) {
|
||||
foreach ($this->passwords as $password) {
|
||||
$user = $this->getUser($password['form']);
|
||||
|
||||
$this->propertyAccessor->setValue(
|
||||
$user,
|
||||
$password['property_path'],
|
||||
$this->passwordHasher->hashPassword($user, $password['password'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->passwords = [];
|
||||
}
|
||||
|
||||
private function getTargetForm(FormInterface $form): FormInterface
|
||||
{
|
||||
if (!$parentForm = $form->getParent()) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
$parentType = $parentForm->getConfig()->getType();
|
||||
|
||||
do {
|
||||
if ($parentType->getInnerType() instanceof RepeatedType) {
|
||||
return $parentForm;
|
||||
}
|
||||
} while ($parentType = $parentType->getParent());
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
private function getUser(FormInterface $form): PasswordAuthenticatedUserInterface
|
||||
{
|
||||
$parent = $this->getTargetForm($form)->getParent();
|
||||
|
||||
if (!($user = $parent?->getData()) || !$user instanceof PasswordAuthenticatedUserInterface) {
|
||||
throw new InvalidConfigurationException(sprintf('The "hash_property_path" option only supports "%s" objects, "%s" given.', PasswordAuthenticatedUserInterface::class, get_debug_type($user)));
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function assertNotMapped(FormInterface $form): void
|
||||
{
|
||||
if ($this->getTargetForm($form)->getConfig()->getMapped()) {
|
||||
throw new InvalidConfigurationException('The "hash_property_path" option cannot be used on mapped field.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\PasswordHasher;
|
||||
|
||||
use Symfony\Component\Form\AbstractExtension;
|
||||
use Symfony\Component\Form\Extension\PasswordHasher\EventListener\PasswordHasherListener;
|
||||
|
||||
/**
|
||||
* Integrates the PasswordHasher component with the Form library.
|
||||
*
|
||||
* @author Sébastien Alfaiate <s.alfaiate@webarea.fr>
|
||||
*/
|
||||
class PasswordHasherExtension extends AbstractExtension
|
||||
{
|
||||
public function __construct(
|
||||
private PasswordHasherListener $passwordHasherListener,
|
||||
) {
|
||||
}
|
||||
|
||||
protected function loadTypeExtensions(): array
|
||||
{
|
||||
return [
|
||||
new Type\FormTypePasswordHasherExtension($this->passwordHasherListener),
|
||||
new Type\PasswordTypePasswordHasherExtension($this->passwordHasherListener),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\PasswordHasher\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Extension\PasswordHasher\EventListener\PasswordHasherListener;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
|
||||
/**
|
||||
* @author Sébastien Alfaiate <s.alfaiate@webarea.fr>
|
||||
*/
|
||||
class FormTypePasswordHasherExtension extends AbstractTypeExtension
|
||||
{
|
||||
public function __construct(
|
||||
private PasswordHasherListener $passwordHasherListener,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->addEventListener(FormEvents::POST_SUBMIT, [$this->passwordHasherListener, 'hashPasswords']);
|
||||
}
|
||||
|
||||
public static function getExtendedTypes(): iterable
|
||||
{
|
||||
return [FormType::class];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\PasswordHasher\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\PasswordHasher\EventListener\PasswordHasherListener;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\PropertyAccess\PropertyPath;
|
||||
|
||||
/**
|
||||
* @author Sébastien Alfaiate <s.alfaiate@webarea.fr>
|
||||
*/
|
||||
class PasswordTypePasswordHasherExtension extends AbstractTypeExtension
|
||||
{
|
||||
public function __construct(
|
||||
private PasswordHasherListener $passwordHasherListener,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if ($options['hash_property_path']) {
|
||||
$builder->addEventListener(FormEvents::POST_SUBMIT, [$this->passwordHasherListener, 'registerPassword']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'hash_property_path' => null,
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('hash_property_path', ['null', 'string', PropertyPath::class]);
|
||||
|
||||
$resolver->setInfo('hash_property_path', 'A valid PropertyAccess syntax where the hashed password will be set.');
|
||||
}
|
||||
|
||||
public static function getExtendedTypes(): iterable
|
||||
{
|
||||
return [PasswordType::class];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user