瀏覽代碼

Merge branch 'V8-6489_enable_admin_login' into feature/V8-6489-dvelopper-loutil-de-cration-des-

Olivier Massot 1 年之前
父節點
當前提交
04c860e130

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

@@ -2,6 +2,7 @@
 
 
 namespace App\ApiResources\Organization;
 namespace App\ApiResources\Organization;
 
 
+use App\Enum\Core\FileTypeEnum;
 use App\Enum\Person\GenderEnum;
 use App\Enum\Person\GenderEnum;
 use Symfony\Component\Validator\Constraints as Assert;
 use Symfony\Component\Validator\Constraints as Assert;
 
 
@@ -10,7 +11,8 @@ use Symfony\Component\Validator\Constraints as Assert;
  */
  */
 class OrganizationMemberCreationRequest
 class OrganizationMemberCreationRequest
 {
 {
-    private GenderEnum $gender;
+    #[Assert\Type(type: FileTypeEnum::class)]
+    private GenderEnum $gender = GenderEnum::MISTER;
 
 
     #[Assert\Regex(pattern: '/^[a-z0-9\-]{3,}$/')]
     #[Assert\Regex(pattern: '/^[a-z0-9\-]{3,}$/')]
     private string $username;
     private string $username;

+ 14 - 0
src/Entity/Access/Access.php

@@ -112,6 +112,9 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
     private ?array $roles = [];
     private ?array $roles = [];
 
 
+    #[ORM\Column(options: ['default' => false])]
+    private bool $loginEnabled = false;
+
     /** @var mixed[]|null */
     /** @var mixed[]|null */
     #[Groups(['my_access:input'])]
     #[Groups(['my_access:input'])]
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
     #[ORM\Column(type: 'json', length: 4294967295, nullable: true)]
@@ -493,6 +496,17 @@ class Access implements UserInterface, PasswordAuthenticatedUserInterface
         return array_unique($roles ?? []);
         return array_unique($roles ?? []);
     }
     }
 
 
+    public function isLoginEnabled(): bool
+    {
+        return $this->loginEnabled;
+    }
+
+    public function setLoginEnabled(bool $loginEnabled): self
+    {
+        $this->loginEnabled = $loginEnabled;
+        return $this;
+    }
+
     public function getPersonActivity(): Collection
     public function getPersonActivity(): Collection
     {
     {
         return $this->personActivity;
         return $this->personActivity;

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

@@ -42,6 +42,9 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\Column(length: 180, unique: true, nullable: true)]
     #[ORM\Column(length: 180, unique: true, nullable: true)]
     private ?string $username = null;
     private ?string $username = null;
 
 
+    #[ORM\Column(options: ['default' => false])]
+    private bool $enabled = false;
+
     /**
     /**
      * @var array<mixed>|null
      * @var array<mixed>|null
      */
      */
@@ -59,7 +62,7 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     #[Groups(['access_people_ref', 'access_address'])]
     #[Groups(['access_people_ref', 'access_address'])]
     private ?string $givenName = null;
     private ?string $givenName = null;
 
 
-    #[ORM\ManyToMany(targetEntity: ContactPoint::class, mappedBy: 'person')]
+    #[ORM\ManyToMany(targetEntity: ContactPoint::class, mappedBy: 'person', cascade: ['persist'], orphanRemoval: true)]
     private Collection $contactPoints;
     private Collection $contactPoints;
 
 
     #[ORM\ManyToMany(targetEntity: BankAccount::class, inversedBy: 'person', cascade: ['persist'], orphanRemoval: true)]
     #[ORM\ManyToMany(targetEntity: BankAccount::class, inversedBy: 'person', cascade: ['persist'], orphanRemoval: true)]
@@ -67,7 +70,7 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\InverseJoinColumn(name: 'bankAccount_id', referencedColumnName: 'id')]
     #[ORM\InverseJoinColumn(name: 'bankAccount_id', referencedColumnName: 'id')]
     private Collection $bankAccount;
     private Collection $bankAccount;
 
 
-    #[ORM\OneToMany(mappedBy: 'person', targetEntity: PersonAddressPostal::class, orphanRemoval: true)]
+    #[ORM\OneToMany(mappedBy: 'person', targetEntity: PersonAddressPostal::class, cascade: ['persist'], orphanRemoval: true)]
     #[Groups('access_address')]
     #[Groups('access_address')]
     private Collection $personAddressPostal;
     private Collection $personAddressPostal;
 
 
