Backend: - Add role hierarchy (ADMIN > GESTIONNAIRE > VIEWER > USER) in security.yaml - Add password authentication on profile activation (SessionProfileController) - Add SessionProfileAuthenticator with stateless API firewall - Add ProfilePasswordHasher state processor for API Platform - Add security annotations on all 18 API Platform entities - Add denyAccessUnlessGranted on all 13 custom controllers - Add AdminProfileController for profile/role management (/api/admin/profiles) - Add InitProfilePasswordsCommand for initial admin setup - Simplify SessionProfilesController to list-only (removed create/delete) Frontend (submodule update): - Add usePermissions composable (isAdmin, canEdit, canView, isGranted) - Add password login modal on profiles page - Add admin backoffice page for profile management - Disable all form fields for ROLE_VIEWER across all edit/create pages - Show navigation buttons for all roles, hide destructive actions for viewers - Add readonly mode to ModelTypeForm and site/constructeur modals - Guard /admin routes in middleware - Configure Vite proxy for API requests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
86 lines
3.1 KiB
PHP
86 lines
3.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Command;
|
|
|
|
use App\Repository\ProfileRepository;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Command\Command;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
|
|
|
use function count;
|
|
use function in_array;
|
|
|
|
#[AsCommand(
|
|
name: 'app:init-profile-passwords',
|
|
description: 'Initialize all profile passwords to first letter of firstName + "123"',
|
|
)]
|
|
class InitProfilePasswordsCommand extends Command
|
|
{
|
|
public function __construct(
|
|
private readonly ProfileRepository $profiles,
|
|
private readonly EntityManagerInterface $em,
|
|
private readonly UserPasswordHasherInterface $passwordHasher,
|
|
) {
|
|
parent::__construct();
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
$all = $this->profiles->findAll();
|
|
|
|
if (0 === count($all)) {
|
|
$io->warning('Aucun profil trouvé.');
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
|
|
// Promote first profile to ROLE_ADMIN if none exists
|
|
$hasAdmin = false;
|
|
foreach ($all as $profile) {
|
|
if (in_array('ROLE_ADMIN', $profile->getRoles(), true)) {
|
|
$hasAdmin = true;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
$isFirst = true;
|
|
$count = 0;
|
|
foreach ($all as $profile) {
|
|
// Set password: first letter of firstName + "123"
|
|
$firstLetter = mb_strtoupper(mb_substr($profile->getFirstName(), 0, 1));
|
|
$plain = $firstLetter.'123';
|
|
$hashed = $this->passwordHasher->hashPassword($profile, $plain);
|
|
$profile->setPassword($hashed);
|
|
|
|
// Set roles: first profile → ADMIN, others → VIEWER (minimum to use the app)
|
|
if (!$hasAdmin && $isFirst) {
|
|
$profile->setRoles(['ROLE_ADMIN']);
|
|
$io->writeln(sprintf(' %s %s → mdp: %s — ROLE_ADMIN', $profile->getFirstName(), $profile->getLastName(), $plain));
|
|
$isFirst = false;
|
|
} elseif (in_array('ROLE_USER', $profile->getRoles(), true) && !in_array('ROLE_VIEWER', $profile->getRoles(), true) && !in_array('ROLE_GESTIONNAIRE', $profile->getRoles(), true) && !in_array('ROLE_ADMIN', $profile->getRoles(), true)) {
|
|
$profile->setRoles(['ROLE_VIEWER']);
|
|
$io->writeln(sprintf(' %s %s → mdp: %s — ROLE_VIEWER', $profile->getFirstName(), $profile->getLastName(), $plain));
|
|
} else {
|
|
$io->writeln(sprintf(' %s %s → mdp: %s — %s', $profile->getFirstName(), $profile->getLastName(), $plain, implode(', ', $profile->getRoles())));
|
|
}
|
|
|
|
++$count;
|
|
}
|
|
|
|
$this->em->flush();
|
|
|
|
$io->success(sprintf('%d mot(s) de passe initialisé(s).', $count));
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
}
|