Просмотр исходного кода

Début envoie automatisé de la newsletter + correctif pour KC26+

garthh 1 неделя назад
Родитель
Сommit
5b19632ccb

+ 10 - 0
.env

@@ -56,6 +56,9 @@ APP_PHONE_REGION="FR"
 CONTACT_EMAIL="no-reply@mail.com"
 CONTACT_NAME="Orgasso"
 
+# Liste de diffusion pour les annonces
+ML_EMAIL="liste@mail.com"
+
 # Les visiteurs peuvent créer un compte
 APP_ALLOW_REGISTER="true"
 
@@ -68,10 +71,17 @@ APP_PLANNING_HEIGHT_MULTIPLIER="1"
 
 # Paramétrage OpenID Keycloak
 KEYCLOAK_ENABLED="false"
+KEYCLOAK_DEBUG=1
 KEYCLOAK_BASE_URL=""
 KEYCLOAK_REALM=""
 KEYCLOAK_CLIENT_ID=""
 KEYCLOAK_CLIENT_SECRET=""
+KEYCLOAK_USER_ATTRIBUTE_NICKNAME=""
+KEYCLOAK_USER_ATTRIBUTE_EMAIL=""
+KEYCLOAK_USER_ATTRIBUTE_FIRSTNAME=""
+KEYCLOAK_USER_ATTRIBUTE_LASTNAME=""
+KEYCLOAK_USER_ATTRIBUTE_PHONE=""
+KEYCLOAK_USER_ATTRIBUTE_GROUPS=""
 KEYCLOAK_STAFF_GROUP=""
 KEYCLOAK_GAMEMASTER_GROUP=""
 KEYCLOAK_MANAGER_GROUP=""

+ 7 - 1
src/Controller/ParticipationController.php

@@ -19,13 +19,14 @@ use App\Entity\Party;
 use App\Entity\Event;
 use App\Entity\Participation;
 use App\Repository\SlotRepository;
+use App\Repository\ParticipationRepository;
 use App\Form\ParticipationType;
 
 final class ParticipationController extends AbstractController
 {
 
     #[Route('/cancel/{id}', name: 'app_participation_cancel', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
-    public function cancel(?Participation $participation, Request $request, EntityManagerInterface $manager): Response
+    public function cancel(?Participation $participation, Request $request, EntityManagerInterface $manager, ParticipationRepository $repository): Response
     {
         if (!$participation) {
             // TGCM, ça ressemble à un UUID, mais y'a rien derrière
@@ -41,6 +42,11 @@ final class ParticipationController extends AbstractController
         }
 
         // TODO: prendre en charge l'annulation en une fois de réservations de groupe
+        // Détecter si d'autres réservations avec la même adresse mail existent -> présnter dans un tableau annexe
+        $otherParticipations = $repository->findAllByEmail($participation->getParticipantEmail());
+        if (count($otherParticipations)>1) {
+            // Plusieurs participations avec la même adresse sur cette partie...  OUI, MAIS C'EST PAS LE BON REPO !!!! IL FAUT BRIDER AUX PARTIES !!!!
+        }
 
         $form = $this->createFormBuilder(FormType::class)->getForm();
         $form->handleRequest($request);

+ 142 - 0
src/Entity/Announcement.php

@@ -0,0 +1,142 @@
+<?php
+
+namespace App\Entity;
+
+use App\Repository\AnnouncementRepository;
+use Doctrine\DBAL\Types\Types;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ORM\Entity(repositoryClass: AnnouncementRepository::class)]
+class Announcement
+{
+    #[ORM\Id]
+    #[ORM\GeneratedValue]
+    #[ORM\Column]
+    private ?int $id = null;
+
+    #[ORM\Column]
+    private ?int $year = null;
+
+    #[ORM\Column]
+    private ?int $month = null;
+
+    #[ORM\ManyToOne(inversedBy: 'announcements')]
+    #[ORM\JoinColumn(nullable: false)]
+    private ?User $editedBy = null;
+
+    #[ORM\Column]
+    private ?\DateTime $editedDate = null;
+
+    #[ORM\Column(type: Types::TEXT)]
+    private ?string $announcement = null;
+
+    #[ORM\Column]
+    private ?bool $showEventDetail = null;
+
+    #[ORM\Column]
+    private ?bool $showAuthors = null;
+
+    #[ORM\Column]
+    private ?bool $sent = null;
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getYear(): ?int
+    {
+        return $this->year;
+    }
+
+    public function setYear(int $year): static
+    {
+        $this->year = $year;
+
+        return $this;
+    }
+
+    public function getMonth(): ?int
+    {
+        return $this->month;
+    }
+
+    public function setMonth(int $month): static
+    {
+        $this->month = $month;
+
+        return $this;
+    }
+
+    public function getEditedBy(): ?User
+    {
+        return $this->editedBy;
+    }
+
+    public function setEditedBy(?User $editedBy): static
+    {
+        $this->editedBy = $editedBy;
+
+        return $this;
+    }
+
+    public function getEditedDate(): ?\DateTime
+    {
+        return $this->editedDate;
+    }
+
+    public function setEditedDate(\DateTime $editedDate): static
+    {
+        $this->editedDate = $editedDate;
+
+        return $this;
+    }
+
+    public function getAnnouncement(): ?string
+    {
+        return $this->announcement;
+    }
+
+    public function setAnnouncement(string $announcement): static
+    {
+        $this->announcement = $announcement;
+
+        return $this;
+    }
+
+    public function isShowEventDetail(): ?bool
+    {
+        return $this->showEventDetail;
+    }
+
+    public function setShowEventDetail(bool $showEventDetail): static
+    {
+        $this->showEventDetail = $showEventDetail;
+
+        return $this;
+    }
+
+    public function isShowAuthors(): ?bool
+    {
+        return $this->showAuthors;
+    }
+
+    public function setShowAuthors(bool $showAuthors): static
+    {
+        $this->showAuthors = $showAuthors;
+
+        return $this;
+    }
+
+    public function isSent(): ?bool
+    {
+        return $this->sent;
+    }
+
+    public function setSent(bool $sent): static
+    {
+        $this->sent = $sent;
+
+        return $this;
+    }
+}

+ 37 - 0
src/Entity/User.php

@@ -85,12 +85,19 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\OneToMany(targetEntity: PartyRequest::class, mappedBy: 'requester', orphanRemoval: true)]
     private Collection $partyRequests;
 
