feat(Security/PasswordGenerator): Ajoute un générateur de mot de passe.

 feat(src/Service): Ajoute un event pour la création d'une boite mail client.
 feat(templates): Ajoute le template de mail pour la création de boite mail.
 feat(src/Form): Ajoute le formulaire de création de boite mail.
 feat(src/Controller): Gère la création de boite mail et envoi du mail.
This commit is contained in:
Serreau Jovann
2025-09-27 16:16:50 +02:00
parent 95c1a665ad
commit 98f7581b22
7 changed files with 193 additions and 2 deletions

View File

@@ -13,6 +13,7 @@ use App\Entity\CustomerDnsEmail;
use App\Entity\CustomerOrder;
use App\Entity\CustomerOrderLine;
use App\Entity\OrderNumberCurrent;
use App\Form\Artemis\Intranet\CustomerDnsEmailType;
use App\Form\Artemis\Intranet\CustomerEditType;
use App\Form\Artemis\Intranet\CustomerNddType;
use App\Form\Artemis\Intranet\CustomerType;
@@ -21,16 +22,19 @@ use App\Repository\CustomerOrderRepository;
use App\Repository\CustomerRepository;
use App\Repository\OrderNumberCurrentRepository;
use App\Repository\OrderNumberDispoRepository;
use App\Security\PasswordGenerator;
use App\Service\Customer\Billing\CreateAvisEventSend;
use App\Service\Customer\Billing\CreateDevisCustomerEvent;
use App\Service\Customer\Billing\CreateDevisCustomerEventSend;
use App\Service\Customer\Billing\CreateFactureEventSend;
use App\Service\Customer\CreateAvisEvent;
use App\Service\Customer\CreateCustomerNddEmailEvent;
use App\Service\Customer\CreateFactureEvent;
use App\Service\Customer\DeleteCustomerEvent;
use App\Service\Customer\RestoreCustomerEvent;
use App\Service\Logger\LoggerService;
use App\Service\Ovh\Client;
use App\Service\Vault\VaultClient;
use AWS\CRT\Log;
use Doctrine\ORM\EntityManagerInterface;
use Exbil\MailCowAPI;
@@ -40,6 +44,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
use Symfony\Component\Uid\Uuid;
class CustomerController extends AbstractController
@@ -127,6 +132,7 @@ class CustomerController extends AbstractController
public function customerView(OrderNumberCurrentRepository $currentRepository,
OrderNumberDispoRepository $currentDispoRepository,
CustomerOrderRepository $customerOrderRepository,
VaultClient $vaultClient,
PaginatorInterface $paginator,
Client $client,
?Customer $customer,
@@ -363,6 +369,36 @@ class CustomerController extends AbstractController
return $this->redirectToRoute('artemis_intranet_customer_view',['id'=>$customer->getId(),'current'=>'nnd']);
}
$nddEmail = new CustomerDnsEmail();
$nddEmail->setIsBilling(true);
$nddEmail->setIsDeleted(false);
if($request->query->has('idNdd')) {
$nddEmail->setDns($entityManager->getRepository(CustomerDns::class)->find($request->get('idNdd')));
}
$formNddEmail = $this->createForm(CustomerDnsEmailType::class,$nddEmail);
$formNddEmail->handleRequest($request);
if($formNddEmail->isSubmitted() && $formNddEmail->isValid()) {
$password = new PasswordGenerator();
$nddEmail->setPassword($vaultClient->encrypt('mainframe_customer',$password->generate()));
$nddEmail->setCreateAt(new \DateTimeImmutable());
$nddEmail->setStorage("3221225472");
$entityManager->persist($nddEmail);
$mailcow = new MailCowAPI('mail.esy-web.dev',$_ENV['MAILCOW_KEY']);
$domain = $mailcow->domains()->getDomain($customerNdd->getNdd());
if(isset($domain->domain_name)){
$mailcow->mailBoxes()->addMailBox($nddEmail->getEmail(),$nddEmail->getDns()->getNdd(),"",$vaultClient->decrypt("mainframe_customer",$nddEmail->getPassword()));
} else {
}
$entityManager->flush();
$advertCustomerNewEmail = new CreateCustomerNddEmailEvent($nddEmail);
$eventDispatcher->dispatch($advertCustomerNewEmail);
}
$orderDevis = $entityManager->getRepository(CustomerDevis::class)->findBy(['customer'=>$customer],['id'=>'ASC']);
$orderAdvert = $entityManager->getRepository(CustomerAdvertPayment::class)->findBy(['customer'=>$customer],['id'=>'ASC']);
@@ -377,6 +413,7 @@ class CustomerController extends AbstractController
return $this->render('artemis/intranet/customer/edit.twig',[
'form' => $form->createView(),
'formNdd' => $formNdd->createView(),
'formNddEmail' => $formNddEmail->createView(),
'customer' => $customer,
'nddEmails' => $nddEmails,
'orderDevis' => $paginator->paginate($orderDevis,$request->get('page',1),20),

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Form\Artemis\Intranet;
use App\Entity\Customer;
use App\Entity\CustomerDnsEmail;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Choice;
class CustomerDnsEmailType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email',TextType::class,[
'label' => 'Nom de la boite mail',
'required' => true,
])
->add('isBilling',ChoiceType::class,[
'label' => 'Facturer la boite mail',
'required' => true,
'choices' => [
'Oui' => true,
'Non' => false,
]
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('data_class',CustomerDnsEmail::class);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Security;
class PasswordGenerator
{
private $length;
private $charsLower = 'abcdefghijklmnopqrstuvwxyz';
private $charsUpper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
private $digits = '0123456789';
private $specials = '@#_-'; // Caractères spéciaux limités
public function __construct($length = 12)
{
$this->length = $length;
}
public function generate()
{
$password = [];
$password[] = $this->charsLower[random_int(0, strlen($this->charsLower) - 1)];
$password[] = $this->charsUpper[random_int(0, strlen($this->charsUpper) - 1)];
$password[] = $this->digits[random_int(0, strlen($this->digits) - 1)];
$password[] = $this->specials[random_int(0, strlen($this->specials) - 1)];
$allChars = $this->charsLower . $this->charsUpper . $this->digits . $this->specials;
for ($i = 4; $i < $this->length; $i++) {
$password[] = $allChars[random_int(0, strlen($allChars) - 1)];
}
shuffle($password);
return implode('', $password);
}
}

View File

@@ -12,6 +12,7 @@ use App\Service\Pdf\DevisPdf;
use App\Service\Pdf\FacturePdf;
use App\Service\Pdf\PaymentPdf;
use App\Service\Stancer\Client;
use App\Service\Vault\VaultClient;
use Doctrine\ORM\EntityManagerInterface;
use Stancer\Customer;
use Stancer\Payment;
@@ -23,6 +24,7 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Uid\Uuid;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
#[AsEventListener(event: CreateCustomerNddEmailEvent::class, method: 'onCreateCustomerNddEmailEvent')]
#[AsEventListener(event: CreateDevisCustomerEvent::class, method: 'onBillingEvent')]
#[AsEventListener(event: CreateDevisCustomerEventSend::class, method: 'onBillingEventSend')]
#[AsEventListener(event: CreateAvisEvent::class, method: 'onCreatedAvisEvent')]
@@ -31,8 +33,29 @@ use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
class BillingEventSusbriber
{
public function __construct(private readonly UrlGeneratorInterface $urlGenerator,private readonly Client $client,private readonly UploaderHelper $uploaderHelper,private readonly Mailer $mailer,private readonly SignClient $signClient,private readonly EntityManagerInterface $entityManager,private KernelInterface $kernel)
public function __construct(
private readonly UrlGeneratorInterface $urlGenerator,
private readonly Client $client,
private readonly VaultClient $vaultClient,
private readonly UploaderHelper $uploaderHelper,
private readonly Mailer $mailer,
private readonly SignClient $signClient,
private readonly EntityManagerInterface $entityManager,
private readonly KernelInterface $kernel
){
}
public function onCreateCustomerNddEmailEvent(CreateCustomerNddEmailEvent $event): void
{
$ndd = $event->getCustomerDnsEmail()->getDns();
$email = $event->getCustomerDnsEmail();
$password = $this->vaultClient->decrypt('mainframe_customer',$email->getPassword());
$this->mailer->send($ndd->getCustomer()->mainContact()->getEmail(),$ndd->getCustomer()->getRaisonSocial(),"[SARL SITECONSEIL] - Nouvelle boite mail","mails/customer/new_mailbox.twig",[
'ndd' => $ndd,
'email' => $email,
'password' => $password,
]);
}
public function onCreateFactureEvent(CreateFactureEvent $event)

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Service\Customer;
use App\Entity\CustomerDnsEmail;
class CreateCustomerNddEmailEvent
{
private CustomerDnsEmail $customerDnsEmail;
public function __construct(CustomerDnsEmail $customerDnsEmail)
{
$this->customerDnsEmail = $customerDnsEmail;
}
/**
* @return CustomerDnsEmail
*/
public function getCustomerDnsEmail(): CustomerDnsEmail
{
return $this->customerDnsEmail;
}
}

View File

@@ -43,5 +43,15 @@
</table>
</div>
<div class="mt-5 bg-gray-800 rounded-lg shadow-lg p-6 space-y-4">
{{ form_start(formNddEmail) }}
<div class="flex space-x-4 mb-4">
<div class="flex-1">
{{ form_row(formNddEmail.email) }}
</div>
<div class="flex-1">
{{ form_row(formNddEmail.isBilling) }}
</div>
</div>
<button type="submit" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-semibold px-4 py-2 rounded">Enregistrer</button>
{{ form_end(formNddEmail) }}
</div>

View File

@@ -0,0 +1,25 @@
{% extends 'mails/base.twig' %}
{% block content %}
<mj-text>
Bonjour,
</mj-text>
<mj-text>
Nous vous informons qu'une nouvelle boîte mail <strong>{{ datas.email.email }}@{{ datas.ndd.ndd }}</strong> a été créée.
</mj-text>
<mj-text>
Voici son mot de passe : <strong>{{ datas.password }}</strong>
</mj-text>
<mj-text>
Configuration pour votre messagerie serveur sécurisée :<br/>
Serveur : <strong>mail.esy-web.dev</strong><br/>
Protocole POP3 sécurisé (SSL) : Port <strong>995</strong><br/>
Protocole IMAP sécurisé (SSL) : Port <strong>993</strong><br/>
Protocole SMTP sécurisé : Ports <strong>465 (SSL)</strong> et <strong>587 (STARTTLS)</strong><br/>
</mj-text>
<mj-text>
Vous pouvez accéder à votre webmail ici : <a href="https://mail.esy-web.dev/" target="_blank">https://mail.esy-web.dev/</a>
</mj-text>
<mj-text>
Cordialement
</mj-text>
{% endblock %}