feat(firewall): complete operational reliability phase

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-07-30 23:39:37 -04:00
parent 90d847ffae
commit 4ee91a7918
15 changed files with 574 additions and 22 deletions
+37 -3
View File
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace KTXC\Stores;
use KTXC\Db\DataStore;
use KTXC\Db\ObjectId;
use KTXC\Db\UTCDateTime;
use KTXC\Models\Firewall\FirewallRuleObject;
use KTXC\Models\Firewall\FirewallLogObject;
@@ -17,6 +18,7 @@ class FirewallStore
protected const RULES_COLLECTION = 'firewall_rules';
protected const LOGS_COLLECTION = 'firewall_logs';
protected const BRUTE_FORCE_CLAIMS_COLLECTION = 'firewall_brute_force_claims';
protected const MAINTENANCE_COLLECTION = 'firewall_maintenance';
public function __construct(
protected readonly DataStore $dataStore
@@ -180,7 +182,7 @@ class FirewallStore
*/
public function fetchRule(string $id): ?FirewallRuleObject
{
$entry = $this->dataStore->selectCollection(self::RULES_COLLECTION)->findOne(['_id' => $id]);
$entry = $this->dataStore->selectCollection(self::RULES_COLLECTION)->findOne(self::ruleIdFilter($id));
if (!$entry) {
return null;
}
@@ -259,7 +261,7 @@ class FirewallStore
unset($data['id']);
$this->dataStore->selectCollection(self::RULES_COLLECTION)->updateOne(
['_id' => $id],
self::ruleIdFilter($id),
['$set' => $data]
);
return $rule;
@@ -274,7 +276,7 @@ class FirewallStore
if (!$id) {
return;
}
$this->dataStore->selectCollection(self::RULES_COLLECTION)->deleteOne(['_id' => $id]);
$this->dataStore->selectCollection(self::RULES_COLLECTION)->deleteOne(self::ruleIdFilter($id));
}
/**
@@ -476,6 +478,33 @@ class FirewallStore
return $result->getDeletedCount();
}
public function recordMaintenanceStatus(
\DateTimeImmutable $startedAt,
\DateTimeImmutable $completedAt,
string $status,
array $result,
?string $error = null
): void {
$this->dataStore->selectCollection(self::MAINTENANCE_COLLECTION)->updateOne(
['_id' => 'cleanup'],
['$set' => [
'startedAt' => self::bsonDate($startedAt),
'completedAt' => self::bsonDate($completedAt),
'status' => $status,
'result' => $result,
'error' => $error,
]],
['upsert' => true]
);
}
public function maintenanceStatus(): ?array
{
return $this->dataStore
->selectCollection(self::MAINTENANCE_COLLECTION)
->findOne(['_id' => 'cleanup']);
}
private static function ruleDocument(FirewallRuleObject $rule): array
{
$data = $rule->jsonSerialize();
@@ -502,4 +531,9 @@ class FirewallStore
{
return UTCDateTime::fromDateTime($date);
}
private static function ruleIdFilter(string $id): array
{
return ['_id' => ObjectId::isValid($id) ? ObjectId::fromString($id) : $id];
}
}