mirror of
https://github.com/kevinveenbirkenbach/infinito.git
synced 2025-01-09 22:17:26 +01:00
implemented checking of source source attributs
This commit is contained in:
parent
878eae62db
commit
1ee710e608
@ -4,9 +4,9 @@ namespace App\Domain\SecureLoadManagement;
|
|||||||
|
|
||||||
use App\Entity\Source\SourceInterface;
|
use App\Entity\Source\SourceInterface;
|
||||||
use App\Entity\Meta\RightInterface;
|
use App\Entity\Meta\RightInterface;
|
||||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
|
||||||
use Doctrine\Common\Persistence\ObjectRepository;
|
use Doctrine\Common\Persistence\ObjectRepository;
|
||||||
use App\Domain\SecureManagement\SecureSourceChecker;
|
use App\Domain\SecureManagement\SecureSourceChecker;
|
||||||
|
use App\Exception\SourceAccessDenied;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kevinfrantz
|
* @author kevinfrantz
|
||||||
@ -71,6 +71,6 @@ final class SecureSourceLoader implements SecureSourceLoaderInterface
|
|||||||
if ($secureSourceChecker->hasPermission($requestedRight)) {
|
if ($secureSourceChecker->hasPermission($requestedRight)) {
|
||||||
return $source;
|
return $source;
|
||||||
}
|
}
|
||||||
throw new AccessDeniedHttpException();
|
throw new SourceAccessDenied();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ namespace App\Domain\SecureManagement;
|
|||||||
use App\Entity\Meta\RightInterface;
|
use App\Entity\Meta\RightInterface;
|
||||||
use App\Entity\Source\SourceInterface;
|
use App\Entity\Source\SourceInterface;
|
||||||
use App\Domain\LawManagement\LawPermissionCheckerService;
|
use App\Domain\LawManagement\LawPermissionCheckerService;
|
||||||
|
use App\Exception\SourceAccessDenied;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kevinfrantz
|
* @author kevinfrantz
|
||||||
@ -24,10 +25,77 @@ final class SecureSourceChecker implements SecureSourceCheckerInterface
|
|||||||
$this->source = $source;
|
$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
|
public function hasPermission(RightInterface $requestedRight): bool
|
||||||
{
|
{
|
||||||
$law = new LawPermissionCheckerService($this->source->getLaw());
|
$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;
|
namespace App\Domain\SecureManagement;
|
||||||
|
|
||||||
use App\Entity\Meta\RightInterface;
|
use App\Entity\Meta\RightInterface;
|
||||||
|
use App\Exception\SourceAccessDenied;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kevinfrantz
|
* @author kevinfrantz
|
||||||
@ -10,6 +11,8 @@ use App\Entity\Meta\RightInterface;
|
|||||||
interface SecureSourceCheckerInterface
|
interface SecureSourceCheckerInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* @throws SourceAccessDenied
|
||||||
|
*
|
||||||
* @param RightInterface $right
|
* @param RightInterface $right
|
||||||
*
|
*
|
||||||
* @return bool
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user