Browse Source

post review fixes, and other fixes

Olivier Massot 1 year ago
parent
commit
d3aca6f46e

+ 1 - 0
config/packages/monolog.yaml

@@ -2,6 +2,7 @@ monolog:
     channels:
         - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
         - cron
+        - admin
 
     handlers:
         # sorties standards (stdout, stderr, console)

+ 3 - 3
doc/internal_requests.md

@@ -17,8 +17,8 @@ Pour éviter tout risque de sécurité lié à ces routes :
 
 Ainsi, si l'on prend l'exemple d'une requête `/internal/download/123` sur ap2i :
 
-* Un utilisateur dans le VPN qui ferait un curl à cette adresse recevra une erreur 500 à cause du token manquant
-* Un utilisateur hors VPN, même s'il connaissait le token, recevra une erreur 500, car n'ayant pas une ip autorisée
+* Un utilisateur dans le VPN sans le token qui ferait un curl à cette adresse recevra une erreur 403
+* Un utilisateur hors VPN, même s'il connaissait le token, recevra une erreur 403, car n'ayant pas une ip autorisée
 * Une requête issue de la V1 avec le bon token et provenant d'une ip interne sera autorisée sans authentification
 
 ### Ip internes 
@@ -64,8 +64,8 @@ Côté ap2i, les requêtes suivantes doivent donner les résultats correspondant
 | /api/internal/download/$id | OUI           | NON         | NON        | 401 Unauthorized |
 | /api/internal/download/$id | OUI           | NON         | OUI        | 200 OK           |
 | /api/internal/download/$id | OUI           | OUI         | OUI        | 200 OK           |
+| /api/internal/download/$id | NON           | OUI         | OUI        | 200 OK           |
 | /api/internal/download/$id | OUI           | OUI         | NON        | 403 Forbidden    |
-| /api/internal/download/$id | NON           | OUI         | OUI        | 403 Forbidden    |
 | /api/download/$id          | *             | NON         | *          | 401 Unauthorized |
 | /api/download/$id          | *             | OUI         | *          | 200 OK           |
 

+ 3 - 4
src/ApiResources/Organization/OrganizationCreationRequest.php

@@ -37,7 +37,7 @@ class OrganizationCreationRequest
      * @var string|null
      */
     #[Assert\Email(message: 'The email {{ value }} is not a valid email.')]
-    private ?string $sendConfirmationEmailAt;
+    private ?string $sendConfirmationEmailAt = null;
 
     private string $name;
 
@@ -75,9 +75,8 @@ class OrganizationCreationRequest
     )]
     private string $phoneNumber;
 
-    #[Assert\Length(
-        min: 5,
-        minMessage: 'Email must be at least {{ limit }} characters long',
+    #[Assert\Email(
+        message: 'The email {{ value }} is not a valid email.',
     )]
     private string $email;
 

+ 2 - 3
src/ApiResources/Organization/OrganizationMemberCreationRequest.php

@@ -61,9 +61,8 @@ class OrganizationMemberCreationRequest
     )]
     private ?string $mobile = null;
 
-    #[Assert\Length(
-        min: 5,
-        minMessage: 'Email must be at least {{ limit }} characters long',
+    #[Assert\Email(
+        message: 'The email {{ value }} is not a valid email.',
     )]
     private string $email;
 

+ 2 - 7
src/Entity/Organization/Organization.php

@@ -77,8 +77,8 @@ class Organization
     #[ORM\Column(length: 50, nullable: true, enumType: LegalEnum::class)]
     private ?LegalEnum $legalStatus = null;
 
-    #[ORM\Column(length: 255, nullable: true, enumType: PrincipalTypeEnum::class)]
-    private ?PrincipalTypeEnum $principalType = null;
+    #[ORM\Column(length: 255, nullable: false, enumType: PrincipalTypeEnum::class)]
+    private PrincipalTypeEnum $principalType;
 
     #[ORM\OneToOne(mappedBy: 'organization', cascade: ['persist', 'remove'])]
     private Settings $settings;
