Commit 3beffb61 authored by Baudouin Feildel's avatar Baudouin Feildel
Browse files

Add commands to change user passwords

parent ca3971b3
<?php
namespace App\Command;
use App\Entity\Lizmap\LizmapUser;
use App\Entity\User;
use Doctrine\Common\Persistence\ManagerRegistry;
use SplFileObject;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
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\HttpFoundation\File\File;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class AppUserBatchSetPassword extends Command
{
protected static $defaultName = 'app:user:batch-set-password';
protected $encoder;
protected $emDdec;
protected $emLizmap;
public function __construct(UserPasswordEncoderInterface $encoder, ManagerRegistry $doctrine) {
parent::__construct(self::$defaultName);
$this->encoder = $encoder;
$this->emDdec = $doctrine->getManager('ddec');
$this->emLizmap = $doctrine->getManager('lizmap');
}
protected function configure()
{
$this
->setDescription('Set password for multiple users')
->setHelp("The password will be set for DDEC-Info user and Lizmap user if any.\nThe input file is a CSV with two columns: 'email;password'")
->addArgument('input_file', InputArgument::REQUIRED, 'The input file')
->addArgument('csv_delimiter', InputArgument::OPTIONAL, 'CSV delimiter, by default: ";"', ';')
->addOption('has-header', null, InputOption::VALUE_OPTIONAL, 'The input file has header line', false)
;
}
private const NOT_FOUND = "not found";
private const OK_NO_LIZMAP = "OK (no lizmap user found)";
private const OK = "OK";
protected function setPasswordForUser(string $email, string $password): string {
/** @var User $user */
$user = $this->emDdec->getRepository(User::class)->findOneBy(['email' => $email]);
if ($user === null) {
return self::NOT_FOUND;
}
$encodedPassword = $this->encoder->encodePassword($user, $password);
$user->setPassword($encodedPassword);
$this->emDdec->persist($user);
$this->emDdec->flush();
$lizmapUser = $this->emLizmap->getRepository(LizmapUser::class)->fromDdecInfoUser($user);
if ($lizmapUser === null) {
return self::OK_NO_LIZMAP;
} else {
$lizmapUser->setPassword($encodedPassword);
$this->emLizmap->persist($lizmapUser);
$this->emLizmap->flush();
}
return self::OK;
}
protected function readInputFile(string $file, string $delimiter, bool $has_header) : array {
$file = new File($file);
$f = $file->openFile();
$f->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE);
$f->setCsvControl($delimiter, "\"", "\\");
$i = 0;
$data = [];
foreach ($f as $line) {
if($has_header && $i === 0)
$i++;
else if($line !== false)
$data[] = $line;
}
return $data;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->section("Read input file : " . $input->getArgument('input_file'));
$data = $this->readInputFile(
$input->getArgument('input_file'),
$input->getArgument('csv_delimiter'),
$input->getOption('has-header'));
$io->section("Set passwords for " . count($data) . " users.");
foreach ($data as $line) {
$status = $this->setPasswordForUser($line[0], $line[1]);
$io->text("User $line[0] $status");
}
$io->success("File processed");
}
}
<?php
namespace App\Command;
use App\Entity\Lizmap\LizmapUser;
use App\Entity\User;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class AppUserSetPassword extends Command
{
protected static $defaultName = 'app:user:set-password';
protected $encoder;
protected $emDdec;
protected $emLizmap;
public function __construct(UserPasswordEncoderInterface $encoder, ManagerRegistry $doctrine) {
parent::__construct(self::$defaultName);
$this->encoder = $encoder;
$this->emDdec = $doctrine->getManager('ddec');
$this->emLizmap = $doctrine->getManager('lizmap');
}
protected function configure()
{
$this
->setDescription('Set password for one user')
->setHelp('The password will be set for DDEC-Info user and Lizmap user if any')
->addArgument('email', InputArgument::OPTIONAL, 'The user email (in ddec-info)')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
if(!$input->hasArgument('email') || $input->getArgument('email') === null) {
$email = $io->ask('User email');
} else {
$email = $input->getArgument('email');
$io->note(sprintf('Set password for user with email address: %s', $email));
}
/** @var User $user */
$user = $this->emDdec->getRepository(User::class)->findOneBy(['email' => $email]);
if ($user === null) {
$io->error(sprintf('User not found'));
return;
}
$encodedPassword = $this->encoder->encodePassword($user, $io->askHidden('User password'));
$user->setPassword($encodedPassword);
$this->emDdec->persist($user);
$this->emDdec->flush();
$lizmapUser = $this->emLizmap->getRepository(LizmapUser::class)->fromDdecInfoUser($user);
if ($lizmapUser === null) {
$io->note("No linked lizmap user found");
} else {
$io->note("Linked lizmap user found, set password.");
$lizmapUser->setPassword($encodedPassword);
$this->emLizmap->persist($lizmapUser);
$this->emLizmap->flush();
}
$io->success('User password set successfully');
}
}
......@@ -4,6 +4,7 @@ namespace App\Repository\Lizmap;
use App\Entity\Lizmap\LizmapUser;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NonUniqueResultException;
......@@ -53,4 +54,16 @@ class LizmapUserRepository extends EntityRepository implements ServiceEntityRepo
return null;
}
}
public function fromDdecInfoUser(User $user): ?LizmapUser {
try {
return $this->createQueryBuilder('u')
->where('u.usr_login = :username')
->setParameter('username', $user->getLizmapLogin())
->getQuery()
->getOneOrNullResult();
} catch (NonUniqueResultException $e) {
return null;
}
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment