Bläddra i källkod

add the SubdomainAvailability api resource and provider

Olivier Massot 2 år sedan
förälder
incheckning
a814f3a269

+ 1 - 0
config/opentalent/products.yaml

@@ -15,6 +15,7 @@ parameters:
           - Enum
           - LicenceCmfOrganizationER
           - DownloadRequest
+          - SubdomainAvailability
         roles:
           - ROLE_IMPORT
           - ROLE_TAGG

+ 0 - 0
src/ApiResource/.gitignore


+ 89 - 0
src/ApiResources/Organization/Subdomain/SubdomainAvailability.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace App\ApiResources\Organization\Subdomain;
+
+use ApiPlatform\Metadata\ApiProperty;
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\Get;
+use App\State\Provider\Organization\Subdomain\SubdomainAvailabilityProvider;
+
+#[ApiResource(
+    operations: [
+        new Get(
+            uriTemplate: '/subdomains/is_available',
+            security: 'is_granted("ROLE_ORGANIZATION_VIEW") or is_granted("ROLE_ORGANIZATION")',
+            provider: SubdomainAvailabilityProvider::class
+        )
+    ]
+)]
+class SubdomainAvailability
+{
+    /**
+     * Id 'bidon' ajouté par défaut pour permettre la construction
+     * de l'IRI par api platform
+     *
+     * @var int
+     */
+    #[ApiProperty(identifier: true)]
+    protected int $id = 0;
+
+    /**
+     * The subdomain
+     * @var string
+     */
+    private string $subdomain;
+
+    /**
+     * Is the subdomain available (not registered nor reserved)
+     * @var bool
+     */
+    private bool $available;
+
+    /**
+     * @return int
+     */
+    public function getId(): int
+    {
+        return $this->id;
+    }
+
+    /**
+     * @param int $id
+     */
+    public function setId(int $id): void
+    {
+        $this->id = $id;
+    }
+
+    /**
+     * @return string
+     */
+    public function getSubdomain(): string
+    {
+        return $this->subdomain;
+    }
+
+    /**
+     * @param string $subdomain
+     */
+    public function setSubdomain(string $subdomain): void
+    {
+        $this->subdomain = $subdomain;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isAvailable(): bool
+    {
+        return $this->available;
+    }
+
+    /**
+     * @param bool $available
+     */
+    public function setAvailable(bool $available): void
+    {
+        $this->available = $available;
+    }
+}

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

@@ -83,6 +83,16 @@ class SubdomainService
         return preg_match($regex, $subdomainValue) !== 0;
     }
 
+    /**
+     * Returns true if the subdomain has already been registered
+     *
+     * @param string $subdomainValue
+     * @return bool
+     */
+    public function isRegistered(string $subdomainValue): bool {
+        return count($this->subdomainRepository->findBy(['subdomain' => $subdomainValue])) !== 0;
+    }
+
     /**
      * Register a new subdomain for the organization
      * Is $activate is true, makes this new subdomain the active one too.
@@ -110,8 +120,7 @@ class SubdomainService
             throw new \RuntimeException('This subdomain is not available');
         }
 
-        // Vérifie que le sous-domaine n'est pas déjà utilisé
-        if ($this->subdomainRepository->findBy(['subdomain' => $subdomainValue])) {
+        if ($this->isRegistered($subdomainValue)) {
             throw new \RuntimeException('This subdomain is already registered');
         }
 

+ 52 - 0
src/State/Provider/Organization/Subdomain/SubdomainAvailabilityProvider.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace App\State\Provider\Organization\Subdomain;
+
+use ApiPlatform\Metadata\GetCollection;
+use ApiPlatform\Metadata\Operation;
+use ApiPlatform\State\ProviderInterface;
+use App\ApiResources\Organization\Subdomain\SubdomainAvailability;
+use App\Service\File\Exception\FileNotFoundException;
+use App\Service\Typo3\SubdomainService;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Custom provider permettant de tester la disponibilité d'un sous-domaine
+ */
+final class SubdomainAvailabilityProvider implements ProviderInterface
+{
+    public function __construct(
+        private SubdomainService $subdomainService
+    ) {}
+
+    /**
+     * @param Operation $operation
+     * @param array<mixed> $uriVariables
+     * @param array<mixed> $context
+     * @return Response|RedirectResponse
+     * @throws FileNotFoundException
+     */
+    public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?SubdomainAvailability
+    {
+        if ($operation instanceof GetCollection) {
+            throw new \RuntimeException('not supported', 500);
+        }
+
+        $filters = $context['filters'] ?? [];
+        $subdomain = $filters['subdomain'] ?? null;
+        if ($subdomain === null) {
+            throw new \RuntimeException('missing parameter: subdomain', 500);
+        }
+
+        $available =
+            !$this->subdomainService->isRegistered($subdomain) &&
+            !$this->subdomainService->isReservedSubdomain($subdomain);
+
+        $subdomainAvailability = new SubdomainAvailability();
+        $subdomainAvailability->setSubdomain($subdomain);
+        $subdomainAvailability->setAvailable($available);
+
+        return $subdomainAvailability;
+    }
+}

+ 23 - 8
tests/Unit/Service/Typo3/SubdomainServiceTest.php

@@ -146,6 +146,21 @@ class SubdomainServiceTest extends TestCase
         $this->assertFalse($subdomainService->isReservedSubdomain('foo'));
     }
 
+    public function testIsRegisteredSubdomain(): void {
+        $subdomainService = $this->makeSubdomainServiceMockFor('isRegistered');
+
+        $this->subdomainRepository->method('findBy')->willReturnCallback(function ($args) {
+            if ($args === ['subdomain' => 'sub']) {
+                $subdomain = $this->getMockBuilder(Subdomain::class)->getMock();
+                return [$subdomain];
+            }
+            return [];
+        });
+
+        $this->assertTrue($subdomainService->isRegistered('sub'));
+        $this->assertFalse($subdomainService->isRegistered('foo'));
+    }
+
     public function testAddNewSubdomain(): void {
         $subdomainService = $this->makeSubdomainServiceMockFor('addNewSubdomain');
 
@@ -154,7 +169,7 @@ class SubdomainServiceTest extends TestCase
         $subdomainService->expects(self::once())->method('isValidSubdomain')->with('sub')->willReturn(True);
         $subdomainService->expects(self::once())->method('canRegisterNewSubdomain')->with($organization)->willReturn(True);
         $subdomainService->expects(self::once())->method('isReservedSubdomain')->with('sub')->willReturn(false);
-        $this->subdomainRepository->expects(self::once())->method('findBy')->with(['subdomain' => 'sub'])->willReturn(0);
+        $subdomainService->expects(self::once())->method('isRegistered')->with('sub')->willReturn(false);
 
         $this->entityManager->expects(self::once())->method('persist');
         $this->entityManager->expects(self::once())->method('flush');
@@ -177,10 +192,10 @@ class SubdomainServiceTest extends TestCase
 
         $organization = $this->getMockBuilder(Organization::class)->disableOriginalConstructor()->getMock();
 
-        $subdomainService->expects(self::once())->method('isValidSubdomain')->with('_sub')->willReturn(False);
-        $subdomainService->expects(self::never())->method('canRegisterNewSubdomain')->with($organization)->willReturn(True);
+        $subdomainService->expects(self::once())->method('isValidSubdomain')->with('_sub')->willReturn(false);
+        $subdomainService->expects(self::never())->method('canRegisterNewSubdomain')->with($organization)->willReturn(true);
         $subdomainService->expects(self::never())->method('isReservedSubdomain')->with($organization)->willReturn(false);
-        $this->subdomainRepository->expects(self::never())->method('findBy')->with(['subdomain' => '_sub'])->willReturn(0);
+        $subdomainService->expects(self::never())->method('isRegistered')->with('sub')->willReturn(false);
 
         $this->entityManager->expects(self::never())->method('persist');
         $this->entityManager->expects(self::never())->method('flush');
@@ -202,7 +217,7 @@ class SubdomainServiceTest extends TestCase
         $subdomainService->expects(self::once())->method('isValidSubdomain')->with('_sub')->willReturn(true);
         $subdomainService->expects(self::once())->method('canRegisterNewSubdomain')->with($organization)->willReturn(false);
         $subdomainService->expects(self::never())->method('isReservedSubdomain')->with($organization)->willReturn(false);
-        $this->subdomainRepository->expects(self::never())->method('findBy')->with(['subdomain' => '_sub'])->willReturn(0);
+        $subdomainService->expects(self::never())->method('isRegistered')->with('sub')->willReturn(false);
 
         $this->entityManager->expects(self::never())->method('persist');
         $this->entityManager->expects(self::never())->method('flush');
@@ -224,7 +239,7 @@ class SubdomainServiceTest extends TestCase
         $subdomainService->expects(self::once())->method('isValidSubdomain')->with('_sub')->willReturn(true);
         $subdomainService->expects(self::once())->method('canRegisterNewSubdomain')->with($organization)->willReturn(true);
         $subdomainService->expects(self::once())->method('isReservedSubdomain')->with('_sub')->willReturn(true);
-        $this->subdomainRepository->expects(self::never())->method('findBy')->with(['subdomain' => '_sub'])->willReturn(0);
+        $subdomainService->expects(self::never())->method('isRegistered')->with('sub')->willReturn(false);
 
         $this->entityManager->expects(self::never())->method('persist');
         $this->entityManager->expects(self::never())->method('flush');
@@ -246,7 +261,7 @@ class SubdomainServiceTest extends TestCase
         $subdomainService->expects(self::once())->method('isValidSubdomain')->with('sub')->willReturn(true);
         $subdomainService->expects(self::once())->method('canRegisterNewSubdomain')->with($organization)->willReturn(true);
         $subdomainService->expects(self::once())->method('isReservedSubdomain')->with('sub')->willReturn(false);
-        $this->subdomainRepository->expects(self::once())->method('findBy')->with(['subdomain' => 'sub'])->willReturn(1);
+        $subdomainService->expects(self::once())->method('isRegistered')->with('sub')->willReturn(true);
 
         $this->entityManager->expects(self::never())->method('persist');
         $this->entityManager->expects(self::never())->method('flush');
@@ -268,7 +283,7 @@ class SubdomainServiceTest extends TestCase
         $subdomainService->expects(self::once())->method('isValidSubdomain')->with('sub')->willReturn(true);
         $subdomainService->expects(self::once())->method('canRegisterNewSubdomain')->with($organization)->willReturn(true);
         $subdomainService->expects(self::once())->method('isReservedSubdomain')->with('sub')->willReturn(false);
-        $this->subdomainRepository->expects(self::once())->method('findBy')->with(['subdomain' => 'sub'])->willReturn(0);
+        $subdomainService->expects(self::once())->method('isRegistered')->with('sub')->willReturn(false);
 
         $subdomainService->expects(self::once())->method('activateSubdomain');