@@ -500,11 +500,6 @@ class Organization
 
     public function setParameters(Parameters $parameters): self
     {
-        // set the owning side of the relation if necessary
-        if ($parameters->getOrganization() !== $this) {
-            $parameters->setOrganization($this);
-        }
-
         $this->parameters = $parameters;
 
         return $this;

+ 7 - 2
src/Entity/Organization/Parameters.php

@@ -153,10 +153,10 @@ class Parameters
     private ?TimeZoneEnum $timezone = null;
 
     #[ORM\Column(length: 255, nullable: false, enumType: PeriodicityEnum::class, options: ['default' => PeriodicityEnum::ANNUAL])]
-    private ?PeriodicityEnum $educationPeriodicity = null;
+    private PeriodicityEnum $educationPeriodicity = PeriodicityEnum::ANNUAL;
 
     #[ORM\Column(length: 255, nullable: true, enumType: AdvancedEducationNotationTypeEnum::class, options: ['default' => AdvancedEducationNotationTypeEnum::BY_EDUCATION])]
-    private ?AdvancedEducationNotationTypeEnum $advancedEducationNotationType = null;
+    private AdvancedEducationNotationTypeEnum $advancedEducationNotationType = AdvancedEducationNotationTypeEnum::BY_EDUCATION;
 
     #[ORM\Column(options: ['default' => false])]
     private bool $sendAttendanceEmail = false;
@@ -225,6 +225,11 @@ class Parameters
 
     public function setOrganization(Organization $organization): self
     {
+        // set the owning side of the relation if necessary
+        if ($organization->getParameters() !== $this) {
+            $organization->setParameters($this);
+        }
+
         $this->organization = $organization;
         return $this;
     }

+ 16 - 1
src/Entity/Person/Person.php

@@ -39,7 +39,7 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\Column(length: 180, unique: true, nullable: true)]
     private ?string $username = null;
 
-    /** @var string[]|null */
+    #[ORM\Column(type: "array", nullable: true)]
     private ?array $roles = [];
 
     #[ORM\Column(nullable: true)]
@@ -103,6 +103,10 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\OneToMany(mappedBy: 'personOwner', targetEntity: DocumentWish::class, cascade: ['persist'], orphanRemoval: true)]
     private Collection $documentWishes;
 
+    /** @var array<string, string> */
+    #[ORM\Column(type: "json", nullable: true)]
+    private array $confidentiality = [];
+
     #[Pure]
     public function __construct()
     {
@@ -588,4 +592,15 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
 
         return $this;
     }
+
+    public function getConfidentiality(): array
+    {
+        return $this->confidentiality;
+    }
+
+    public function setConfidentiality(array $confidentiality): self
+    {
+        $this->confidentiality = $confidentiality;
+        return $this;
+    }
 }

+ 17 - 20
src/Message/Handler/OrganizationCreationHandler.php

@@ -22,32 +22,29 @@ class OrganizationCreationHandler
     public function __invoke(OrganizationCreationCommand $organizationCreationCommand): void
     {
         $organizationCreationRequest = $organizationCreationCommand->getOrganizationCreationRequest();
-        $error = null;
 
         try {
             $organization = $this->organizationFactory->create($organizationCreationRequest);
-        } catch (\Exception $e) {
-            $error = $e->getMessage();
-        }
 
-        if ($organizationCreationRequest->getSendConfirmationEmailAt() !== null) {
+            $subject = 'New organization created';
+            $message = 'The organization "' . $organization->getName() . '" has been created successfully.';
 
-            if ($error !== null) {
-                $subject = 'Organization creation : an error occured';
-                $message = 'An error occured while creating the new organization : \n' . $error;
-            } else {
-                $subject = 'New organization created';
-                $message = 'The organization "' . $organization->getName() . '" has been created successfully.';
+        } catch (\Exception $e) {
+            $subject = 'Organization creation : an error occured';
+            $message = 'An error occured while creating the new organization : \n' . $e->getMessage();
+            throw $e;
+
+        } finally {
+            if ($organizationCreationRequest->getSendConfirmationEmailAt() !== null) {
+                $symfonyMail = (new SymfonyEmail())
+                    ->from('mail.report@opentalent.fr')
+                    ->replyTo('mail.report@opentalent.fr')
+                    ->returnPath(Address::create('mail.report@opentalent.fr'))
+                    ->to($organizationCreationRequest->getSendConfirmationEmailAt())
+                    ->subject($subject)
+                    ->text($message);
+                $this->symfonyMailer->send($symfonyMail);
             }
-
-            $symfonyMail = (new SymfonyEmail())
-                ->from('mail.report@opentalent.fr')
-                ->replyTo('mail.report@opentalent.fr')
-                ->returnPath(Address::create('mail.report@opentalent.fr'))
-                ->to($organizationCreationRequest->getSendConfirmationEmailAt())
-                ->subject($subject)
-                ->text($message);
-            $this->symfonyMailer->send($symfonyMail);
         }
     }
 }

