Selaa lähdekoodia

implements reserved subdomains, add ConfigUtils, restore tests

Olivier Massot 2 vuotta sitten
vanhempi
commit
9ced8d325a

+ 53 - 0
config/opentalent/subdomains.yaml

@@ -0,0 +1,53 @@
+# Liste des sous-domaines réservés (sous forme de RegEx, sans les caractères de début et de fin de ligne '^' et '$')
+# @see https://ressources.opentalent.fr/display/SPEC/Nom+de+sous+domaines+reserves+pour+2IOS
+reserved:
+  - opentalent
+  - 2ios
+  - 2iopenservice
+  - app
+  - my
+  - api
+  - ap2i
+  - local
+  - logs?
+  - stats
+  - preprod\d*
+  - test\d*
+  - admin
+  - frames
+  - git
+  - v\d+
+  - myadmin
+  - mailcatcher
+  - mail
+  - gitlab
+  - metabase
+  - dolibarr
+  - prod
+  - production
+  - assistance
+  - ressources
+  - support
+  - statistiques.*
+  - drive
+  - cloud
+  - www
+  - ww\d*
+  - agenda
+  - store
+  - boutique
+  - annuaire
+  - opentalent
+  - 2iopenservice
+  - typo3
+  - actus?
+  - actualites?
+  - news
+  - annonces?
+  - mobile
+  - membres
+  - mercure
+  - kibana
+  - phpmyadmin
+  - elasticsearch
+  - es

+ 7 - 51
src/Service/Security/Module.php

@@ -4,10 +4,9 @@ declare(strict_types=1);
 namespace App\Service\Security;
 
 use App\Entity\Organization\Organization;
-use App\Service\Utils\Parser;
+use App\Service\Utils\ConfigUtils;
 use App\Service\Utils\Reflection;
 use Doctrine\Common\Cache\ApcuCache;
