mirror of
				https://github.com/kevinveenbirkenbach/infinito.git
				synced 2025-10-31 01:09:41 +00:00 
			
		
		
		
	implemented checking of source source attributs
This commit is contained in:
		| @@ -4,9 +4,9 @@ namespace App\Domain\SecureLoadManagement; | ||||
|  | ||||
| use App\Entity\Source\SourceInterface; | ||||
| use App\Entity\Meta\RightInterface; | ||||
| use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; | ||||
| use Doctrine\Common\Persistence\ObjectRepository; | ||||
| use App\Domain\SecureManagement\SecureSourceChecker; | ||||
| use App\Exception\SourceAccessDenied; | ||||
|  | ||||
| /** | ||||
|  * @author kevinfrantz | ||||
| @@ -71,6 +71,6 @@ final class SecureSourceLoader implements SecureSourceLoaderInterface | ||||
|         if ($secureSourceChecker->hasPermission($requestedRight)) { | ||||
|             return $source; | ||||
|         } | ||||
|         throw new AccessDeniedHttpException(); | ||||
|         throw new SourceAccessDenied(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ namespace App\Domain\SecureManagement; | ||||
| use App\Entity\Meta\RightInterface; | ||||
| use App\Entity\Source\SourceInterface; | ||||
| use App\Domain\LawManagement\LawPermissionCheckerService; | ||||
| use App\Exception\SourceAccessDenied; | ||||
|  | ||||
| /** | ||||
|  * @author kevinfrantz | ||||
| @@ -24,10 +25,77 @@ final class SecureSourceChecker implements SecureSourceCheckerInterface | ||||
|         $this->source = $source; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $methodName | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function isGetter(string $methodName): bool | ||||
|     { | ||||
|         return 'get' === substr($methodName, 0, 3); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param mixed $value | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function isSource($value): bool | ||||
|     { | ||||
|         return $value instanceof SourceInterface; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $methodName | ||||
|      * | ||||
|      * @return SourceInterface|null | ||||
|      */ | ||||
|     private function getExpectedSource(string $methodName): ?SourceInterface | ||||
|     { | ||||
|         try { | ||||
|             return $this->source->{$methodName}(); | ||||
|         } catch (\TypeError $typeError) { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RightInterface $requestedRight | ||||
|      * | ||||
|      * @throws SourceAccessDenied It's important to fire this exception to reduce complexity in debuging | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function itterateOverSourceAttributs(RightInterface $requestedRight): bool | ||||
|     { | ||||
|         foreach (get_class_methods($this->source) as $methodName) { | ||||
|             if ($this->isGetter($methodName)) { | ||||
|                 $attributExpectedSource = $this->getExpectedSource($methodName); | ||||
|                 if ($attributExpectedSource) { | ||||
|                     $requestedSubSourceRight = clone $requestedRight; | ||||
|                     $requestedSubSourceRight->setSource($attributExpectedSource); | ||||
|                     if ($this->isSource($attributExpectedSource)) { | ||||
|                         $methodSecureSourceChecker = new self($attributExpectedSource); | ||||
|                         if (!$methodSecureSourceChecker->hasPermission($requestedSubSourceRight)) { | ||||
|                             throw new SourceAccessDenied('Access denied for subsource!'); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * {@inheritdoc} | ||||
|      * | ||||
|      * @see \App\Domain\SecureManagement\SecureSourceCheckerInterface::hasPermission() | ||||
|      */ | ||||
|     public function hasPermission(RightInterface $requestedRight): bool | ||||
|     { | ||||
|         $law = new LawPermissionCheckerService($this->source->getLaw()); | ||||
|  | ||||
|         return $law->hasPermission($requestedRight); | ||||
|         return $law->hasPermission($requestedRight) && $this->itterateOverSourceAttributs($requestedRight); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| namespace App\Domain\SecureManagement; | ||||
|  | ||||
| use App\Entity\Meta\RightInterface; | ||||
| use App\Exception\SourceAccessDenied; | ||||
|  | ||||
| /** | ||||
|  * @author kevinfrantz | ||||
| @@ -10,6 +11,8 @@ use App\Entity\Meta\RightInterface; | ||||
| interface SecureSourceCheckerInterface | ||||
| { | ||||
|     /** | ||||
|      * @throws SourceAccessDenied | ||||
|      * | ||||
|      * @param RightInterface $right | ||||
|      * | ||||
|      * @return bool | ||||
|   | ||||
							
								
								
									
										105
									
								
								application/tests/Unit/Domain/SecureSourceCheckerTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								application/tests/Unit/Domain/SecureSourceCheckerTest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Tests\Unit\Domain; | ||||
|  | ||||
| use PHPUnit\Framework\TestCase; | ||||
| use App\Entity\Source\SourceInterface; | ||||
| use App\Domain\SecureManagement\SecureSourceCheckerInterface; | ||||
| use App\Entity\Source\AbstractSource; | ||||
| use App\Domain\SecureManagement\SecureSourceChecker; | ||||
| use App\Entity\Meta\Right; | ||||
| use App\DBAL\Types\LayerType; | ||||
| use App\DBAL\Types\RightType; | ||||
| use App\Entity\Attribut\SourceAttribut; | ||||
| use App\Entity\Attribut\SourceAttributInterface; | ||||
| use App\Exception\SourceAccessDenied; | ||||
|  | ||||
| /** | ||||
|  * @author kevinfrantz | ||||
|  */ | ||||
| class SecureSourceCheckerTest extends TestCase | ||||
| { | ||||
|     /** | ||||
|      * @var SourceInterface|SourceAttributInterface | ||||
|      */ | ||||
|     private $source; | ||||
|  | ||||
|     /** | ||||
|      * @var SourceInterface | ||||
|      */ | ||||
|     private $recieverSource; | ||||
|  | ||||
|     /** | ||||
|      * @var SecureSourceCheckerInterface | ||||
|      */ | ||||
|     private $securerSourceChecker; | ||||
|  | ||||
|     private function createSourceMock(): SourceInterface | ||||
|     { | ||||
|         return new class() extends AbstractSource implements SourceAttributInterface { | ||||
|             use SourceAttribut; | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     public function setUp(): void | ||||
|     { | ||||
|         $this->source = $this->createSourceMock(); | ||||
|         $this->recieverSource = $this->createSourceMock(); | ||||
|         $this->securerSourceChecker = new SecureSourceChecker($this->source); | ||||
|     } | ||||
|  | ||||
|     public function testFirstLevel(): void | ||||
|     { | ||||
|         $right = new Right(); | ||||
|         $right->setLayer(LayerType::SOURCE); | ||||
|         $right->setType(RightType::WRITE); | ||||
|         $right->setReciever($this->recieverSource); | ||||
|         $right->setSource($this->source); | ||||
|         $this->source->getLaw()->getRights()->add($right); | ||||
|         $requestedRight = clone $right; | ||||
|         $this->assertTrue($this->securerSourceChecker->hasPermission($requestedRight)); | ||||
|         $requestedRight->setType(RightType::READ); | ||||
|         $this->assertFalse($this->securerSourceChecker->hasPermission($requestedRight)); | ||||
|     } | ||||
|  | ||||
|     public function testSecondLevel(): void | ||||
|     { | ||||
|         $right = new Right(); | ||||
|         $right->setLayer(LayerType::SOURCE); | ||||
|         $right->setType(RightType::WRITE); | ||||
|         $right->setReciever($this->recieverSource); | ||||
|         $right->setSource($this->source); | ||||
|         $this->source->getLaw()->getRights()->add($right); | ||||
|         $attributSource = $this->createSourceMock(); | ||||
|         $childRight = clone $right; | ||||
|         $attributSource->getLaw()->getRights()->add($childRight); | ||||
|         $this->source->setSource($attributSource); | ||||
|         $requestedRight = clone $right; | ||||
|         $this->assertTrue($this->securerSourceChecker->hasPermission($requestedRight)); | ||||
|         $childRight->setType(RightType::READ); | ||||
|         $this->expectException(SourceAccessDenied::class); | ||||
|         $this->securerSourceChecker->hasPermission($requestedRight); | ||||
|     } | ||||
|  | ||||
|     public function testThirdLevel(): void | ||||
|     { | ||||
|         $right = new Right(); | ||||
|         $right->setLayer(LayerType::SOURCE); | ||||
|         $right->setType(RightType::WRITE); | ||||
|         $right->setReciever($this->recieverSource); | ||||
|         $right->setSource($this->source); | ||||
|         $this->source->getLaw()->getRights()->add($right); | ||||
|         $attribut1Source = $this->createSourceMock(); | ||||
|         $attribut1Source->getLaw()->getRights()->add($right); | ||||
|         $this->source->setSource($attribut1Source); | ||||
|         $childRight = clone $right; | ||||
|         $attribut2Source = $this->createSourceMock(); | ||||
|         $attribut2Source->getLaw()->getRights()->add($childRight); | ||||
|         $attribut1Source->setSource($attribut2Source); | ||||
|         $requestedRight = clone $right; | ||||
|         $this->assertTrue($this->securerSourceChecker->hasPermission($requestedRight)); | ||||
|         $childRight->setType(RightType::READ); | ||||
|         $this->expectException(SourceAccessDenied::class); | ||||
|         $this->securerSourceChecker->hasPermission($requestedRight); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user