+ 31 - 22
src/Service/Organization/OrganizationFactory.php

@@ -13,6 +13,7 @@ use App\Entity\Organization\Organization;
 use App\Entity\Organization\OrganizationAddressPostal;
 use App\Entity\Organization\Parameters;
 use App\Entity\Organization\Settings;
+use App\Entity\Organization\Subdomain;
 use App\Entity\Person\Person;
 use App\Entity\Person\PersonAddressPostal;
 use App\Enum\Core\ContactPointTypeEnum;
@@ -24,6 +25,7 @@ use App\Repository\Network\NetworkRepository;
 use App\Repository\Organization\OrganizationRepository;
 use App\Repository\Person\PersonRepository;
 use App\Service\Dolibarr\DolibarrApiService;
+use App\Service\Typo3\BindFileService;
 use App\Service\Typo3\SubdomainService;
 use App\Service\Typo3\Typo3Service;
 use App\Service\Utils\DatesUtils;
@@ -49,7 +51,8 @@ class OrganizationFactory
         private readonly Typo3Service           $typo3Service,
         private readonly DolibarrApiService     $dolibarrApiService,
         private readonly EntityManagerInterface $entityManager,
-        private readonly PersonRepository       $personRepository
+        private readonly PersonRepository       $personRepository,
+        private readonly BindFileService        $bindFileService,
     ) {}
 
     #[Required]
@@ -77,7 +80,7 @@ class OrganizationFactory
 
         try {
             if ($this->isExistingOrganization($organizationCreationRequest)) {
-                throw new \RuntimeException('An organization named ' . $organizationCreationRequest->getName() . ' already exists at this address.');
+                throw new \RuntimeException('An organization named ' . $organizationCreationRequest->getName() . ' already exists.');
             }
 
             $this->validateSubdomain($organizationCreationRequest->getSubdomain());
@@ -139,6 +142,23 @@ class OrganizationFactory
                 $this->logger->debug(" - Director access created");
             }
 
+            $subdomain = new Subdomain();
+            $subdomain->setSubdomain($organizationCreationRequest->getSubdomain());
+            $subdomain->setOrganization($organization);
+            $subdomain->setActive(true);
+            $this->entityManager->persist($subdomain);
+
+            // <--- Pour la rétrocompatibilité avec la v1 ; pourra être supprimé lorsque la migration sera achevée
+            $parameters = $organization->getParameters();
+            $parameters->setSubDomain($organizationCreationRequest->getSubdomain());
+            $parameters->setOtherWebsite('https://' . $organizationCreationRequest->getSubdomain() . '.opentalent.fr');
+            $this->entityManager->persist($parameters);
+            // --->
+
+            // Création de la société Dolibarr
+            $dolibarrId = $this->dolibarrApiService->createSociety($organization);
+            $this->logger->info("New dolibarr structure created (uid : " . $dolibarrId . ")");
+
             $this->entityManager->persist($organization);
             $this->entityManager->flush();
             $this->entityManager->commit();