@@ -151,6 +154,17 @@ class Person implements UserInterface, PasswordAuthenticatedUserInterface
         return $this;
         return $this;
     }
     }
 
 
+    public function isEnabled(): bool
+    {
+        return $this->enabled;
+    }
+
+    public function setEnabled(bool $enabled): self
+    {
+        $this->enabled = $enabled;
+        return $this;
+    }
+
     /**
     /**
      * @return string[]
      * @return string[]
      */
      */

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

@@ -521,13 +521,20 @@ class OrganizationFactory
         $admin->setUsername('admin'.strtolower($organizationCreationRequest->getSubdomain()));
         $admin->setUsername('admin'.strtolower($organizationCreationRequest->getSubdomain()));
         $randomString = ByteString::fromRandom(32)->toString();
         $randomString = ByteString::fromRandom(32)->toString();
         $admin->setPassword($randomString);
         $admin->setPassword($randomString);
+        $admin->setEnabled(true);
 
 
         $adminAccess = new Access();
         $adminAccess = new Access();
         $adminAccess->setAdminAccess(true);
         $adminAccess->setAdminAccess(true);
         $adminAccess->setPerson($admin);
         $adminAccess->setPerson($admin);
+        $adminAccess->setLoginEnabled(true);
         $adminAccess->setCreateDate($organizationCreationRequest->getCreationDate());
         $adminAccess->setCreateDate($organizationCreationRequest->getCreationDate());
         $adminAccess->setCreatedBy($organizationCreationRequest->getAuthorId());
         $adminAccess->setCreatedBy($organizationCreationRequest->getAuthorId());
 
 
+        $contactPoint = new ContactPoint();
+        $contactPoint->setContactType(ContactPointTypeEnum::PRINCIPAL);
+        $contactPoint->setEmail($organizationCreationRequest->getEmail());
+        $admin->addContactPoint($contactPoint);
+
         return $adminAccess;
         return $adminAccess;
     }
     }
 
 
@@ -580,6 +587,10 @@ class OrganizationFactory
         } else {
         } else {
             $person = new Person();
             $person = new Person();
 
 
+            if ($this->personRepository->findOneBy(['username' => $creationRequestData->getUsername()])) {
+                throw new \RuntimeException('Username already in use : ' . $creationRequestData->getUsername());
+            }
+
             $person->setUsername($creationRequestData->getUsername());
             $person->setUsername($creationRequestData->getUsername());
             $person->setPassword(ByteString::fromRandom(32)->toString());
             $person->setPassword(ByteString::fromRandom(32)->toString());
             $person->setGender($creationRequestData->getGender());
             $person->setGender($creationRequestData->getGender());
@@ -649,8 +660,16 @@ class OrganizationFactory
      */
      */
     protected function makePersonContactPoint(OrganizationMemberCreationRequest $organizationMemberCreationRequest): ContactPoint
     protected function makePersonContactPoint(OrganizationMemberCreationRequest $organizationMemberCreationRequest): ContactPoint
     {
     {
-        $phoneUtil = PhoneNumberUtil::getInstance();
-        $phoneNumber = $phoneUtil->parse($organizationMemberCreationRequest->getPhone());
+        if (!$this->phoneNumberUtil->isPossibleNumber($organizationMemberCreationRequest->getPhone())) {
+            throw new \RuntimeException('Phone number is invalid or missing (person: ' . $organizationMemberCreationRequest->getUsername() . ')');
+        }
+        if (
+            $organizationMemberCreationRequest->getMobile() !== null &&
+            !$this->phoneNumberUtil->isPossibleNumber($organizationMemberCreationRequest->getMobile())) {
+            throw new \RuntimeException('Mobile phone number is invalid (person: ' . $organizationMemberCreationRequest->getUsername() . ')');
+        }
+
+        $phoneNumber = $this->phoneNumberUtil->parse($organizationMemberCreationRequest->getPhone());
 
 
         $contactPoint = new ContactPoint();
         $contactPoint = new ContactPoint();
         $contactPoint->setContactType(ContactPointTypeEnum::PRINCIPAL);
         $contactPoint->setContactType(ContactPointTypeEnum::PRINCIPAL);
@@ -658,7 +677,7 @@ class OrganizationFactory
         $contactPoint->setTelphone($phoneNumber);
         $contactPoint->setTelphone($phoneNumber);
 
 
         if ($organizationMemberCreationRequest->getMobile() !== null) {
         if ($organizationMemberCreationRequest->getMobile() !== null) {
-            $mobileNumber = $phoneUtil->parse($organizationMemberCreationRequest->getMobile());
+            $mobileNumber = $this->phoneNumberUtil->parse($organizationMemberCreationRequest->getMobile());
             $contactPoint->setMobilPhone($mobileNumber);
             $contactPoint->setMobilPhone($mobileNumber);
         }
         }
 
 

+ 123 - 14
tests/Unit/Service/Organization/OrganizationFactoryTest.php

@@ -1398,6 +1398,11 @@ class OrganizationFactoryTest extends TestCase
         $organizationMemberCreationRequest->method('getGivenName')->willReturn('bOBBy');
         $organizationMemberCreationRequest->method('getGivenName')->willReturn('bOBBy');
         $organizationMemberCreationRequest->method('getGender')->willReturn(GenderEnum::MISTER);
         $organizationMemberCreationRequest->method('getGender')->willReturn(GenderEnum::MISTER);
 
 
+        $this->personRepository
+            ->method('findOneBy')
+            ->with(['username' => 'bob'], null)
+            ->willReturn(null);
+
         $personAddressPostal = $this->getMockBuilder(PersonAddressPostal::class)->getMock();
         $personAddressPostal = $this->getMockBuilder(PersonAddressPostal::class)->getMock();
         $organizationFactory
         $organizationFactory
             ->expects(self::once())
             ->expects(self::once())
@@ -1440,6 +1445,37 @@ class OrganizationFactoryTest extends TestCase
         );
         );
     }
     }
 
 
