Browse Source

Merge branch 'feature/V8-5206-ajout-dun-controle-lors-de-lenre' into develop

Olivier Massot 1 year ago
parent
commit
23a4382b9c

+ 1 - 1
config/packages/nelmio_cors.yaml

@@ -3,7 +3,7 @@ nelmio_cors:
         origin_regex: true
         allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
         allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
-        allow_headers: ['Content-Type', 'Authorization', 'x-accessid', 'x-switch-user']
+        allow_headers: ['Content-Type', 'Authorization', 'x-accessid', 'x-switch-user', 'profileHash']
         expose_headers: ['Link']
         max_age: 3600
     paths:

+ 16 - 1
src/EventListener/OnKernelRequestPreRead.php

@@ -5,6 +5,7 @@ namespace App\EventListener;
 use ApiPlatform\Symfony\EventListener\EventPriorities;
 use App\Entity\Access\Access;
 use App\Service\Doctrine\FiltersConfigurationService;
+use App\Service\Utils\ObjectUtils;
 use App\Service\Utils\StringsUtils;
 use Symfony\Bundle\SecurityBundle\Security;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -17,7 +18,7 @@ class OnKernelRequestPreRead implements EventSubscriberInterface
     public function __construct(
         private RequestStack $requestStack,
         private Security $security,
-        private FiltersConfigurationService $filtersConfigurationService
+        private FiltersConfigurationService $filtersConfigurationService,
     ) {
     }
 
@@ -45,8 +46,22 @@ class OnKernelRequestPreRead implements EventSubscriberInterface
             );
 
             if ($timeConstraintEnabled) {
+                // Configure les filtres pour prendre en compte les contraintes temporelles
                 $this->filtersConfigurationService->configureTimeConstraintFilters($access->getId());
             }
+
+            $profileHash = $event->getRequest()->headers->get('profileHash');
+            if (null !== $profileHash) {
+                $profileMask = [
+                    'activityYear' => $access->getActivityYear(),
+                    'historical' => $access->getHistorical(),
+                ];
+                $expectedHash = ObjectUtils::hash($profileMask, 'sha1');
+
+                if ($expectedHash !== $profileHash) {
+                    throw new \RuntimeException('Invalid profile hash');
+                }
+            }
         }
     }
 }

+ 23 - 0
src/Service/Utils/ObjectUtils.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Service\Utils;
+
+class ObjectUtils
+{
+    /**
+     * Créé un hash à partir d'un objet
+     * (après l'avoir trié selon ses clés, et convertit en json sans espace).
+     *
+     * @param object|array<mixed> $instance
+     */
+    public static function hash(object|array $instance, string $algorithm = 'sha256'): string
+    {
+        // Convertit l'objet en tableau associatif
+        $array = (array) $instance;
+        // Puis trie l'objet selon ses clés, encode en json, et hash
+        ksort($array);
+        $json = json_encode((object) $array);
+
+        return hash($algorithm, $json);
+    }
+}

+ 53 - 0
tests/Unit/Service/Utils/ObjectUtilsTest.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Tests\Unit\Service\Utils;
+
+use App\Service\Utils\ObjectUtils;
+use PHPUnit\Framework\TestCase;
+
+class ObjectUtilsTest extends TestCase
+{
+    public function testHashWithEmptyArray()
+    {
+        $this->assertEquals(
+            '44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a',
+            ObjectUtils::hash([])
+        );
+        $this->assertEquals(
+            'bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f',
+            ObjectUtils::hash([], 'sha1')
+        );
+    }
+
+    public function testHashWithArray()
+    {
+        $this->assertEquals(
+            'e6a3385fb77c287a712e7f406a451727f0625041823ecf23bea7ef39b2e39805',
+            ObjectUtils::hash(['a' => 1, 'b' => 2, 'c' => 3])
+        );
+        $this->assertEquals(
+            'e7ec4a8f2309bdd4c4c57cb2adfb79c91a293597',
+            ObjectUtils::hash(['a' => 1, 'b' => 2, 'c' => 3], 'sha1')
+        );
+    }
+
+    public function testHashWithUnsortedArray()
+    {
+        $this->assertEquals(
+            ObjectUtils::hash(['a' => 1, 'b' => 2, 'c' => 3]),
+            ObjectUtils::hash(['b' => 2, 'a' => 1, 'c' => 3])
+        );
+        $this->assertEquals(
+            ObjectUtils::hash(['a' => 1, 'b' => 2, 'c' => 3], 'sha1'),
+            ObjectUtils::hash(['b' => 2, 'a' => 1, 'c' => 3], 'sha1')
+        );
+    }
+
+    public function testHashWithObject()
+    {
+        $this->assertEquals(
+            'e6a3385fb77c287a712e7f406a451727f0625041823ecf23bea7ef39b2e39805',
+            ObjectUtils::hash((object) ['a' => 1, 'b' => 2, 'c' => 3])
+        );
+    }
+}