From 8d48e6e8e29685e58ec1cf39264118e091f49ca7 Mon Sep 17 00:00:00 2001 From: Louis Fortunier Date: Fri, 25 Aug 2023 10:50:23 +0200 Subject: [PATCH 1/3] Use `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` service instead of `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` because it's deprecated --- CHANGELOG.md | 5 ++++ composer.json | 8 +++--- config/bundles.php | 1 + config/services.yaml | 6 ++-- .../Extension/EncodePasswordExtension.php | 23 ++++++--------- src/Controller/AbstractSecurityController.php | 28 +++++++------------ src/DataFixtures/Processor/UserProcessor.php | 16 ++++------- src/Entity/User/UserTrait.php | 3 +- src/Mailer/EmailProvider.php | 1 + 9 files changed, 38 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 861c1ec..6706cbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ CHANGELOG for 1.x =================== +## v2.0.0 - (2023-08-25) +### Fixed +- Use `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` service instead of `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` because it's deprecated +- Stop symfony 4.4 maintenance + ## v1.5.1 - (2024-01-08) ### Changes diff --git a/composer.json b/composer.json index 0659c25..c2b644a 100644 --- a/composer.json +++ b/composer.json @@ -19,10 +19,10 @@ "doctrine/doctrine-fixtures-bundle": "^3.4", "symfony/webpack-encore-bundle": "^1.15 || ^2.0", "theofidry/alice-data-fixtures": "^1.5", - "symfony/mailer": "^4.4 || ^5.4 || ^6.0", - "symfony/property-info": "^4.4 || ^5.4 || ^6.0", - "symfony/security-http": "^4.4 || ^5.4", - "symfony/security-core": "^4.4 || ^5.4", + "symfony/mailer": "^5.4 || ^6.4", + "symfony/property-info": "^5.4 || ^6.4", + "symfony/security-http": "^5.4 || ^6.4", + "symfony/security-core": "^5.4 || ^6.4", "nelmio/security-bundle": "^2.8 || ^3.0", "yokai/security-token-bundle": "^3.3", "sentry/sentry-symfony": "^4.1", diff --git a/config/bundles.php b/config/bundles.php index a0c15a9..3727c51 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -20,4 +20,5 @@ Sonata\AdminBundle\SonataAdminBundle::class => ['all' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['prod' => true], Yokai\SecurityTokenBundle\YokaiSecurityTokenBundle::class => ['all' => true], + Sonata\BlockBundle\SonataBlockBundle::class => ['all' => true], ]; diff --git a/config/services.yaml b/config/services.yaml index bf3b191..a0ba226 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -20,7 +20,7 @@ services: admin.extension.encode_password: class: Smart\SonataBundle\Admin\Extension\EncodePasswordExtension arguments: - - '@Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface' + - '@Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface' tags: - { name: sonata.admin.extension } admin.extension.action_impersonate: @@ -49,7 +49,7 @@ services: Smart\SonataBundle\Controller\AbstractSecurityController: tags: [ 'controller.service_arguments' ] arguments: - [ '@yokai_security_token.default_token_manager', '@Smart\SonataBundle\Mailer\BaseMailer', '@translator', '@security.user_password_encoder.generic', '@Sonata\AdminBundle\Templating\TemplateRegistry', '@Doctrine\ORM\EntityManagerInterface' ] + [ '@yokai_security_token.default_token_manager', '@Smart\SonataBundle\Mailer\BaseMailer', '@translator', '@Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface', '@Sonata\AdminBundle\Templating\TemplateRegistry', '@Doctrine\ORM\EntityManagerInterface' ] Smart\SonataBundle\Admin\AbstractAdmin: abstract: true @@ -100,7 +100,7 @@ services: fixture.processor.password: class: Smart\SonataBundle\DataFixtures\Processor\UserProcessor arguments: - - '@Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface' + - '@Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface' tags: - { name: fidry_alice_data_fixtures.processor } diff --git a/src/Admin/Extension/EncodePasswordExtension.php b/src/Admin/Extension/EncodePasswordExtension.php index e699dd9..e56bf54 100644 --- a/src/Admin/Extension/EncodePasswordExtension.php +++ b/src/Admin/Extension/EncodePasswordExtension.php @@ -5,25 +5,18 @@ use Smart\SonataBundle\Security\SmartUserInterface; use Sonata\AdminBundle\Admin\AbstractAdminExtension; use Sonata\AdminBundle\Admin\AdminInterface; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; -use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; /** * @author Mathieu Ducrot */ class EncodePasswordExtension extends AbstractAdminExtension { - /** - * @var UserPasswordEncoderInterface - */ - private $encoder; + private UserPasswordHasherInterface $hasher; - /** - * @param UserPasswordEncoderInterface $encoder - */ - public function __construct(UserPasswordEncoderInterface $encoder) + public function __construct(UserPasswordHasherInterface $hasher) { - $this->encoder = $encoder; + $this->hasher = $hasher; } /** @@ -32,7 +25,7 @@ public function __construct(UserPasswordEncoderInterface $encoder) */ public function preUpdate(AdminInterface $admin, $user): void { - $this->encodePassword($user); + $this->hashPassword($user); } /** @@ -41,18 +34,18 @@ public function preUpdate(AdminInterface $admin, $user): void */ public function prePersist(AdminInterface $admin, $user): void { - $this->encodePassword($user); + $this->hashPassword($user); } /** * @param SmartUserInterface $user */ - private function encodePassword(SmartUserInterface $user): void + private function hashPassword(SmartUserInterface $user): void { if ("" === trim($user->getPlainPassword())) { return; } - $user->setPassword($this->encoder->encodePassword($user, $user->getPlainPassword())); + $user->setPassword($this->hasher->hashPassword($user, $user->getPlainPassword())); } } diff --git a/src/Controller/AbstractSecurityController.php b/src/Controller/AbstractSecurityController.php index eeb85f3..fe6c61b 100644 --- a/src/Controller/AbstractSecurityController.php +++ b/src/Controller/AbstractSecurityController.php @@ -15,8 +15,8 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; -use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; +use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; +use Symfony\Component\Security\Core\Exception\UserNotFoundException; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; use Symfony\Contracts\Translation\TranslatorInterface; @@ -38,20 +38,12 @@ class AbstractSecurityController extends AbstractController * @var string */ protected $context; - - /** - * @var TokenManagerInterface - */ - protected $tokenManager; - - /** - * @var BaseMailer - */ - protected $mailer; + protected TokenManagerInterface $tokenManager; + protected BaseMailer $mailer; protected TranslatorInterface $translator; protected UserProviderInterface $userProvider; - protected UserPasswordEncoderInterface $userPasswordEncoder; + protected UserPasswordHasherInterface $hasher; protected TemplateRegistry $templateRegistry; protected EntityManagerInterface $entityManager; @@ -59,14 +51,14 @@ public function __construct( TokenManagerInterface $tokenManager, BaseMailer $mailer, TranslatorInterface $translator, - UserPasswordEncoderInterface $userPasswordEncoder, + UserPasswordHasherInterface $hasher, TemplateRegistry $templateRegistry, EntityManagerInterface $entityManager ) { $this->tokenManager = $tokenManager; $this->mailer = $mailer; $this->translator = $translator; - $this->userPasswordEncoder = $userPasswordEncoder; + $this->hasher = $hasher; $this->templateRegistry = $templateRegistry; $this->entityManager = $entityManager; } @@ -107,7 +99,7 @@ public function forgotPassword(Request $request, ParameterBagInterface $paramete } try { - $user = $this->getUserProvider()->loadUserByUsername($form->get('email')->getData()); + $user = $this->getUserProvider()->loadUserByIdentifier($form->get('email')->getData()); if ($user instanceof SmartUserInterface) { $token = $this->tokenManager->create(Token::RESET_PASSWORD, $user); @@ -122,7 +114,7 @@ public function forgotPassword(Request $request, ParameterBagInterface $paramete $this->addFlash('success', 'flash.forgot_password.success'); } - } catch (UsernameNotFoundException $e) { + } catch (UserNotFoundException $e) { $this->addFlash('error', 'flash.forgot_password.unknown'); return $this->redirectToRoute($this->context . '_security_forgot_password'); @@ -243,7 +235,7 @@ protected function updateUser(SmartUserInterface $user) { if (null !== $user->getPlainPassword()) { $user->setPassword( - $this->userPasswordEncoder->encodePassword($user, $user->getPlainPassword()) + $this->hasher->hashPassword($user, $user->getPlainPassword()) ); } diff --git a/src/DataFixtures/Processor/UserProcessor.php b/src/DataFixtures/Processor/UserProcessor.php index 9f142f9..498b4a4 100644 --- a/src/DataFixtures/Processor/UserProcessor.php +++ b/src/DataFixtures/Processor/UserProcessor.php @@ -4,24 +4,18 @@ use Fidry\AliceDataFixtures\ProcessorInterface; use Smart\SonataBundle\Security\SmartUserInterface; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; +use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; /** * Nicolas Bastien */ class UserProcessor implements ProcessorInterface { - /** - * @var UserPasswordEncoderInterface - */ - private $encoder; + private UserPasswordHasherInterface $hasher; - /** - * @param UserPasswordEncoderInterface $encoder - */ - public function __construct(UserPasswordEncoderInterface $encoder) + public function __construct(UserPasswordHasherInterface $hasher) { - $this->encoder = $encoder; + $this->hasher = $hasher; } /** @@ -34,7 +28,7 @@ public function preProcess(string $fixtureId, $object): void return; } - $object->setPassword($this->encoder->encodePassword($object, $object->getPlainPassword() ?? 'test')); + $object->setPassword($this->hasher->hashPassword($object, $object->getPlainPassword() ?? 'test')); } /** diff --git a/src/Entity/User/UserTrait.php b/src/Entity/User/UserTrait.php index 7442010..f04da12 100644 --- a/src/Entity/User/UserTrait.php +++ b/src/Entity/User/UserTrait.php @@ -197,10 +197,9 @@ public function eraseCredentials(): void } /** - * @return array * @inheritdoc */ - public function getRoles() + public function getRoles(): array { return array_unique($this->roles); } diff --git a/src/Mailer/EmailProvider.php b/src/Mailer/EmailProvider.php index ddfd5ce..5a13340 100644 --- a/src/Mailer/EmailProvider.php +++ b/src/Mailer/EmailProvider.php @@ -100,6 +100,7 @@ private function filterEmailsByGroup(string $group): array { $toReturn = $this->getEmails(); + // @phpstan-ignore-next-line return array_filter($toReturn, function ($email) use ($group) { return preg_match("/^$group\./", $email->getCode()); }); From d8c0af2515ee2b6edd745471e45d60a1fabbce9b Mon Sep 17 00:00:00 2001 From: Mathieu Ducrot Date: Fri, 16 Feb 2024 15:50:34 +0100 Subject: [PATCH 2/3] Remove doctrine/annotations to prevent the following error : The service "doctrine.orm.default_annotation_metadata_driver" has a dependency on a non-existent service "annotation_reader". + Transform doctrine annotation to doctrine attribut for Entity files --- composer.json | 1 - src/Entity/Log/BatchLog.php | 104 +++++----------------- src/Entity/Log/HistorizableTrait.php | 4 +- src/Entity/Parameter.php | 30 +++---- src/Entity/User/PasswordSafeableTrait.php | 6 +- src/Entity/User/UserTrait.php | 75 +++------------- tests/Entity/User/User.php | 5 ++ 7 files changed, 52 insertions(+), 173 deletions(-) diff --git a/composer.json b/composer.json index c2b644a..10edfda 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,6 @@ "nelmio/security-bundle": "^2.8 || ^3.0", "yokai/security-token-bundle": "^3.3", "sentry/sentry-symfony": "^4.1", - "doctrine/annotations": "^1.0 || ^2.0", "symfony/expression-language": "^4.4 || ^5.4 || ^6.0", "smartbooster/core-bundle": "^1.0" }, diff --git a/src/Entity/Log/BatchLog.php b/src/Entity/Log/BatchLog.php index 5cc021c..2f8ac65 100644 --- a/src/Entity/Log/BatchLog.php +++ b/src/Entity/Log/BatchLog.php @@ -2,57 +2,41 @@ namespace Smart\SonataBundle\Entity\Log; +use Smart\SonataBundle\Repository\Log\BatchLogRepository; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; /** * @author Louis Fortunier - * - * @ORM\Table(name="batch_log") - * @ORM\Entity(repositoryClass="Smart\SonataBundle\Repository\Log\BatchLogRepository") */ +#[ORM\Table(name: 'batch_log')] +#[ORM\Entity(repositoryClass: BatchLogRepository::class)] class BatchLog { - /** - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @ORM\Column(name="id", type="integer") - */ - private int $id; - - /** - * @ORM\Column(name="date", type="datetime", nullable=false) - */ - private \DateTime $date; - - /** - * @ORM\Column(name="context", type="string", nullable=false) - */ - private string $context; - - /** - * Name of the batch action - * @ORM\Column(name="name", type="string", nullable=false) - */ - private string $name; - - /** - * @ORM\Column(name="summary", type="text", nullable=true) - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column] + private ?int $id = null; + + #[ORM\Column(type: Types::DATE_MUTABLE)] + private ?\DateTime $date = null; + + #[ORM\Column(length: 255)] + private ?string $context = null; + + #[ORM\Column(length: 255)] + private ?string $name = null; + + #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $summary = null; - /** - * @ORM\Column(name="comment", type="text", nullable=true) - */ + #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $comment = null; - /** - * @ORM\Column(name="data", type="json", nullable=true) - */ + #[ORM\Column(nullable: true)] private ?array $data = null; - /** - * @ORM\Column(name="success", type="boolean", nullable=true) - */ + #[ORM\Column(nullable: true)] private ?bool $success = null; public function __construct() @@ -70,113 +54,71 @@ public function getId(): ?int return $this->id; } - /** - * @return \DateTime - */ - public function getDate(): \DateTime + public function getDate(): ?\DateTime { return $this->date; } - /** - * @param \DateTime $date - */ public function setDate(\DateTime $date): void { $this->date = $date; } - /** - * @return string - */ public function getContext(): string { return $this->context; } - /** - * @param string $context - */ public function setContext(string $context): void { $this->context = $context; } - /** - * @return string - */ public function getName(): string { return $this->name; } - /** - * @param string $name - */ public function setName(string $name): void { $this->name = $name; } - /** - * @return string|null - */ public function getSummary(): ?string { return $this->summary; } - /** - * @param string|null $summary - */ public function setSummary(?string $summary): void { $this->summary = $summary; } - /** - * @return string|null - */ public function getComment(): ?string { return $this->comment; } - /** - * @param string|null $comment - */ public function setComment(?string $comment): void { $this->comment = $comment; } - /** - * @return array|null - */ public function getData(): ?array { return $this->data; } - /** - * @param array|null $data - */ public function setData(?array $data): void { $this->data = $data; } - /** - * @return bool|null - */ public function getSuccess(): ?bool { return $this->success; } - /** - * @param bool|null $success - */ public function setSuccess(?bool $success): void { $this->success = $success; diff --git a/src/Entity/Log/HistorizableTrait.php b/src/Entity/Log/HistorizableTrait.php index 75d0799..2be8227 100644 --- a/src/Entity/Log/HistorizableTrait.php +++ b/src/Entity/Log/HistorizableTrait.php @@ -13,9 +13,7 @@ trait HistorizableTrait { private ?PropertyAccessorInterface $propertyAccess = null; - /** - * @ORM\Column(type="json", nullable=true) - */ + #[ORM\Column(nullable: true)] protected ?array $history = null; public function getHistory(): ?array diff --git a/src/Entity/Parameter.php b/src/Entity/Parameter.php index f858bec..7c3a225 100644 --- a/src/Entity/Parameter.php +++ b/src/Entity/Parameter.php @@ -2,41 +2,33 @@ namespace Smart\SonataBundle\Entity; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; /** * @author Mathieu Ducrot - * - * @ORM\Table(name="smart_parameter") - * @ORM\Entity(repositoryClass="Smart\SonataBundle\Repository\ParameterRepository") */ +#[ORM\Table(name: "smart_parameter")] +#[ORM\Entity(repositoryClass: "Smart\SonataBundle\Repository\ParameterRepository")] class Parameter { - /** - * @ORM\Id - * @ORM\GeneratedValue(strategy="AUTO") - * @ORM\Column(name="id", type="integer") - */ - private int $id; + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column] + private ?int $id = null; - /** - * @ORM\Column(name="code", type="string", nullable=false, unique=true) - */ + #[ORM\Column(name: "code", unique: true, nullable: false)] private string $code; - /** - * @ORM\Column(name="value", type="text", nullable=false) - */ + #[ORM\Column(name: "value", type: Types::TEXT, nullable: false)] private string $value; - /** - * @ORM\Column(name="help", type="text", nullable=true) - */ + #[ORM\Column(name: "help", type: Types::TEXT, nullable: true)] private ?string $help = null; public function __toString() { - return (string) $this->getCode(); + return $this->getCode(); } public function getId(): ?int diff --git a/src/Entity/User/PasswordSafeableTrait.php b/src/Entity/User/PasswordSafeableTrait.php index ed90a41..84cd4ce 100644 --- a/src/Entity/User/PasswordSafeableTrait.php +++ b/src/Entity/User/PasswordSafeableTrait.php @@ -6,10 +6,6 @@ trait PasswordSafeableTrait { - /** - * @var ?string - * - * @SmartAssert\IsPasswordSafe - */ + #[SmartAssert\IsPasswordSafe] private ?string $plainPassword = null; } diff --git a/src/Entity/User/UserTrait.php b/src/Entity/User/UserTrait.php index f04da12..31897a8 100644 --- a/src/Entity/User/UserTrait.php +++ b/src/Entity/User/UserTrait.php @@ -3,6 +3,7 @@ namespace Smart\SonataBundle\Entity\User; use DateTime; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; @@ -14,64 +15,30 @@ */ trait UserTrait { - /** - * @var int - * - * @ORM\Id - * @ORM\Column(type="integer") - * @ORM\GeneratedValue(strategy="AUTO") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column] protected ?int $id = null; - /** - * @var string - * - * @ORM\Column(type="string", length=255, nullable=false, unique=true) - * - * @Assert\NotBlank - * @Assert\Email - */ + #[ORM\Column(length: 255, unique: true, nullable: false)] + #[Assert\NotBlank] + #[Assert\Email] private ?string $email = null; - /** - * @var string - * - * @ORM\Column(name="password", type="string", length=100, nullable=false) - */ + #[ORM\Column(name: "password", length: 100, nullable: false)] private ?string $password = null; - /** - * @var ?string - */ private ?string $plainPassword = null; - /** - * @var string - * - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(length: 255, nullable: true)] protected ?string $firstName = null; - /** - * @var string - * - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(length: 255, nullable: true)] protected ?string $lastName = null; - /** - * @ORM\Column(type="json") - */ - private array $roles = []; - - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: Types::DATE_MUTABLE, nullable: true)] protected ?DateTime $lastLogin = null; - /** - * @return string - */ public function __toString() { return $this->getListDisplay(); @@ -196,26 +163,6 @@ public function eraseCredentials(): void $this->plainPassword = null; } - /** - * @inheritdoc - */ - public function getRoles(): array - { - return array_unique($this->roles); - } - - /** - * @param array $roles - * - * @return $this - */ - public function setRoles(array $roles = []) - { - $this->roles = $roles; - - return $this; - } - /** * @return string */ diff --git a/tests/Entity/User/User.php b/tests/Entity/User/User.php index 6d4201f..3a8706f 100644 --- a/tests/Entity/User/User.php +++ b/tests/Entity/User/User.php @@ -13,4 +13,9 @@ class User implements UserInterface { use UserTrait; + + public function getRoles(): array + { + return []; + } } From 0e158dddd8d48921621fee3f3bca044d2ae0b891 Mon Sep 17 00:00:00 2001 From: Mathieu Ducrot Date: Mon, 19 Feb 2024 15:32:33 +0100 Subject: [PATCH 3/3] Handle AbstractAdmin::setTokenManager via AdminCompilerPass + Fix login-box style + nelmio_alice default locale + flag AbstractAdmin::get as deprecated + add missing admin/security trads --- CHANGELOG.md | 24 +++++++++++++-- assets/styles/_login.scss | 3 +- config/bundle_prepend_config.yml | 3 ++ config/services.yaml | 6 ---- src/Admin/AbstractAdmin.php | 4 ++- src/Admin/SmartAdminInterface.php | 29 +++++++++++++++++++ .../Compiler/AdminCompilerPass.php | 28 ++++++++++++++++++ src/SmartSonataBundle.php | 9 ++++++ translations/admin.en.xlf | 8 +++++ translations/admin.fr.xlf | 4 +++ translations/security.en.xliff | 4 +++ translations/security.fr.xliff | 4 +++ 12 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 src/Admin/SmartAdminInterface.php create mode 100644 src/DependencyInjection/Compiler/AdminCompilerPass.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 6706cbe..59a0715 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,27 @@ CHANGELOG for 1.x =================== -## v2.0.0 - (2023-08-25) +## v2.0.0 - (2024-02-19) +### Added +- **Add Symfony v6.4 support** +- Default `nelmio_alice` locale config to **fr_FR** +- `SmartAdminInterface` which is used on AdminCompilerPass to add the required extra services +- Missing admin and security trad added + +### Removed +- **Drop Symfony v4 support** +- Remove `doctrine/annotations` as we now use PHP8 attributes to define ORM properties +- User roles aren't stored in database anymore, each entity with UserInterface must just define the getRoles function + +### Changed +- Use `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` service instead of `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` to be compatible with +SF 6 +- Reformat all the entity annotations with PHP8 attributes +- `AbstractAdmin::setTokenManager` is now preset by the new `AdminCompilerPass` (as the services.yaml abstract: true old way don't work properly with +SF 6 and the latest Sonata version) +- The `AbstractAdmin::get` function has been flagged as @deprecated and will be remove next major (instead inject service via construct DI) + ### Fixed -- Use `Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface` service instead of `Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface` because it's deprecated -- Stop symfony 4.4 maintenance +- Fix auto margin of the login-box using display flex ## v1.5.1 - (2024-01-08) diff --git a/assets/styles/_login.scss b/assets/styles/_login.scss index f3af88a..4261ec1 100644 --- a/assets/styles/_login.scss +++ b/assets/styles/_login.scss @@ -6,10 +6,11 @@ html.login, html.login body { .wrapper { background: none; + display: flex; .login-box, .register-box { width: 375px; - margin: 15% auto; + margin: auto; } .login-box-body { box-shadow: 3px 3px 0 rgba(12,12,12,.3); diff --git a/config/bundle_prepend_config.yml b/config/bundle_prepend_config.yml index 21d1774..08cefcb 100644 --- a/config/bundle_prepend_config.yml +++ b/config/bundle_prepend_config.yml @@ -37,6 +37,9 @@ yokai_security_token: reset_password: duration: +1 month +nelmio_alice: + locale: fr_FR + smart_sonata: emails: - admin.security.forgot_password diff --git a/config/services.yaml b/config/services.yaml index a0ba226..e516a6e 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -51,12 +51,6 @@ services: arguments: [ '@yokai_security_token.default_token_manager', '@Smart\SonataBundle\Mailer\BaseMailer', '@translator', '@Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface', '@Sonata\AdminBundle\Templating\TemplateRegistry', '@Doctrine\ORM\EntityManagerInterface' ] - Smart\SonataBundle\Admin\AbstractAdmin: - abstract: true - calls: - - setContainer: [ '@Symfony\Component\DependencyInjection\ContainerInterface' ] - - setTokenManager: [ '@security.token_storage' ] - smart_sonata.parameter_provider: class: Smart\SonataBundle\Provider\ParameterProvider public: true diff --git a/src/Admin/AbstractAdmin.php b/src/Admin/AbstractAdmin.php index 6e88abc..a3aee28 100644 --- a/src/Admin/AbstractAdmin.php +++ b/src/Admin/AbstractAdmin.php @@ -13,7 +13,7 @@ /** * @author Nicolas Bastien */ -abstract class AbstractAdmin extends \Sonata\AdminBundle\Admin\AbstractAdmin +abstract class AbstractAdmin extends \Sonata\AdminBundle\Admin\AbstractAdmin implements SmartAdminInterface { public const ACTION_CREATE = 'CREATE'; public const ACTION_VIEW = 'VIEW'; @@ -30,6 +30,7 @@ public function __construct(string $code, ?string $class, string $baseController $this->init($code, $class, $baseControllerName); } + // Requires to always call the parent to remove the export route if the method is redefined in a concrete admin implementation and don't want it protected function configureRoutes(RouteCollectionInterface $collection): void { $collection->remove('export'); @@ -65,6 +66,7 @@ protected function getUser() } /** + * @deprecated Do a service injection via the __construct instead of using the get method * @param string $id * * @return object diff --git a/src/Admin/SmartAdminInterface.php b/src/Admin/SmartAdminInterface.php new file mode 100644 index 0000000..1445f80 --- /dev/null +++ b/src/Admin/SmartAdminInterface.php @@ -0,0 +1,29 @@ + + */ +interface SmartAdminInterface +{ + /** + * @deprecated Do a service injection via the __construct instead of using the get method + */ + public function setContainer(ContainerInterface $container): void; + + /** + * Require for the getUser method + */ + public function setTokenManager(TokenStorageInterface $tokenStorage): void; + + public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string; + + /** + * @param mixed $attributes + */ + public function smartIsGranted($attributes, ?object $object = null): bool; +} diff --git a/src/DependencyInjection/Compiler/AdminCompilerPass.php b/src/DependencyInjection/Compiler/AdminCompilerPass.php new file mode 100644 index 0000000..ddf7f9d --- /dev/null +++ b/src/DependencyInjection/Compiler/AdminCompilerPass.php @@ -0,0 +1,28 @@ +findTaggedServiceIds('sonata.admin')) as $adminId) { + $adminDefinition = $container->getDefinition($adminId); + $adminClass = $adminDefinition->getClass(); + if (!class_exists($adminClass) || !isset(class_implements($adminClass)[SmartAdminInterface::class])) { + continue; + } + $adminDefinition->addMethodCall('setTokenManager', [new Reference('security.token_storage')]); + $adminDefinition->addMethodCall('setContainer', [new Reference('Symfony\Component\DependencyInjection\ContainerInterface')]); + } + } +} diff --git a/src/SmartSonataBundle.php b/src/SmartSonataBundle.php index 5e5186b..eba83a3 100644 --- a/src/SmartSonataBundle.php +++ b/src/SmartSonataBundle.php @@ -2,6 +2,8 @@ namespace Smart\SonataBundle; +use Smart\SonataBundle\DependencyInjection\Compiler\AdminCompilerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; /** @@ -13,4 +15,11 @@ public function getPath(): string { return \dirname(__DIR__); } + + public function build(ContainerBuilder $container): void + { + parent::build($container); + + $container->addCompilerPass(new AdminCompilerPass()); + } } diff --git a/translations/admin.en.xlf b/translations/admin.en.xlf index a68a786..5ff2ea0 100644 --- a/translations/admin.en.xlf +++ b/translations/admin.en.xlf @@ -50,10 +50,18 @@ fieldset.label_general General informations + + fieldset.label_password + Password + fieldset.label_profile My profile + + fieldset.label_log + Log + field.label_id diff --git a/translations/admin.fr.xlf b/translations/admin.fr.xlf index a257aaf..75d7cae 100644 --- a/translations/admin.fr.xlf +++ b/translations/admin.fr.xlf @@ -67,6 +67,10 @@ fieldset.label_general Informations générales + + fieldset.label_password + Mot de passe + fieldset.label_profile Mon compte diff --git a/translations/security.en.xliff b/translations/security.en.xliff index 3298856..eee0614 100644 --- a/translations/security.en.xliff +++ b/translations/security.en.xliff @@ -26,6 +26,10 @@ Bad credentials. Username or invalid password. + + The presented password is invalid. + Username or invalid password. + login.action.forgot_password Forgot password ? diff --git a/translations/security.fr.xliff b/translations/security.fr.xliff index fcf3e4d..6eefbb5 100644 --- a/translations/security.fr.xliff +++ b/translations/security.fr.xliff @@ -26,6 +26,10 @@ Bad credentials. Nom d'utilisateur ou mot de passe invalides. + + The presented password is invalid. + Nom d'utilisateur ou mot de passe invalides. + login.action.forgot_password Mot de passe oublié ?