+    /**
+     * @var Collection<int, Announcement>
+     */
+    #[ORM\OneToMany(targetEntity: Announcement::class, mappedBy: 'editedBy')]
+    private Collection $announcements;
+
     public function __construct()
     {
         $this->lastUpdate = new \DateTime('now');
         $this->games = new ArrayCollection();
         $this->submittedParties = new ArrayCollection();
         $this->partyRequests = new ArrayCollection();
+        $this->announcements = new ArrayCollection();
     }
 
     public function getId(): ?Uuid
@@ -414,4 +421,34 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
 
         return $this;
     }
+
+    /**
+     * @return Collection<int, Announcement>
+     */
+    public function getAnnouncements(): Collection
+    {
+        return $this->announcements;
+    }
+
+    public function addAnnouncement(Announcement $announcement): static
+    {
+        if (!$this->announcements->contains($announcement)) {
+            $this->announcements->add($announcement);
+            $announcement->setEditedBy($this);
+        }
+
+        return $this;
+    }
+
+    public function removeAnnouncement(Announcement $announcement): static
+    {
+        if ($this->announcements->removeElement($announcement)) {
+            // set the owning side to null (unless already changed)
+            if ($announcement->getEditedBy() === $this) {
+                $announcement->setEditedBy(null);
+            }
+        }
+
+        return $this;
+    }
 }

+ 43 - 0
src/Repository/AnnouncementRepository.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace App\Repository;
+
+use App\Entity\Announcement;
+use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\Persistence\ManagerRegistry;
+
+/**
+ * @extends ServiceEntityRepository<Announcement>
+ */
+class AnnouncementRepository extends ServiceEntityRepository
+{
+    public function __construct(ManagerRegistry $registry)
+    {
+        parent::__construct($registry, Announcement::class);
+    }
+
+    //    /**
+    //     * @return Announcement[] Returns an array of Announcement objects
+    //     */
+    //    public function findByExampleField($value): array
+    //    {
+    //        return $this->createQueryBuilder('a')
+    //            ->andWhere('a.exampleField = :val')
+    //            ->setParameter('val', $value)
+    //            ->orderBy('a.id', 'ASC')
+    //            ->setMaxResults(10)
+    //            ->getQuery()
+    //            ->getResult()
+    //        ;
+    //    }
+
+    //    public function findOneBySomeField($value): ?Announcement
+    //    {
+    //        return $this->createQueryBuilder('a')
+    //            ->andWhere('a.exampleField = :val')
+    //            ->setParameter('val', $value)
+    //            ->getQuery()
+    //            ->getOneOrNullResult()
+    //        ;
+    //    }
+}