+    public function testMakeAccessNewPersonUsernameAlreadyInUse(): void
+    {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('makeAccess');
+
+        $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock();
+
+        $organizationMemberCreationRequest->method('getUsername')->willReturn('bob');
+        $organizationMemberCreationRequest->method('getName')->willReturn('Bob');
+        $organizationMemberCreationRequest->method('getGivenName')->willReturn('bOBBy');
+        $organizationMemberCreationRequest->method('getGender')->willReturn(GenderEnum::MISTER);
+
+        $person = $this->getMockBuilder(Person::class)->getMock();
+        $this->personRepository
+            ->method('findOneBy')
+            ->with(['username' => 'bob'], null)
+            ->willReturn($person);
+
+        $organizationFactory
+            ->expects(self::never())
+            ->method('makePersonPostalAddress');
+
+        $organizationFactory
+                ->expects(self::never())
+                ->method('makePersonContactPoint');
+
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionMessage('Username already in use : bob');
+
+       $organizationFactory->makeAccess($organizationMemberCreationRequest);
+    }
+
     public function testMakeAccessExistingPerson(): void
     public function testMakeAccessExistingPerson(): void
     {
     {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeAccess');
         $organizationFactory = $this->getOrganizationFactoryMockFor('makeAccess');
@@ -1507,6 +1543,25 @@ class OrganizationFactoryTest extends TestCase
         $organizationMemberCreationRequest->method('getEmail')->willReturn('email@domain.com');
         $organizationMemberCreationRequest->method('getEmail')->willReturn('email@domain.com');
         $organizationMemberCreationRequest->method('getMobile')->willReturn('+33607080910');
         $organizationMemberCreationRequest->method('getMobile')->willReturn('+33607080910');
 
 
+        $this->phoneNumberUtil
+            ->expects(self::exactly(2))
+            ->method('isPossibleNumber')
+            ->willReturnMap([
+                ['+33102030405', null, true],
+                ['+33607080910', null, true],
+            ]);
+
+        $phoneNumber = $this->getMockBuilder(PhoneNumber::class)->getMock();
+        $mobilePhoneNumber = $this->getMockBuilder(PhoneNumber::class)->getMock();
+
+        $this->phoneNumberUtil
+            ->expects(self::exactly(2))
+            ->method('parse')
+            ->willReturnMap([
+                ['+33102030405', null, null, false, $phoneNumber],
+                ['+33607080910', null, null, false, $mobilePhoneNumber],
+            ]);
+
         $contactPoint = $organizationFactory->makePersonContactPoint($organizationMemberCreationRequest);
         $contactPoint = $organizationFactory->makePersonContactPoint($organizationMemberCreationRequest);
 
 
         $this->assertEquals(
         $this->assertEquals(
@@ -1515,29 +1570,77 @@ class OrganizationFactoryTest extends TestCase
         );
         );
 
 
         $this->assertEquals(
         $this->assertEquals(
-            '33',
-            $contactPoint->getTelphone()->getCountryCode()
-        );
-        $this->assertEquals(
-            '102030405',
-            $contactPoint->getTelphone()->getNationalNumber()
+            'email@domain.com',
+            $contactPoint->getEmail()
         );
         );
 
 
         $this->assertEquals(
         $this->assertEquals(
-            '33',
-            $contactPoint->getMobilPhone()->getCountryCode()
-        );
-        $this->assertEquals(
-            '607080910',
-            $contactPoint->getMobilPhone()->getNationalNumber()
+            $phoneNumber,
+            $contactPoint->getTelphone()
         );
         );
 
 
         $this->assertEquals(
         $this->assertEquals(
-            'email@domain.com',
-            $contactPoint->getEmail()
+            $mobilePhoneNumber,
+            $contactPoint->getMobilPhone()
         );
         );
     }
     }
 
 