-use Symfony\Component\Config\FileLocator;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 
 /**
@@ -28,9 +27,8 @@ class Module
 
     public function __construct(
         readonly private Reflection $reflection,
-        readonly private Parser $parser,
-        readonly private string $opentalentConfig)
-    {}
+        readonly private ConfigUtils $configUtils
+    ) {}
 
     /**
      * @todo activer le cache après que la fin de la migration.
@@ -89,7 +87,7 @@ class Module
     public function getModulesByConditions(Organization $organization): array
     {
         $modulesByConditions = [];
-        $modules = $this->getModuleByConditionsConfig()['opentalent']['modulesbyconditions'];
+        $modules = $this->configUtils->loadFromFile('modulesbyconditions')['opentalent']['modulesbyconditions'];
         foreach ($modules as $moduleName => $module) {
             try{
                 $response = $this->reflection->dynamicInvokeServiceWithArgsAndMethod(
@@ -117,10 +115,10 @@ class Module
     {
         $product = str_replace('-', '_', $product);
 
-        if (!array_key_exists($product, $this->getModuleConfig()['opentalent']['products'])) {
+        if (!array_key_exists($product, $this->configUtils->loadFromFile('products')['opentalent']['products'])) {
             throw new AccessDeniedHttpException(sprintf('The product %s does not exist !', $product));
         }
-        $productConfig = $this->getModuleConfig()['opentalent']['products'][$product];
+        $productConfig = $this->configUtils->loadFromFile('products')['opentalent']['products'][$product];
         $modules = $productConfig['modules'] ?? [];
 
         if (array_key_exists('extend', $productConfig)) {
@@ -131,48 +129,6 @@ class Module
         return $modules;
     }
 
-    /**
-     * @return mixed[]
-     * @throws \Exception
-     */
-    protected function getModuleConfig(): array {
-        if ($this->moduleConfig === null) {
-            $this->moduleConfig = $this->loadModuleConfig();
-        }
-        return $this->moduleConfig;
-    }
-
-    /**
-     * Parse et retourne le contenu du fichier products.yaml
-     * @return mixed
-     * @throws \Exception
-     */
-    protected function loadModuleConfig(): mixed
-    {
-        return $this->parser->yamlParser($this->opentalentConfig, 'products.yaml');
-    }
-
-    /**
-     * @return mixed[]
-     * @throws \Exception
-     */
-    protected function getModuleByConditionsConfig(): array {
-        if ($this->moduleByConditionsConfig === null) {
-            $this->moduleByConditionsConfig = $this->loadModuleByConditionsConfig();
-        }
-        return $this->moduleByConditionsConfig;
-    }
-
-    /**
-     * Parse et retourne le contenu du fichier modulesbyconditions.yaml
-     * @return mixed
-     * @throws \Exception
-     */
-    protected function loadModuleByConditionsConfig(): mixed
-    {
-        return $this->parser->yamlParser($this->opentalentConfig, 'modulesbyconditions.yaml');
-    }
-
     /**
      * Retourne le module possédant la resource passée en paramètre
      * @param string $resource
@@ -180,7 +136,7 @@ class Module
      */
     public function getModuleByResourceName(string $resource): int|string|null
     {
-        $modules = $this->getModuleConfig()['opentalent']['modules'];
+        $modules = $this->configUtils->loadFromFile('products')['opentalent']['modules'];
         foreach ($modules as $module => $data) {
             if ($data['entities'] && in_array($resource, $data['entities'], true)) {
                 return $module;

+ 28 - 1
src/Service/Typo3/SubdomainService.php

@@ -11,6 +11,7 @@ use App\Repository\Access\AccessRepository;
 use App\Repository\Organization\SubdomainRepository;
 use App\Service\Mailer\Model\SubdomainChangeModel;
 use App\Service\Organization\Utils as OrganizationUtils;
+use App\Service\Utils\ConfigUtils;
 use Doctrine\ORM\EntityManagerInterface;
 use Symfony\Bundle\SecurityBundle\Security;
 use Symfony\Component\Console\Exception\InvalidArgumentException;
@@ -33,7 +34,8 @@ class SubdomainService
         private readonly MessageBusInterface $messageBus,
         private readonly OrganizationUtils $organizationUtils,
         private readonly BindFileService $bindFileService,
-        private readonly AccessRepository $accessRepository
+        private readonly AccessRepository $accessRepository,
+        private readonly ConfigUtils $configUtils
     ) {}
 
     /**
@@ -61,6 +63,27 @@ class SubdomainService
         return (bool)preg_match(self::RX_VALIDATE_SUBDOMAIN, $subdomainValue);
     }
 
+    /**
+     * Is the subdomain a reserved one
+     * @see https://ressources.opentalent.fr/display/SPEC/Nom+de+sous+domaines+reserves+pour+2IOS
+     *
+     * @param string $subdomainValue
+     * @return bool
+     * @throws \Exception
+     */
+    public function isReservedSubdomain(string $subdomainValue): bool {
+        $reservedSubdomains = $this->configUtils->loadFromFile('subdomains')['reserved'];
+
+        $subRegexes = array_map(
+            function (string $s) { return '(' . trim($s, '^$/\s') . ')'; },
+            $reservedSubdomains
+        );
+
+        $regex = '/^' . strtolower(implode("|", $subRegexes)) . '$/';
+
+        return preg_match($regex, $subdomainValue) !== 0;
+    }
+
     /**
      * Register a new subdomain for the organization
      * Is $activate is true, makes this new subdomain the active one too.
@@ -84,6 +107,10 @@ class SubdomainService
             throw new \RuntimeException("This organization can not register new subdomains");
         }
 
+        if ($this->isReservedSubdomain($subdomainValue)) {
+            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])) {
             throw new \RuntimeException('This subdomain is already registered');

+ 47 - 0
src/Service/Utils/ConfigUtils.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace App\Service\Utils;
+
+use App\Service\Utils\Parser\YamlParser;
+
+/**
+ * Fonctions d'accès à la configuration Opentalent
+ */
+class ConfigUtils
+{
+    private array $cache = [];
+
+    public function __construct(
+        readonly private string     $opentalentConfig,
+        private YamlParser          $yamlParser
+    ) {}
+
+    /**
+     * Parse et retourne le contenu du fichier de configuration yaml donné
+     *
+     * Exemple :
+     *
+     *     $this->configUtils->loadFromFile('products');
+     *
+     * @return mixed
+     * @throws \Exception
+     */
+    public function loadFromFile(string $filename): mixed
+    {
+        $filename = strtolower($filename);
+        if (pathinfo($filename, PATHINFO_EXTENSION) !== 'yaml') {
+            $filename = $filename . '.yaml';
+        }
+
+        if (array_key_exists($filename, $this->cache)) {
+            return $this->cache[$filename];
+        }
+
+        $path = Path::locate([$this->opentalentConfig], $filename);
+        $data = $this->yamlParser->parseFile($path);
+
+        $cache[$filename] = $data;
+
+        return $data;
+    }
+}

+ 0 - 29
src/Service/Utils/Parser.php

@@ -1,29 +0,0 @@
-<?php
-declare(strict_types=1);
-
-namespace App\Service\Utils;
-
-use Symfony\Component\Config\FileLocator;
-use Symfony\Component\Yaml\Yaml;
-
-/**
- * Class Parser : méthodes d'aide pour la gestion de parsing de fichier.
- * @package App\Service\Utils
- */
-class Parser
-{
-    /**
-     * Parse le fichier yaml passé en paramètre et renvoie un tableau PHP
-     * @param string $directory
-     * @param string $yamlFile
-     * @return mixed
-     * @see ParserTest::testYamlParser()
-     */
-    public function yamlParser(string $directory, string $yamlFile): mixed
-    {
-        $configDirectories = [$directory];
-        $fileLocator = new FileLocator($configDirectories);
-        $yamlConfig = $fileLocator->locate($yamlFile, null, false)[0];
-        return Yaml::parseFile($yamlConfig);
-    }
-}

+ 25 - 0
src/Service/Utils/Parser/ParserInterface.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Service\Utils\Parser;
+
+/**
+ * Interface d'un service de parsing de fichiers
+ */
+interface ParserInterface
+{
+    /**
+     * Parse une chaine de caractères au format donné
+     *
+     * @param string $content
+     * @return mixed
+     */
+    public function parse(string $content): mixed;
+
+    /**
+     * Parse le contenu d'un fichier au format donné
+     *
+     * @param string $path
+     * @return mixed
+     */
+    public function parseFile(string $path): mixed;
+}

+ 36 - 0
src/Service/Utils/Parser/YamlParser.php

@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Utils\Parser;
+
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\Yaml\Yaml;
+
+/**
+ * Class Parser : méthodes d'aide pour la gestion de parsing de fichier.
+ * @package App\Service\Utils
+ */
+class YamlParser implements ParserInterface
+{
+    /**
+     * Parse la chaine de caractères au format Yaml donné et renvoie un tableau PHP
+     *
+     * @param string $content
+     * @return mixed
+     */
+    public function parse(string $content): mixed {
+        return Yaml::parse($content);
+    }
+
+    /**
+     * Parse le fichier yaml passé en paramètre et renvoie un tableau PHP
+     *
+     * @param string $path Chemin d'accès du fichier à parser
+     * @return mixed
+     * @see ParserTest::testYamlParser()
+     */
+    public function parseFile(string $path): mixed
+    {
+        return Yaml::parseFile($path);
+    }
+}

+ 13 - 0
src/Service/Utils/Path.php

@@ -4,6 +4,7 @@ declare(strict_types=1);
 namespace App\Service\Utils;
 
 use RuntimeException;
+use Symfony\Component\Config\FileLocator;
 
 /**
  * Various methods to manipulate file paths
@@ -66,4 +67,16 @@ class Path
         }
         return $content;
     }
+
+    /**
+     * Locate a file in the given directories and return its absolute path
+     *
+     * @param array<string> $directories
+     * @param string $filename
+     * @return string
+     */
+    public static function locate(array $directories, string $filename): string {
+        $fileLocator = new FileLocator($directories);
+        return $fileLocator->locate($filename, null, false)[0];
+    }
 }

+ 5 - 5
src/State/Provider/Enum/EnumProvider.php

@@ -7,7 +7,8 @@ use ApiPlatform\Metadata\GetCollection;
 use ApiPlatform\Metadata\Operation;
 use ApiPlatform\State\ProviderInterface;
 use App\ApiResources\Enum\Enum;
-use App\Service\Utils\Parser;
+use App\Service\Utils\ConfigUtils;
+use App\Service\Utils\Parser\YamlParser;
 use App\Service\Utils\Reflection;
 use Exception;
 use RuntimeException;
@@ -20,8 +21,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 final class EnumProvider implements ProviderInterface
 {
     public function __construct(
-        private Parser $parser,
-        private string $opentalentConfig,
+        private ConfigUtils $configUtils,
         private Reflection $reflection
     )
     { }
@@ -39,7 +39,7 @@ final class EnumProvider implements ProviderInterface
         }
 
         $id = $uriVariables['id'];
-        $enums = $this->parser->yamlParser($this->opentalentConfig, 'enum.yaml');
+        $enums = $this->configUtils->loadFromFile('enum');
         $enumClass = $enums['opentalent'][$id];
 
         if(!$enumClass) {
@@ -60,4 +60,4 @@ final class EnumProvider implements ProviderInterface
         $enumResponse->setItems($items);
         return $enumResponse;
     }
-}
+}

