6700ff145d
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
117 lines
5.1 KiB
PHP
117 lines
5.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KTXT\Unit\Controllers;
|
|
|
|
use KTXC\Context\IdentityContextInterface;
|
|
use KTXC\Context\TenantContextInterface;
|
|
use KTXC\Controllers\FirewallController;
|
|
use KTXC\Service\FirewallRuleCache;
|
|
use KTXC\Service\FirewallRuleManager;
|
|
use KTXC\Service\FirewallStatusService;
|
|
use KTXC\Service\FirewallLogService;
|
|
use KTXC\Service\SystemFirewallLogService;
|
|
use KTXC\Service\SystemFirewallRuleService;
|
|
use KTXC\Service\SystemFirewallStatusService;
|
|
use KTXC\Service\TenantFirewallLogService;
|
|
use KTXC\Service\TenantFirewallRuleService;
|
|
use KTXC\Service\TenantFirewallStatusService;
|
|
use KTXC\Stores\FirewallStore;
|
|
use KTXF\Event\EventDispatcherInterface;
|
|
use KTXF\Routing\Attributes\AuthenticatedRoute;
|
|
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
|
|
use PHPUnit\Framework\Attributes\TestDox;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
#[AllowMockObjectsWithoutExpectations]
|
|
final class FirewallControllerTest extends TestCase
|
|
{
|
|
private FirewallStore $store;
|
|
private FirewallController $controller;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->store = $this->createMock(FirewallStore::class);
|
|
$tenant = $this->createMock(TenantContextInterface::class);
|
|
$tenant->method('requireIdentifier')->willReturn('tenant-a');
|
|
$identity = $this->createMock(IdentityContextInterface::class);
|
|
$identity->method('hasPermission')->willReturn(true);
|
|
$manager = new FirewallRuleManager(
|
|
$this->store,
|
|
new FirewallRuleCache($this->store),
|
|
$this->createStub(EventDispatcherInterface::class)
|
|
);
|
|
$this->controller = new FirewallController(
|
|
new TenantFirewallRuleService($manager, $tenant, $identity),
|
|
new SystemFirewallRuleService($manager, $identity),
|
|
new TenantFirewallLogService(new FirewallLogService($this->store), $tenant, $identity),
|
|
new SystemFirewallLogService(new FirewallLogService($this->store), $identity),
|
|
new TenantFirewallStatusService(new FirewallStatusService($this->store), $tenant, $identity),
|
|
new SystemFirewallStatusService(new FirewallStatusService($this->store), $identity)
|
|
);
|
|
}
|
|
|
|
#[TestDox('Tenant rule endpoint returns bounded paginated results')]
|
|
public function testTenantRules(): void
|
|
{
|
|
$this->store->expects(self::once())
|
|
->method('queryRules')
|
|
->with('tenant', 'tenant-a', 'active', null, null, 25, 10)
|
|
->willReturn(['items' => [], 'total' => 0, 'limit' => 25, 'offset' => 10]);
|
|
|
|
$response = $this->controller->tenantRules(limit: '25', offset: '10');
|
|
$data = json_decode($response->getContent(), true, flags: JSON_THROW_ON_ERROR);
|
|
|
|
self::assertSame(200, $response->getStatusCode());
|
|
self::assertSame(25, $data['limit']);
|
|
self::assertSame(10, $data['offset']);
|
|
}
|
|
|
|
#[TestDox('Rule endpoints reject malformed and excessive pagination')]
|
|
public function testPaginationValidation(): void
|
|
{
|
|
$this->store->expects(self::never())->method('queryRules');
|
|
|
|
self::assertSame(400, $this->controller->tenantRules(limit: 'invalid')->getStatusCode());
|
|
self::assertSame(400, $this->controller->systemRules(limit: '101')->getStatusCode());
|
|
}
|
|
|
|
#[TestDox('Metric endpoints return scoped counts and stable validation errors')]
|
|
public function testMetrics(): void
|
|
{
|
|
$this->store->method('countBlockedRequests')->willReturn(4);
|
|
|
|
$response = $this->controller->tenantMetrics();
|
|
$data = json_decode($response->getContent(), true, flags: JSON_THROW_ON_ERROR);
|
|
|
|
self::assertSame(4, $data['blockedRequests']);
|
|
self::assertSame(400, $this->controller->systemMetrics(since: 'not-a-date')->getStatusCode());
|
|
}
|
|
|
|
#[TestDox('Every rule endpoint declares its scope-specific read permission')]
|
|
public function testRoutePermissions(): void
|
|
{
|
|
$expected = [
|
|
'tenantRules' => TenantFirewallRuleService::PERMISSION_READ,
|
|
'tenantRule' => TenantFirewallRuleService::PERMISSION_READ,
|
|
'effectivePolicy' => TenantFirewallRuleService::PERMISSION_READ,
|
|
'systemRules' => SystemFirewallRuleService::PERMISSION_READ,
|
|
'systemRule' => SystemFirewallRuleService::PERMISSION_READ,
|
|
'tenantLogs' => TenantFirewallLogService::PERMISSION_READ,
|
|
'systemLogs' => SystemFirewallLogService::PERMISSION_READ,
|
|
'tenantMetrics' => TenantFirewallLogService::PERMISSION_READ,
|
|
'tenantConfiguration' => TenantFirewallStatusService::PERMISSION_SETTINGS_READ,
|
|
'systemMetrics' => SystemFirewallLogService::PERMISSION_READ,
|
|
'maintenanceStatus' => SystemFirewallStatusService::PERMISSION_MAINTENANCE_READ,
|
|
];
|
|
|
|
foreach ($expected as $method => $permission) {
|
|
$attributes = (new \ReflectionMethod(FirewallController::class, $method))
|
|
->getAttributes(AuthenticatedRoute::class);
|
|
self::assertCount(1, $attributes);
|
|
self::assertSame([$permission], $attributes[0]->newInstance()->permissions);
|
|
}
|
|
}
|
|
}
|