id = $data['_id'] !== null ? (string)$data['_id'] : null; } elseif (array_key_exists('id', $data)) { $this->id = $data['id'] !== null ? (string)$data['id'] : null; } if (!array_key_exists('scope', $data)) { throw new \InvalidArgumentException('Firewall rules require an explicit scope.'); } $this->setScope((string)$data['scope']); if (array_key_exists('tenantId', $data)) { $this->tenantId = $data['tenantId'] !== null ? (string)$data['tenantId'] : null; } if (array_key_exists('type', $data)) { $this->type = $data['type'] !== null ? (string)$data['type'] : null; } if (array_key_exists('action', $data)) { $this->action = $data['action'] !== null ? (string)$data['action'] : null; } if (array_key_exists('value', $data)) { $this->value = $data['value'] !== null ? (string)$data['value'] : null; } if (array_key_exists('reason', $data)) { $this->reason = $data['reason'] !== null ? (string)$data['reason'] : null; } if (array_key_exists('createdBy', $data)) { $this->createdBy = $data['createdBy'] !== null ? (string)$data['createdBy'] : null; } if (array_key_exists('createdAt', $data)) { $this->createdAt = self::deserializeDate($data['createdAt']); } if (array_key_exists('expiresAt', $data)) { $this->expiresAt = self::deserializeDate($data['expiresAt']); } if (array_key_exists('enabled', $data)) { $this->enabled = (bool)$data['enabled']; } if (array_key_exists('metadata', $data)) { $this->metadata = $data['metadata'] !== null ? (array)$data['metadata'] : null; } return $this; } public function jsonSerialize(): array { return [ 'id' => $this->id, 'scope' => $this->scope, 'tenantId' => $this->tenantId, 'type' => $this->type, 'action' => $this->action, 'value' => $this->value, 'reason' => $this->reason, 'createdBy' => $this->createdBy, 'createdAt' => $this->createdAt?->format(\DateTimeInterface::ATOM), 'expiresAt' => $this->expiresAt?->format(\DateTimeInterface::ATOM), 'enabled' => $this->enabled, 'metadata' => $this->metadata, ]; } private static function deserializeDate(mixed $value): ?\DateTimeImmutable { if ($value === null) { return null; } if ($value instanceof \MongoDB\BSON\UTCDateTime) { return \DateTimeImmutable::createFromMutable($value->toDateTime()); } if ($value instanceof \DateTimeImmutable) { return $value; } if ($value instanceof \DateTimeInterface) { return \DateTimeImmutable::createFromInterface($value); } return new \DateTimeImmutable((string)$value); } /** * Check if this rule has expired */ public function isExpired(): bool { if ($this->expiresAt === null) { return false; } return $this->expiresAt < new \DateTimeImmutable(); } /** * Check if this rule is currently active (enabled and not expired) */ public function isActive(): bool { return $this->enabled && !$this->isExpired(); } // Getters and setters public function getId(): ?string { return $this->id; } public function setId(?string $id): self { $this->id = $id; return $this; } public function getTenantId(): ?string { return $this->tenantId; } public function getScope(): string { return $this->scope; } public function setScope(string $scope): self { if (!in_array($scope, [self::SCOPE_TENANT, self::SCOPE_SYSTEM], true)) { throw new \InvalidArgumentException("Invalid firewall rule scope: {$scope}"); } $this->scope = $scope; return $this; } public function isTenantScoped(): bool { return $this->scope === self::SCOPE_TENANT; } public function isSystemScoped(): bool { return $this->scope === self::SCOPE_SYSTEM; } public function assertValidScopeOwnership(): void { if ($this->isTenantScoped() && ($this->tenantId === null || $this->tenantId === '')) { throw new \InvalidArgumentException('Tenant firewall rules require a tenant ID.'); } if ($this->isSystemScoped() && $this->tenantId !== null) { throw new \InvalidArgumentException('System firewall rules cannot have a tenant ID.'); } } public function setTenantId(?string $tenantId): self { $this->tenantId = $tenantId; return $this; } public function getType(): ?string { return $this->type; } public function setType(?string $type): self { $this->type = $type; return $this; } public function getAction(): ?string { return $this->action; } public function setAction(?string $action): self { $this->action = $action; return $this; } public function getValue(): ?string { return $this->value; } public function setValue(?string $value): self { $this->value = $value; return $this; } public function getReason(): ?string { return $this->reason; } public function setReason(?string $reason): self { $this->reason = $reason; return $this; } public function getCreatedBy(): ?string { return $this->createdBy; } public function setCreatedBy(?string $createdBy): self { $this->createdBy = $createdBy; return $this; } public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } public function setCreatedAt(?\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } public function getExpiresAt(): ?\DateTimeImmutable { return $this->expiresAt; } public function setExpiresAt(?\DateTimeImmutable $expiresAt): self { $this->expiresAt = $expiresAt; return $this; } public function isEnabled(): bool { return $this->enabled; } public function setEnabled(bool $enabled): self { $this->enabled = $enabled; return $this; } public function getMetadata(): ?array { return $this->metadata; } public function setMetadata(?array $metadata): self { $this->metadata = $metadata; return $this; } }