+    public function testMakeAccessContactPointInvalidPhone(): void
+    {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint');
+
+        $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock();
+
+        $organizationMemberCreationRequest->method('getUsername')->willReturn('bob');
+        $organizationMemberCreationRequest->method('getPhone')->willReturn('invalid');
+        $organizationMemberCreationRequest->method('getEmail')->willReturn('email@domain.com');
+        $organizationMemberCreationRequest->method('getMobile')->willReturn('+33607080910');
+
+        $this->phoneNumberUtil
+            ->expects(self::once())
+            ->method('isPossibleNumber')
+            ->with('invalid')
+            ->willReturn(false);
+
+        $this->phoneNumberUtil
+            ->expects(self::never())
+            ->method('parse');
+
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionMessage('Phone number is invalid or missing (person: bob)');
+
+        $organizationFactory->makePersonContactPoint($organizationMemberCreationRequest);
+    }
+
+    public function testMakeAccessContactPointInvalidMobilePhone(): void
+    {
+        $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint');
+
+        $organizationMemberCreationRequest = $this->getMockBuilder(OrganizationMemberCreationRequest::class)->getMock();
+
+        $organizationMemberCreationRequest->method('getUsername')->willReturn('bob');
+        $organizationMemberCreationRequest->method('getPhone')->willReturn('+33102030405');
+        $organizationMemberCreationRequest->method('getEmail')->willReturn('email@domain.com');
+        $organizationMemberCreationRequest->method('getMobile')->willReturn('invalid');
+
+        $this->phoneNumberUtil
+            ->expects(self::exactly(2))
+            ->method('isPossibleNumber')
+            ->willReturnMap([
+                ['+33102030405', null, true],
+                ['invalid', null, false],
+            ]);
+
+        $this->phoneNumberUtil
+            ->expects(self::never())
+            ->method('parse');
+
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionMessage('Mobile phone number is invalid (person: bob)');
+
+        $organizationFactory->makePersonContactPoint($organizationMemberCreationRequest);
+    }
+
     public function testMakePersonContactPointNoMobile(): void
     public function testMakePersonContactPointNoMobile(): void
     {
     {
         $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint');
         $organizationFactory = $this->getOrganizationFactoryMockFor('makePersonContactPoint');
@@ -1547,6 +1650,12 @@ class OrganizationFactoryTest extends TestCase
         $organizationMemberCreationRequest->method('getPhone')->willReturn('+33102030405');
         $organizationMemberCreationRequest->method('getPhone')->willReturn('+33102030405');
         $organizationMemberCreationRequest->method('getMobile')->willReturn(null);
         $organizationMemberCreationRequest->method('getMobile')->willReturn(null);
 
 
+        $this->phoneNumberUtil
+            ->expects(self::once())
+            ->method('isPossibleNumber')
+            ->with('+33102030405')
+            ->willReturn(true);
+
         $contactPoint = $organizationFactory->makePersonContactPoint($organizationMemberCreationRequest);
         $contactPoint = $organizationFactory->makePersonContactPoint($organizationMemberCreationRequest);
 
 
         $this->assertEquals(
         $this->assertEquals(