feat: Initialise l'infrastructure de base et ajoute la gestion des comptes administrateurs

Ce commit initialise la structure de base du projet, ajoute une nouvelle fonctionnalité de gestion des comptes administrateurs, et configure l'environnement de développement.

Les modifications comprennent :

- Ajout d'une commande `mainframe:admin` pour créer des comptes administrateurs via la console.
- Implémentation d'un service de Mailer avec un subscriber pour envoyer des emails lors de la création d'un compte administrateur.
- Création d'un contrôleur `Artemis/DashboardController` pour la partie administration (artemis).
- Mise à jour du `HomeController` pour rediriger les utilisateurs connectés vers le dashboard.
- Ajout de dépendances Symfony (UID) et configuration du Dockerfile (ajout de l'extension exif)
- Suppression du test `HomeControllerTest.php`
- Configuration de SonarQube et de PHPUnit pour exclure certains dossiers du code coverage.
This commit is contained in:
Serreau Jovann
2025-07-17 12:05:39 +02:00
parent d7f1fa0479
commit 2b03f715e3
13 changed files with 337 additions and 24 deletions

View File

@@ -50,6 +50,7 @@
"symfony/string": "7.3.*",
"symfony/translation": "7.3.*",
"symfony/twig-bundle": "7.3.*",
"symfony/uid": "7.3.*",
"symfony/validator": "7.3.*",
"symfony/web-link": "7.3.*",
"symfony/yaml": "7.3.*",

155
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b8542f5daf01c26d6b7aa9aa24c49b4e",
"content-hash": "7271bea1fd76a2d50dba48bc7d223135",
"packages": [
{
"name": "aws/aws-crt-php",
@@ -7619,6 +7619,85 @@
],
"time": "2025-02-20T12:04:08+00:00"
},
{
"name": "symfony/polyfill-uuid",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-uuid.git",
"reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2",
"reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"provide": {
"ext-uuid": "*"
},
"suggest": {
"ext-uuid": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Uuid\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Grégoire Pineau",
"email": "lyrixx@lyrixx.info"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for uuid functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"uuid"
],
"support": {
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/process",
"version": "v7.3.0",
@@ -9214,6 +9293,80 @@
],
"time": "2025-06-27T19:55:54+00:00"
},
{
"name": "symfony/uid",
"version": "v7.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/uid.git",
"reference": "a69f69f3159b852651a6bf45a9fdd149520525bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/uid/zipball/a69f69f3159b852651a6bf45a9fdd149520525bb",
"reference": "a69f69f3159b852651a6bf45a9fdd149520525bb",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/polyfill-uuid": "^1.15"
},
"require-dev": {
"symfony/console": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Uid\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Grégoire Pineau",
"email": "lyrixx@lyrixx.info"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to generate and represent UIDs",
"homepage": "https://symfony.com",
"keywords": [
"UID",
"ulid",
"uuid"
],
"support": {
"source": "https://github.com/symfony/uid/tree/v7.3.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-06-27T19:55:54+00:00"
},
{
"name": "symfony/validator",
"version": "v7.3.1",

View File

@@ -46,7 +46,7 @@ RUN npm install -g mjml
# Configurer et installer les extensions PHP
# Utilisation de -j$(nproc) pour paralléliser la compilation et accélérer le build
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
&& docker-php-ext-install -j$(nproc) gd pdo pdo_pgsql zip gmp bcmath intl
&& docker-php-ext-install -j$(nproc) gd pdo pdo_pgsql zip gmp bcmath intl exif
# Installer Redis via pecl
RUN pecl install redis && docker-php-ext-enable redis

View File

@@ -42,6 +42,9 @@
<directory>src</directory>
</include>
<exclude>
<directory>src/Controller</directory>
<directory>src/Command</directory>
<directory>src/Service</directory>
</exclude>

View File

@@ -17,3 +17,8 @@ sonar.sourceEncoding=UTF-8
sonar.tests=tests
sonar.sources=src
sonar.coverage.exclusions= \
src/Controller/**/*.php, \
src/Service/**/*.php, \
src/Command/*.php

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Command;
use App\Entity\Account;
use App\Service\Mailer\Event\CreatedAdminEvent;
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 Symfony\Component\Uid\Uuid;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
#[AsCommand(name: 'mainframe:admin')]
class AccountCommand extends Command
{
public function __construct(private readonly EventDispatcherInterface $eventDispatcher,private readonly UserPasswordHasherInterface $userPasswordHasher,private readonly EntityManagerInterface $entityManager,?string $name = null)
{
parent::__construct($name);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->title("Création d'un utilisateur administrateur");
$userExit = $this->entityManager->getRepository(Account::class)->findOneBy(['email'=>'jovann@siteconseil.fr']);
if(!$userExit instanceof Account){
$userExit = new Account();
$userExit->setRoles(['ROLE_ROOT']);
$userExit->setUuid(Uuid::v4());
$userExit->setEmail("jovann@siteconseil.fr");
$userExit->setUsername("jovann");
$userExit->setPassword($this->userPasswordHasher->hashPassword($userExit, 'jovann'));
$this->eventDispatcher->dispatch(new CreatedAdminEvent($userExit,"jovann"));
}
return Command::SUCCESS;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Controller\Artemis;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class DashboardController extends AbstractController
{
#[Route(path: '/artemis',name: 'artemis_dashboard',methods: ['GET', 'POST'])]
public function artemis(AuthenticationUtils $authenticationUtils): Response
{
}
}

View File

@@ -15,6 +15,9 @@ class HomeController extends AbstractController
#[Route(path: '/',name: 'app_login',methods: ['GET', 'POST'])]
public function index(AuthenticationUtils $authenticationUtils): Response
{
if($this->getUser()) {
return $this->redirectToRoute('artemis_dashboard');
}
return$this->render('admin/login.twig',[
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Service\Mailer\Event;
use App\Entity\Account;
class CreatedAdminEvent
{
private Account $account;
private string $password;
public function __construct(Account $account,string $password)
{
$this->account = $account;
$this->password = $password;
}
/**
* @return Account
*/
public function getAccount(): Account
{
return $this->account;
}
/**
* @return string
*/
public function getPassword(): string
{
return $this->password;
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Service\Mailer;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Twig\Environment;
class Mailer
{
private \Symfony\Component\Mailer\Mailer $mailer;
public function __construct(private readonly Environment $environment)
{
if($_ENV['APP_ENV'] =="dev") {
$transport = new EsmtpTransport("mailhog","1025",false);
} else {
$transport = new EsmtpTransport("mail.esy-web.dev","465",true);
$transport->setUsername("mainframe@esy-web.dev");
$transport->setPassword("31,%,ArdrOA");
}
$this->mailer = new \Symfony\Component\Mailer\Mailer($transport);
}
public function send(string $address,string $addressName,string $subject,string $template,array $data)
{
$dest = new Address($address,$addressName);
$src = new Address("mainframe@esy-web.dev","Mainframe EsyWeb");
$mail = new Email();
$mail->subject($subject);
$mail->to($dest);
$mail->from($src);
$mail->generateMessageId();
$mail->html($this->environment->render($template,array_merge([
'system' => [
]
],$data)));
$this->mailer->send($mail);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Service\Mailer;
use App\Service\Mailer\Event\CreatedAdminEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
#[AsEventListener(event: CreatedAdminEvent::class, method: 'onAdminEvent')]
class MailerSubscriber
{
public function __construct(private readonly Mailer $mailer)
{
}
public function onAdminEvent(CreatedAdminEvent $createdAdminEvent)
{
$account = $createdAdminEvent->getAccount();
$password = $createdAdminEvent->getPassword();
dd($account,$password);
$this->mailer->send($account->getEmail(),$account->getUsername(),"[MainFrame] - Création d'un compte administrateur","mails/artemis/new_admin.twig",[
'account' => $account,
'password' => $password,
]);
}
}

View File

@@ -323,6 +323,15 @@
"templates/base.html.twig"
]
},
"symfony/uid": {
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "0df5844274d871b37fc3816c57a768ffc60a43a5"
}
},
"symfony/validator": {
"version": "7.3",
"recipe": {

View File

@@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class HomeControllerTest extends WebTestCase
{
public function testIndex(): void
{
$client = static::createClient();
// Request a specific page
$crawler = $client->request('GET', '/');
// Validate a successful response and some content
$this->assertResponseIsSuccessful();
}
}