Restrict interaction with orphan visits when API key has that role

This commit is contained in:
Alejandro Celaya
2023-05-31 09:11:20 +02:00
parent 12da04ef37
commit eaba5edf7f
11 changed files with 78 additions and 20 deletions

View File

@@ -15,18 +15,22 @@ use Shlinkio\Shlink\Core\Visit\Paginator\Adapter\OrphanVisitsPaginatorAdapter;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsCountFiltering;
use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
class OrphanVisitsPaginatorAdapterTest extends TestCase
{
private OrphanVisitsPaginatorAdapter $adapter;
private MockObject & VisitRepositoryInterface $repo;
private VisitsParams $params;
private ApiKey $apiKey;
protected function setUp(): void
{
$this->repo = $this->createMock(VisitRepositoryInterface::class);
$this->params = VisitsParams::fromRawData([]);
$this->adapter = new OrphanVisitsPaginatorAdapter($this->repo, $this->params);
$this->apiKey = ApiKey::create();
$this->adapter = new OrphanVisitsPaginatorAdapter($this->repo, $this->params, $this->apiKey);
}
#[Test]
@@ -34,7 +38,7 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase
{
$expectedCount = 5;
$this->repo->expects($this->once())->method('countOrphanVisits')->with(
new VisitsCountFiltering($this->params->dateRange),
new VisitsCountFiltering($this->params->dateRange, apiKey: $this->apiKey),
)->willReturn($expectedCount);
$result = $this->adapter->getNbResults();
@@ -51,9 +55,13 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase
{
$visitor = Visitor::emptyInstance();
$list = [Visit::forRegularNotFound($visitor), Visit::forInvalidShortUrl($visitor)];
$this->repo->expects($this->once())->method('findOrphanVisits')->with(
new VisitsListFiltering($this->params->dateRange, $this->params->excludeBots, null, $limit, $offset),
)->willReturn($list);
$this->repo->expects($this->once())->method('findOrphanVisits')->with(new VisitsListFiltering(
$this->params->dateRange,
$this->params->excludeBots,
$this->apiKey,
$limit,
$offset,
))->willReturn($list);
$result = $this->adapter->getSlice($offset, $limit);

View File

@@ -10,6 +10,9 @@ use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Core\Visit\Repository\VisitDeleterRepositoryInterface;
use Shlinkio\Shlink\Core\Visit\VisitsDeleter;
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
class VisitsDeleterTest extends TestCase
{
@@ -38,4 +41,16 @@ class VisitsDeleterTest extends TestCase
yield '5000' => [5000];
yield '0' => [0];
}
#[Test]
public function returnsNoDeletedVisitsForApiKeyWithNoPermission(): void
{
$this->repo->expects($this->never())->method('deleteOrphanVisits');
$result = $this->visitsDeleter->deleteOrphanVisits(
ApiKey::fromMeta(ApiKeyMeta::withRoles(RoleDefinition::forOrphanVisitsExcluded())),
);
self::assertEquals(0, $result->affectedItems);
}
}

View File

@@ -50,13 +50,14 @@ class VisitsStatsHelperTest extends TestCase
}
#[Test, DataProvider('provideCounts')]
public function returnsExpectedVisitsStats(int $expectedCount): void
public function returnsExpectedVisitsStats(int $expectedCount, ?ApiKey $apiKey): void
{
$repo = $this->createMock(VisitRepository::class);
$callCount = 0;
$repo->expects($this->exactly(2))->method('countNonOrphanVisits')->willReturnCallback(
function (VisitsCountFiltering $options) use ($expectedCount, &$callCount) {
function (VisitsCountFiltering $options) use ($expectedCount, $apiKey, &$callCount) {
Assert::assertEquals($callCount !== 0, $options->excludeBots);
Assert::assertEquals($apiKey, $options->apiKey);
$callCount++;
return $expectedCount * 3;
@@ -67,14 +68,17 @@ class VisitsStatsHelperTest extends TestCase
)->willReturn($expectedCount);
$this->em->expects($this->once())->method('getRepository')->with(Visit::class)->willReturn($repo);
$stats = $this->helper->getVisitsStats();
$stats = $this->helper->getVisitsStats($apiKey);
self::assertEquals(new VisitsStats($expectedCount * 3, $expectedCount), $stats);
}
public static function provideCounts(): iterable
{
return map(range(0, 50, 5), fn (int $value) => [$value]);
return [
...map(range(0, 50, 5), fn (int $value) => [$value, null]),
...map(range(0, 18, 3), fn (int $value) => [$value, ApiKey::create()]),
];
}
#[Test, DataProvider('provideAdminApiKeys')]