@@ -152,14 +172,6 @@ class OrganizationFactory
             throw $e;
         }
 
-        // Création et enregistrement du sous-domaine
-        $this->subdomainService->addNewSubdomain(
-            $organization,
-            $organizationCreationRequest->getSubdomain(),
-            true
-        );
-        $this->logger->info("Subdomain created and activated");
-
         // Création du site typo3
         if ($organizationCreationRequest->getCreateWebsite()) {
             $response = $this->typo3Service->createSite($organization->getId());
@@ -174,32 +186,28 @@ class OrganizationFactory
             $this->logger->warning("Typo3 website creation was not required");
         }
 
-        // Création de la société Dolibarr
-        $dolibarrId = $this->dolibarrApiService->createSociety($organization);
-        $this->logger->info("New dolibarr structure created (uid : " . $dolibarrId . ")");
+        // Register the subdomain into the BindFile (takes up to 5min to take effect)
+        $this->bindFileService->registerSubdomain($subdomain->getSubdomain());
+        $this->logger->info("Subdomain registered");
 
         return $organization;
     }
 
     /**
-     * Une organisation du même nom existe-t-elle déjà à la même adresse?
+     * Une organisation du même nom existe-t-elle déjà à la même adresse ?
      *
      * @param OrganizationCreationRequest $organizationCreationRequest
      * @return bool
      */
     protected function isExistingOrganization(OrganizationCreationRequest $organizationCreationRequest): bool
     {
-        $results = $this
-            -> organizationRepository
-            ->findBy(
+        return $this
+            ->organizationRepository
+            ->count(
                 [
                     'name' => $organizationCreationRequest->getName(),
-                    'streetAddress' => $organizationCreationRequest->getStreetAddress1(),
-                    'postalCode' => $organizationCreationRequest->getPostalCode()
                 ]
-            );
-
-        return count($results) > 0;
+            ) > 0;
     }
 
     /**
@@ -236,6 +244,7 @@ class OrganizationFactory
         $organization = new Organization();
         $organization->setName($organizationCreationRequest->getName());
         $organization->setLegalStatus($organizationCreationRequest->getLegalStatus());
+        $organization->setPrincipalType($organizationCreationRequest->getPrincipalType());
 
         $this->entityManager->persist($organization);
 

+ 11 - 11
src/Service/Typo3/SubdomainService.php

@@ -117,20 +117,13 @@ class SubdomainService
             throw new \RuntimeException('This subdomain is already registered');
         }
 
-        $subdomain = new Subdomain();
-        $subdomain->setSubdomain($subdomainValue);
-        $subdomain->setOrganization($organization);
-        $subdomain->setActive(false);
-
         $this->em->beginTransaction();
 
         try {
-            // <--- Pour la rétrocompatibilité avec la v1; pourra être supprimé lorsque la migration sera achevée
-            $parameters = $organization->getParameters();
-            $parameters->setSubDomain($subdomainValue);
-            $parameters->setOtherWebsite('https://'.$subdomainValue.'.opentalent.fr');
-            $this->em->persist($parameters);
-            // --->
+            $subdomain = new Subdomain();
+            $subdomain->setSubdomain($subdomainValue);
+            $subdomain->setOrganization($organization);
+            $subdomain->setActive(false);
 
             $this->em->persist($subdomain);
             $this->em->flush();
@@ -191,6 +184,13 @@ class SubdomainService
         }
         $subdomain->setActive(true);
 
+        // <--- Pour la rétrocompatibilité avec la v1; pourra être supprimé lorsque la migration sera achevée
+        $parameters = $subdomain->getOrganization()->getParameters();
+        $parameters->setSubDomain($subdomain->getSubdomain());
+        $parameters->setOtherWebsite('https://'.$subdomain->getSubdomain().'.opentalent.fr');
+        $this->em->persist($parameters);
+        // --->
+
         // TODO: comprendre pourquoi ce refresh est indispensable pour que l'organisation soit à jour
         $this->em->flush();
         $this->em->refresh($subdomain->getOrganization());