+ 14 - 11
src/Security/KeycloakAuthenticator.php

@@ -40,7 +40,10 @@ class KeycloakAuthenticator extends AbstractAuthenticator
         $accessToken = $client->getAccessToken();
         $keycloakUser = $client->fetchUserFromToken($accessToken);
         $data = $keycloakUser->toArray();
-        $email = $data['email'] ?? null;
+        if ($_ENV['KEYCLOAK_DEBUG'] == 1) {
+            dump($data);
+        }
+        $email = $data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_EMAIL']] ?? null;
 
         return new SelfValidatingPassport(
             new UserBadge($email, function($email) use ($data) {
@@ -49,9 +52,9 @@ class KeycloakAuthenticator extends AbstractAuthenticator
                 if (!$user) {
                     $user = new User();
                     $user->setEmail($email);
-                    $user->setFirstName($data['given_name'] ?? '');
-                    $user->setLastName($data['family_name'] ?? '');
-                    $user->setPhone($data['phone_number'] ?? '');
+                    $user->setFirstName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_FIRSTNAME']] ?? '');
+                    $user->setLastName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_LASTNAME']] ?? '');
+                    $user->setPhone($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_PHONE']] ?? '');
                     $user->setRoles(['ROLE_USER']);
                     $user->setIsVerified(true);
                     $user->setPassword(
@@ -62,9 +65,9 @@ class KeycloakAuthenticator extends AbstractAuthenticator
                     // Il vient de KC, donc, l'email est fiabilisé
                     $user->setIsVerified(true);
                     // Mise à jour du numéro de téléphone s'il est renseigné dans KC
-                    $user->setPhone($data['phone_number'] ?? $user->getPhone());
-                    $user->setFirstName($data['given_name'] ?? $user->getFirstName());
-                    $user->setLastName($data['family_name'] ?? $user->getLastName());
+                    $user->setPhone($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_PHONE']] ?? $user->getPhone());
+                    $user->setFirstName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_FIRSTNAME']] ?? $user->getFirstName());
+                    $user->setLastName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_LASTNAME']] ?? $user->getLastName());
                 }
                 
                 // Mise à jour des rôle et du profil GM
@@ -82,9 +85,9 @@ class KeycloakAuthenticator extends AbstractAuthenticator
                         $gamemaster = new Gamemaster();
                         $gamemaster->setFirstName($user->getFirstName());
                         $gamemaster->setLastName($user->getLastName());
-                        $gamemaster->setPreferedName($data['nickname']);
+                        $gamemaster->setPreferedName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_NICKNAME']]);
                         $slugger = new AsciiSlugger('fr_FR');
-                        $slug = $slugger->slug(strtolower($data['nickname']));
+                        $slug = $slugger->slug(strtolower($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_NICKNAME']]));
                         $gamemaster->setSlug($slug);
                         $gamemaster->setEmail($user->getEmail());
                         $phone = $user->getPhone();
@@ -96,9 +99,9 @@ class KeycloakAuthenticator extends AbstractAuthenticator
                         $gamemaster = $user->getLinkToGamemaster();
                         $gamemaster->setFirstName($user->getFirstName());
                         $gamemaster->setLastName($user->getLastName());
-                        $gamemaster->setPreferedName($data['nickname']);
+                        $gamemaster->setPreferedName($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_NICKNAME']]);
                         $slugger = new AsciiSlugger('fr_FR');
-                        $slug = $slugger->slug(strtolower($data['nickname']));
+                        $slug = $slugger->slug(strtolower($data[$_ENV['KEYCLOAK_USER_ATTRIBUTE_NICKNAME']]));
                         $gamemaster->setSlug($slug);
                         $gamemaster->setEmail($user->getEmail());
                         $phone = $user->getPhone();