diff --git a/appli_sf/src/Command/AddClientCommand.php b/appli_sf/src/Command/AddClientCommand.php index 0f0746644bf7ced78cc217532020e12bd3618a61..b9fe201ebbc9ec9f30bc5a3375684ada154717c2 100644 --- a/appli_sf/src/Command/AddClientCommand.php +++ b/appli_sf/src/Command/AddClientCommand.php @@ -10,10 +10,13 @@ use App\Utility\Validator; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; +use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Contracts\Translation\TranslatorInterface; +use function Symfony\Component\String\u; class AddClientCommand extends Command { @@ -49,7 +52,22 @@ class AddClientCommand extends Command protected function configure() { $this - ->setDescription('Ajout d\'un nouvel utilisateur en base de données'); + ->setDescription('Ajout d\'un nouvel utilisateur en base de données') + ->addOption('username', 'u', InputOption::VALUE_REQUIRED, 'Identifiant du nouvel utilisateur') + ->addOption('password', 'p', InputOption::VALUE_REQUIRED, 'Mot de passe du nouvel utilisateur') + ->addOption('email', 'm', InputOption::VALUE_REQUIRED, 'Email du nouvel utilisateur') + ->addOption('role', 'r', InputOption::VALUE_REQUIRED, 'Role du nouvel utilisateur') + ->addOption('name', 'd', InputOption::VALUE_REQUIRED, 'Nom du nouvel utilisateur') + ->addOption('service', null, InputOption::VALUE_OPTIONAL, 'Service du nouvel utilisateur') + ->addOption('address', null, InputOption::VALUE_OPTIONAL, 'Adresse du nouvel utilisateur') + ->addOption( + 'additional-address', + null, + InputOption::VALUE_OPTIONAL, + 'Complément d\'adresse du nouvel utilisateur' + ) + ->addOption('postal-code', null, InputOption::VALUE_OPTIONAL, 'Code postal du nouvel utilisateur') + ->addOption('town', null, InputOption::VALUE_OPTIONAL, 'Ville du nouvel utilisateur'); } protected function initialize(InputInterface $input, OutputInterface $output): void @@ -57,121 +75,312 @@ class AddClientCommand extends Command $this->io = new SymfonyStyle($input, $output); } - protected function execute( - InputInterface $input, - OutputInterface $output - ): int { + protected function interact(InputInterface $input, OutputInterface $output) + { $this->io->title("Ajout d'un utilisateur"); - $username = $this->io->ask( - $this->translator->trans('addUserCmd.login'), - null, - [$this->validator, 'validateUsername'] - ); + $username = $input->getOption('username'); - $user = new User(); - $user->setUsername($username); + if (null !== $username) { + $this->io->text(' > <info>'.$this->translator->trans('addUserCmd.login').'</info>: '.$username); + } else { + $username = $this->io->ask( + $this->translator->trans('addUserCmd.login'), + null, + [$this->validator, 'validateUsername'] + ); + $input->setOption('username', $username); + } - $email = $this->io->ask( - $this->translator->trans('addUserCmd.email'), - null, - [$this->validator, 'validateEmail'] - ); + $email = $input->getOption('email'); - $user->setEmail($email); + if (null !== $email) { + $this->io->text(' > <info>'.$this->translator->trans('addUserCmd.email').'</info>: '.$email); + } else { + $email = $this->io->ask( + $this->translator->trans('addUserCmd.email'), + null, + [$this->validator, 'validateEmail'] + ); + $input->setOption('email', $email); + } - $password = $this->io->askHidden( - $this->translator->trans('addUserCmd.password'), - [$this->validator, 'validatePassword'] - ); + $password = $input->getOption('password'); - $encodedPassword = $this->passwordEncoder->encodePassword($user, $password); - $user->setPassword($encodedPassword); + if (null !== $password) { + $this->io->text( + ' > <info>'.$this->translator->trans('addUserCmd.password').'</info>: ' + .u('*')->repeat(u($password)->length()) + ); + } else { + $password = $this->io->askHidden( + $this->translator->trans('addUserCmd.password'), + [$this->validator, 'validatePassword'] + ); - $confirmPassword = $this->io->askHidden( - $this->translator->trans('addUserCmd.confirmPassword'), - function ($confirmPassword) use ($password) { - if (empty($confirmPassword)) { - throw new \RuntimeException($this->translator->trans('addUser.error.notEmpty')); - } + $confirmPassword = $this->io->askHidden( + $this->translator->trans('addUserCmd.confirmPassword'), + function ($confirmPassword) use ($password) { + if (empty($confirmPassword)) { + throw new \RuntimeException($this->translator->trans('addUser.error.notEmpty')); + } + + if ($confirmPassword !== $password) { + throw new \RuntimeException( + $this->translator->trans('addUser.error.confirmPasswordNoMatch') + ); + } - if ($confirmPassword !== $password) { - throw new \RuntimeException( - $this->translator->trans('addUser.error.confirmPasswordNoMatch') - ); + return $confirmPassword; } + ); - return $confirmPassword; - } - ); + if ($password !== $confirmPassword) { + $this->io->error($this->translator->trans('addUser.error.confirmPasswordNoMatch')); - if ($password !== $confirmPassword) { - $this->io->error($this->translator->trans('addUser.error.confirmPasswordNoMatch')); + return 3; + } - return 3; + $input->setOption('password', $password); } - $rolesList = [ - 1 => $this->translator->trans('ROLE_NOTARY'), - 2 => $this->translator->trans('ROLE_AGENT'), - 3 => $this->translator->trans('ROLE_ADMIN'), - ]; - $roleValue = $this->io->choice($this->translator->trans('addUserCmd.role'), $rolesList, 3); - $roleKey = array_search($roleValue, $rolesList); - $role = UserHelper::getRoleFromInt($roleKey); - $user->setRoles([$role]); + $role = $input->getOption('role'); - $name = $this->io->ask( - $this->translator->trans('addUserCmd.name'), - null, - [$this->validator, 'validateNotEmpty'] - ); - $user->setName($name); + if (null !== $role) { + $this->io->text( + ' > <info>'.$this->translator->trans('addUserCmd.role').'</info>: '.$role + ); + } else { + $rolesList = [ + 1 => $this->translator->trans('ROLE_NOTARY'), + 2 => $this->translator->trans('ROLE_AGENT'), + 3 => $this->translator->trans('ROLE_ADMIN'), + ]; + $roleValue = $this->io->choice($this->translator->trans('addUserCmd.role'), $rolesList, 3); + $roleKey = array_search($roleValue, $rolesList); + $role = UserHelper::getRoleFromInt($roleKey); - if ($role === UserHelper::ROLE_AGENT) { - $service = $this->io->ask( - $this->translator->trans('addUserCmd.service'), + $input->setOption('role', $role); + } + + $name = $input->getOption('name'); + + if (null !== $name) { + $this->io->text( + ' > <info>'.$this->translator->trans('addUserCmd.name').'</info>: '.$name + ); + } else { + $name = $this->io->ask( + $this->translator->trans('addUserCmd.name'), null, [$this->validator, 'validateNotEmpty'] ); - $user->setService($service); + + $input->setOption('name', $name); + } + + if ($role === UserHelper::ROLE_AGENT) { + $service = $input->getOption('service'); + + if (null !== $service) { + $this->io->text( + ' > <info>'.$this->translator->trans('addUserCmd.service').'</info>: '.$service + ); + } else { + $service = $this->io->ask( + $this->translator->trans('addUserCmd.service'), + null, + [$this->validator, 'validateNotEmpty'] + ); + + $input->setOption('service', $service); + } } if ($role === UserHelper::ROLE_NOTARY) { - $address = $this->io->ask( - $this->translator->trans('addUserCmd.address'), - null, - [$this->validator, 'validateNotEmpty'] - ); - $user->setAddress($address); + $address = $input->getOption('address'); - $additionalAddress = $this->io->ask( - $this->translator->trans('addUserCmd.additionnalAddress'), - null, - [$this->validator, 'validateNotEmpty'] - ); - $user->setAdditionalAddress($additionalAddress); + if (null !== $address) { + $this->io->text( + ' > <info>'.$this->translator->trans('addUserCmd.address').'</info>: '.$address + ); + } else { + $address = $this->io->ask( + $this->translator->trans('addUserCmd.address'), + null, + [$this->validator, 'validateNotEmpty'] + ); - $postalCode = $this->io->ask( - $this->translator->trans('addUserCmd.postalCode'), - null, - [$this->validator, 'validateNotEmpty'] - ); - $user->setPostalCode($postalCode); + $input->setOption('address', $address); + } - $town = $this->io->ask( - $this->translator->trans('addUserCmd.town'), - null, - [$this->validator, 'validateNotEmpty'] - ); - $user->setTown($town); + + $additionalAddress = $input->getOption('additional-address'); + + if (null !== $additionalAddress) { + $this->io->text( + ' > <info>'.$this->translator->trans('addUserCmd.additionalAddress').'</info>: '.$additionalAddress + ); + } else { + $additionalAddress = $this->io->ask( + $this->translator->trans('addUserCmd.additionalAddress'), + null, + [$this->validator, 'validateNotEmpty'] + ); + + $input->setOption('additional-address', $additionalAddress); + } + + + $postalCode = $input->getOption('postal-code'); + + if (null !== $postalCode) { + $this->io->text( + ' > <info>'.$this->translator->trans('addUserCmd.postalCode').'</info>: '.$postalCode + ); + } else { + $postalCode = $this->io->ask( + $this->translator->trans('addUserCmd.postalCode'), + null, + [$this->validator, 'validateNotEmpty'] + ); + + $input->setOption('postal-code', $postalCode); + } + + + $town = $input->getOption('town'); + + if (null !== $town) { + $this->io->text( + ' > <info>'.$this->translator->trans('addUserCmd.town').'</info>: '.$town + ); + } else { + $town = $this->io->ask( + $this->translator->trans('addUserCmd.town'), + null, + [$this->validator, 'validateNotEmpty'] + ); + + $input->setOption('town', $town); + } } + } + + protected function execute( + InputInterface $input, + OutputInterface $output + ): int { + + $stopwatch = new Stopwatch(); + $stopwatch->start('add-user-command'); + + $username = $input->getOption('username'); + $plainPassword = $input->getOption('password'); + $email = $input->getOption('email'); + $role = $input->getOption('role'); + $name = $input->getOption('name'); + $service = $input->getOption('service'); + $address = $input->getOption('address'); + $additionalAddress = $input->getOption('additional-address'); + $postalCode = $input->getOption('postal-code'); + $town = $input->getOption('town'); + + $this->validateUserData( + $username, + $plainPassword, + $email, + $name, + $role, + $service, + $address, + $additionalAddress, + $postalCode, + $town + ); + + $user = new User(); + $user->setUsername($username); + + $encodedPassword = $this->passwordEncoder->encodePassword($user, $plainPassword); + $user->setPassword($encodedPassword); + + $user->setEmail($email); + $user->setRoles([$role]); + $user->setName($name); + $user->setService($service); + $user->setAddress($address); + $user->setAdditionalAddress($additionalAddress); + $user->setPostalCode($postalCode); + $user->setTown($town); $this->entityManager->persist($user); $this->entityManager->flush(); $this->io->success($this->translator->trans('addUser.success.userCreated', [$username, $role])); - return 0; + $event = $stopwatch->stop('add-user-command'); + if ($output->isVerbose()) { + $this->io->comment( + sprintf( + 'New user database id: %d / Elapsed time: %.2f ms / Consumed memory: %.2f MB', + $user->getId(), + $event->getDuration(), + $event->getMemory() / (1024 ** 2) + ) + ); + } + + return Command::SUCCESS; + } + + /** + * @param string $username + * @param string $plainPassword + * @param string $email + * @param string $name + * @param string $role + * @param string $service + * @param string $address + * @param string $additionalAddress + * @param string $postalCode + * @param string $town + */ + private function validateUserData( + $username, + $plainPassword, + $email, + $name, + $role, + $service = '', + $address = '', + $additionalAddress = '', + $postalCode = '', + $town = '' + ): void { + // first check if a user with the same username already exists. + $existingUser = $this->userRepository->findOneBy(['username' => $username]); + + if (null !== $existingUser) { + throw new \RuntimeException( + sprintf('There is already a user registered with the "%s" username.', $username) + ); + } + + // validate password and email if is not this input means interactive. + $this->validator->validatePassword($plainPassword); + $this->validator->validateEmail($email); + $this->validator->validateNotEmpty($name, 'name'); + + if ($role === UserHelper::ROLE_AGENT) { + $this->validator->validateNotEmpty($service, 'service'); + } + + if ($role === UserHelper::ROLE_NOTARY) { + $this->validator->validateNotEmpty($address, 'address'); + $this->validator->validateNotEmpty($additionalAddress, 'additionalAddress'); + $this->validator->validateNotEmpty($postalCode, 'postalCode'); + $this->validator->validateNotEmpty($town, 'town'); + } } } diff --git a/appli_sf/src/Form/UserType.php b/appli_sf/src/Form/UserType.php index f0401bbd3e16d1021a9c67c511d0751d3a2190dd..509e8eeee973221e89143c59535762927fd5b5ee 100644 --- a/appli_sf/src/Form/UserType.php +++ b/appli_sf/src/Form/UserType.php @@ -127,7 +127,7 @@ class UserType extends AbstractType 'additionalAddress', TextType::class, [ - 'label' => 'addUser.additionnalAddress', + 'label' => 'addUser.additionalAddress', 'required' => false, ] ) diff --git a/appli_sf/src/Utility/Validator.php b/appli_sf/src/Utility/Validator.php index ca14f907a5794be12612f628b8faf1a9fd93c586..ba9f2a9ca5265054e8983c8a00107b7facc29436 100644 --- a/appli_sf/src/Utility/Validator.php +++ b/appli_sf/src/Utility/Validator.php @@ -35,7 +35,12 @@ class Validator public function validateUsername(?string $username): string { if (empty($username)) { - throw new InvalidArgumentException($this->translator->trans('addUser.error.notEmpty')); + throw new InvalidArgumentException( + $this->translator->trans( + 'addUser.error.notEmpty', + ['%field%' => $this->translator->trans('addUser.login')] + ) + ); } $user = $this->userRepository->findOneBy(['username' => $username]); @@ -59,7 +64,12 @@ class Validator public function validateEmail(?string $email): string { if (empty($email)) { - throw new InvalidArgumentException($this->translator->trans('addUser.error.notEmpty')); + throw new InvalidArgumentException( + $this->translator->trans( + 'addUser.error.notEmpty', + ['%field%' => $this->translator->trans('addUser.email')] + ) + ); } $userEmail = $this->userRepository->findOneBy(['email' => $email]); @@ -83,7 +93,12 @@ class Validator public function validatePassword(?string $plainPassword): string { if (empty($plainPassword)) { - throw new InvalidArgumentException($this->translator->trans('addUser.error.notEmpty')); + throw new InvalidArgumentException( + $this->translator->trans( + 'addUser.error.notEmpty', + ['%field%' => $this->translator->trans('addUser.password')] + ) + ); } $passwordConstraint = new PasswordRequirements( @@ -118,12 +133,23 @@ class Validator * * @param string|null $value * + * @param string $name + * * @return string */ - public function validateNotEmpty(?string $value): string + public function validateNotEmpty(?string $value, $name = null): string { if (empty($value)) { - throw new InvalidArgumentException($this->translator->trans('addUser.error.notEmpty')); + throw new InvalidArgumentException( + $name ? + $this->translator->trans( + 'addUser.error.notEmptyFieldName', + ['%fieldName%' => $this->translator->trans('addUser.'.$name)] + ) : + $this->translator->trans( + 'addUser.error.notEmpty' + ) + ); } return $value; diff --git a/appli_sf/translations/messages.fr.yaml b/appli_sf/translations/messages.fr.yaml index c69cf91805a73bc28b97832aeed0fa0e5f27b992..7f5d93411e5a9a997a66c14ef84c8895d3f3cd40 100644 --- a/appli_sf/translations/messages.fr.yaml +++ b/appli_sf/translations/messages.fr.yaml @@ -16,7 +16,7 @@ addUser: roleConsole: "Rôle \n1) Étude notariale \n2) Agent du département \n3) Administrateur\n> " service: "Service" address: "Adresse" - additionnalAddress: "Complément d'adresse" + additionalAddress: "Complément d'adresse" postalCode: "Code postal" town: "Ville" send: "Ajouter" @@ -25,6 +25,7 @@ addUser: userUsernameExists: "L'utilisateur '%username%' existe déjà !" confirmPasswordNoMatch: "Les mots de passe ne correspondent pas" notEmpty: "Ce champ ne peut être vide" + notEmptyFieldName: "%fieldName% : Ce champ ne peut être vide" success: userCreated: "L'utilisateur '0' a été créé avec le(s) role(s) [1] !" confirmEmail: @@ -38,7 +39,7 @@ addUserCmd: role: "Profil" service: "Service" address: "Adresse" - additionnalAddress: "Complément d'adresse" + additionalAddress: "Complément d'adresse" postalCode: "Code postal" town: "Ville" userEdit: diff --git a/bin/console b/bin/console index b7693ffc76c96da1528aea6d111c85281f66373e..257b3f2f7b41acaecddef30eab976ab34b9e1b0e 100755 --- a/bin/console +++ b/bin/console @@ -2,4 +2,4 @@ ./bin/test-php-docker-running -docker-compose exec php //entrypoint bin/console $@ +docker-compose exec php //entrypoint bin/console "$@"