mirror of
				https://github.com/kevinveenbirkenbach/infinito.git
				synced 2025-11-04 03:07:58 +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