+ 35 - 121
tests/Unit/Service/Security/ModuleTest.php

@@ -6,16 +6,16 @@ use App\Entity\Organization\Organization;
 use App\Entity\Organization\Settings;
 use App\Service\Cotisation\Utils as CotisationUtils;
 use App\Service\Security\Module;
-use App\Service\Utils\Parser;
+use App\Service\Utils\ConfigUtils;
+use App\Service\Utils\Parser\YamlParser;
 use App\Service\Utils\Reflection;
+use Hoa\Iterator\Mock;
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
+use PHPUnit\Util\Test;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 
 class TestableModule extends Module {
-    public function loadModuleConfig(): array { return parent::loadModuleConfig(); }
-    public function getModuleConfig(): array { return parent::getModuleConfig(); }
-    public function loadModuleByConditionsConfig(): array { return parent::loadModuleByConditionsConfig(); }
     public function getModuleByConditionsConfig(): array { return parent::getModuleByConditionsConfig(); }
 }
 
@@ -24,12 +24,19 @@ class ModuleTest extends TestCase
     private const OPENTALENT_CONFIG = __DIR__.'/../../../config/opentalent';
 
     private MockObject | Reflection $reflection;
-    private MockObject | Parser $parser;
+    private MockObject | YamlParser $parser;
 
     public function setUp():void
     {
         $this->reflection = $this->getMockBuilder(Reflection::class)->disableOriginalConstructor()->getMock();
-        $this->parser = $this->getMockBuilder(Parser::class)->disableOriginalConstructor()->getMock();
+        $this->configUtils = $this->getMockBuilder(ConfigUtils::class)->disableOriginalConstructor()->getMock();
+    }
+
+    public function getMockForMethod(string $methodName): MockObject | TestableModule {
+        return $this->getMockBuilder(TestableModule::class)
+            ->setConstructorArgs([$this->reflection, $this->configUtils])
+            ->setMethodsExcept([$methodName])
+            ->getMock();
     }
 
     /**
@@ -37,10 +44,7 @@ class ModuleTest extends TestCase
      */
     public function testGetOrganizationModules(): void
     {
-        $module = $this->getMockBuilder(Module::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getOrganizationModules'])
-            ->getMock();
+        $module = $this->getMockForMethod('getOrganizationModules');
 
         $module->expects(self::once())->method('getModuleBySettings')->willReturn(['Sms']);
         $module->expects(self::once())->method('getModulesByConditions')->willReturn(['CotisationCall']);
@@ -64,10 +68,7 @@ class ModuleTest extends TestCase
      */
     public function testGetModuleBySettings(): void
     {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModuleBySettings'])
-            ->getMock();
+        $module = $this->getMockForMethod('getModuleBySettings');
 
         $settings = $this->getMockBuilder(Settings::class)->getMock();
         $settings
@@ -89,12 +90,9 @@ class ModuleTest extends TestCase
      */
     public function testGetModulesByConditions(): void
     {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModulesByConditions'])
-            ->getMock();
+        $module = $this->getMockForMethod('getModulesByConditions');
 
-        $module->method('getModuleByConditionsConfig')->willReturn(
+        $this->configUtils->method('loadFromFile')->with('modulesbyconditions')->willReturn(
             ['opentalent' =>
                 ['modulesbyconditions' =>
                     ['CotisationCall' => [
@@ -124,12 +122,9 @@ class ModuleTest extends TestCase
      */
     public function testGetModulesByConditionsLogicError(): void
     {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModulesByConditions'])
-            ->getMock();
+        $module = $this->getMockForMethod('getModulesByConditions');
 
-        $module->method('getModuleByConditionsConfig')->willReturn(
+        $this->configUtils->method('loadFromFile')->with('modulesbyconditions')->willReturn(
             ['opentalent' =>
                 ['modulesbyconditions' =>
                     ['CotisationCall' => []]
@@ -153,12 +148,11 @@ class ModuleTest extends TestCase
      */
     public function testGetModulesByProductConfiguration(): void
     {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModulesByProductConfiguration'])
-            ->getMock();
+        $module = $this->getMockForMethod('getModulesByProductConfiguration');
 
-        $module->method('getModuleConfig')->willReturn(['opentalent' => ['products' => ['artist' => ['modules' => ['foo']]]]]);
+        $this->configUtils->method('loadFromFile')->with('products')->willReturn(
+            ['opentalent' => ['products' => ['artist' => ['modules' => ['foo']]]]]
+        );
 
         $this->assertEquals(['foo'], $module->getModulesByProductConfiguration('artist')) ;
     }
@@ -168,12 +162,9 @@ class ModuleTest extends TestCase
      */
     public function testGetModulesByProductConfigurationExtend(): void
     {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModulesByProductConfiguration'])
-            ->getMock();
+        $module = $this->getMockForMethod('getModulesByProductConfiguration');
 
-        $module->method('getModuleConfig')->willReturn(
+        $this->configUtils->method('loadFromFile')->with('products')->willReturn(
             ['opentalent' =>
                 ['products' =>
                     [
@@ -195,12 +186,13 @@ class ModuleTest extends TestCase
      */
     public function testGetModulesByProductConfigurationAccessDenied(): void
     {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModulesByProductConfiguration'])
-            ->getMock();
+        $module = $this->getMockBuilder(TestableModule::class);
 
-        $module->method('getModuleConfig')->willReturn(['opentalent' => ['products' => ['artist' => ['modules' => ['foo']]]]]);
+        $module = $this->getMockForMethod('getModulesByProductConfiguration');
+
+        $this->configUtils->method('loadFromFile')->with('products')->willReturn(
+            ['opentalent' => ['products' => ['artist' => ['modules' => ['foo']]]]]
+        );
 
         $this->expectException(AccessDeniedHttpException::class);
         $this->expectExceptionMessage('The product artist_premium does not exist !');
@@ -208,88 +200,13 @@ class ModuleTest extends TestCase
         $module->getModulesByProductConfiguration('artist-premium');
     }
 
-    /**
-     * @see Module::getModuleConfig()
-     */
-    public function testGetModuleConfig(): void {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModuleConfig'])
-            ->getMock();
-
-        $module->expects(self::once())->method('loadModuleConfig')->willReturn(['foo']);
-
-        $this->assertEquals(['foo'], $module->getModuleConfig());
-        $this->assertEquals(['foo'], $module->getModuleConfig());
-    }
-
-    /**
-     * @see Module::loadModuleConfig()
-     */
-    public function testLoadModuleConfig(): void {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['loadModuleConfig'])
-            ->getMock();
-
-        $this->parser
-            ->expects(self::once())
-            ->method('yamlParser')
-            ->with(self::OPENTALENT_CONFIG, 'products.yaml')
-            ->willReturn(['foo']);
-
-        $this->assertEquals(
-            ['foo'],
-            $module->loadModuleConfig()
-        );
-    }
-
-    /**
-     * @see Module::getModuleByConditionsConfig()
-     */
-    public function testGetModuleByConditionsConfig(): void {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModuleByConditionsConfig'])
-            ->getMock();
-
-        $module->expects(self::once())->method('loadModuleByConditionsConfig')->willReturn(['foo']);
-
-        $this->assertEquals(['foo'], $module->getModuleByConditionsConfig());
-        $this->assertEquals(['foo'], $module->getModuleByConditionsConfig());
-    }
-
-    /**
-     * @see Module::loadModuleByConditionsConfig()
-     */
-    public function testLoadModuleByConditionsConfig(): void {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['loadModuleByConditionsConfig'])
-            ->getMock();
-
-        $this->parser->expects(self::once())
-            ->method('yamlParser')
-            ->with(self::OPENTALENT_CONFIG, 'modulesbyconditions.yaml')
-            ->willReturn(['foo']);
-
-        $this->assertEquals(
-            ['foo'],
-            $module->loadModuleByConditionsConfig()
-        );
-    }
-
     /**
      * @see Module::getModuleByResourceName()
      */
     public function testGetModuleByResourceName(): void {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModuleByResourceName'])
-            ->getMock();
+        $module = $this->getMockForMethod('getModuleByResourceName');
 
-
-        $module->method('getModuleConfig')->willReturn(
+        $this->configUtils->method('loadFromFile')->with('products')->willReturn(
             ['opentalent' =>
                 ['modules' =>
                     ['Core' => ['entities' => ['foo', 'bar']]]
@@ -304,12 +221,9 @@ class ModuleTest extends TestCase
      * @see Module::getModuleByResourceName()
      */
     public function testGetModuleByResourceNameNotFound(): void {
-        $module = $this->getMockBuilder(TestableModule::class)
-            ->setConstructorArgs([$this->reflection, $this->parser, self::OPENTALENT_CONFIG])
-            ->setMethodsExcept(['getModuleByResourceName'])
-            ->getMock();
+        $module = $this->getMockForMethod('getModuleByResourceName');
 
-        $module->method('getModuleConfig')->willReturn(
+        $this->configUtils->method('loadFromFile')->with('products')->willReturn(
             ['opentalent' =>
                 ['modules' =>
                     ['Core' => ['entities' => ['bar']]]

+ 4 - 1
tests/Unit/Service/Typo3/SubdomainServiceTest.php

@@ -15,6 +15,7 @@ use App\Service\Mailer\Model\SubdomainChangeModel;
 use App\Service\Organization\Utils as OrganizationUtils;
 use App\Service\Typo3\BindFileService;
 use App\Service\Typo3\SubdomainService;
+use App\Service\Utils\ConfigUtils;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\ORM\EntityManagerInterface;
 use PHPUnit\Framework\MockObject\MockObject;
@@ -61,6 +62,7 @@ class SubdomainServiceTest extends TestCase
         $this->organizationUtils = $this->getMockBuilder(OrganizationUtils::class)->disableOriginalConstructor()->getMock();
         $this->bindFileService = $this->getMockBuilder(BindFileService::class)->disableOriginalConstructor()->getMock();
         $this->accessRepository = $this->getMockBuilder(AccessRepository::class)->disableOriginalConstructor()->getMock();
+        $this->configUtils = $this->getMockBuilder(ConfigUtils::class)->disableOriginalConstructor()->getMock();
     }
 
     private function makeSubdomainServiceMockFor(string $methodName): MockObject | TestableSubdomainService {
@@ -71,7 +73,8 @@ class SubdomainServiceTest extends TestCase
                 $this->messageBus,
                 $this->organizationUtils,
                 $this->bindFileService,
-                $this->accessRepository
+                $this->accessRepository,
+                $this->configUtils
             ])
             ->setMethodsExcept([$methodName])
             ->getMock();

+ 43 - 0
tests/Unit/Service/Utils/Parser/YamlParserTest.php

@@ -0,0 +1,43 @@
+<?php
+namespace App\Tests\Unit\Service\Utils\Parser;
+
+use App\Service\Utils\Parser\YamlParser;
+use PHPUnit\Framework\TestCase;
+
+class YamlParserTest extends TestCase
+{
+    public const FIXTURES = __DIR__.'/fixtures';
+
+    /**
+     * @see YamlParser::yamlParser()
+     */
+    public function testParse():void
+    {
+        $parser = new YamlParser();
+        $parsingArray = $parser->parse("
+opentalent:
+    modulesbyconditions:
+        CotisationCall:
+            roles:
+                - ROLE_COTISATION
+            conditions:
+                service:
+                    name: opentalent.cotisation.utils
+                    function: isLastParentAndCMF");
+        $this->assertIsArray($parsingArray);
+        $this->assertIsArray($parsingArray['opentalent']);
+        $this->assertEquals('ROLE_COTISATION', $parsingArray['opentalent']['modulesbyconditions']['CotisationCall']['roles'][0]);
+    }
+
+    /**
+     * @see YamlParser::yamlParser()
+     */
+    public function testParseFile():void
+    {
+        $parser = new YamlParser();
+        $parsingArray = $parser->parseFile(self::FIXTURES . '/fixture.yaml');
+        $this->assertIsArray($parsingArray);
+        $this->assertIsArray($parsingArray['opentalent']);
+        $this->assertEquals('ROLE_COTISATION', $parsingArray['opentalent']['modulesbyconditions']['CotisationCall']['roles'][0]);
+    }
+}

+ 0 - 0
tests/Unit/Service/Utils/fixtures/fixture.yaml → tests/Unit/Service/Utils/Parser/fixtures/fixture.yaml


+ 0 - 22
tests/Unit/Service/Utils/ParserTest.php

@@ -1,22 +0,0 @@
-<?php
-namespace App\Tests\Unit\Service\Utils;
-
-use App\Service\Utils\Parser;
-use PHPUnit\Framework\TestCase;
-
-class ParserTest extends TestCase
-{
-    public const FIXTURES = __DIR__.'/fixtures';
-
-    /**
-     * @see Parser::yamlParser()
-     */
-    public function testYamlParser():void
-    {
-        $parser = new Parser();
-        $parsingArray = $parser->yamlParser(self::FIXTURES, 'fixture.yaml');
-        $this->assertIsArray($parsingArray);
-        $this->assertIsArray($parsingArray['opentalent']);
-        $this->assertEquals('ROLE_COTISATION', $parsingArray['opentalent']['modulesbyconditions']['CotisationCall']['roles'][0]);
-    }
-}