refactor(firewall): separate enforcement from rule management

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-07-30 22:35:24 -04:00
parent 266b364c93
commit da81f1ddf1
14 changed files with 814 additions and 436 deletions
@@ -4,10 +4,11 @@ declare(strict_types=1);
namespace KTXT\Integration\Stores;
use KTXC\Context\TenantContextInterface;
use KTXC\Db\DataStore;
use KTXC\Models\Firewall\FirewallRuleObject;
use KTXC\Service\FirewallService;
use KTXC\Service\FirewallRuleCache;
use KTXC\Service\FirewallRuleManager;
use KTXC\Service\FirewallRuleScope;
use KTXC\Stores\FirewallStore;
use KTXF\Event\EventDispatcherInterface;
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
@@ -93,13 +94,16 @@ class FirewallStoreTest extends TestCase
FirewallRuleObject::ACTION_BLOCK
));
$tenantContext = $this->createMock(TenantContextInterface::class);
$tenantContext->method('identifier')->willReturn('tenant-a');
$tenantContext->method('configuration')->willReturn(null);
$events = $this->createMock(EventDispatcherInterface::class);
$service = new FirewallService($this->store, $tenantContext, $events);
$replacement = $service->blockIp('203.0.113.10', durationSeconds: 300);
$cache = new FirewallRuleCache($this->store);
$manager = new FirewallRuleManager($this->store, $cache, $events);
$replacement = $manager->blockIp(
FirewallRuleScope::tenant('tenant-a'),
'203.0.113.10',
null,
null,
300
);
self::assertFalse($replacement->isExpired());
self::assertNotSame($expired->getId(), $replacement->getId());
@@ -146,6 +150,28 @@ class FirewallStoreTest extends TestCase
));
}
#[TestDox('System rule listings exclude tenant, disabled, and expired rules')]
public function testSystemListing(): void
{
$this->store->depositRule($this->rule('system', FirewallRuleObject::SCOPE_SYSTEM));
$this->store->depositRule(
$this->rule('disabled', FirewallRuleObject::SCOPE_SYSTEM)->setEnabled(false)
);
$this->store->depositRule(
$this->rule('expired', FirewallRuleObject::SCOPE_SYSTEM)
->setExpiresAt(new \DateTimeImmutable('-1 minute'))
);
$this->store->depositRule(
$this->rule('tenant', FirewallRuleObject::SCOPE_TENANT, 'tenant-a')
);
$rules = $this->store->listSystemRules();
self::assertCount(1, $rules);
self::assertSame('system', $rules[0]->getReason());
self::assertTrue($rules[0]->isSystemScoped());
}
private function rule(
string $reason,
string $scope,