feat: make event state constructor-only and immutable
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
@@ -9,7 +9,7 @@ use KTXF\Event\Event;
|
||||
/**
|
||||
* Security-specific event for authentication and access control events
|
||||
*/
|
||||
class SecurityEvent extends Event
|
||||
final class SecurityEvent extends Event
|
||||
{
|
||||
// Event names
|
||||
public const AUTH_SUCCESS = 'security.auth.success';
|
||||
@@ -35,15 +35,6 @@ class SecurityEvent extends Event
|
||||
public const FIREWALL_RULE_REMOVED = 'security.firewall.rule.removed';
|
||||
public const FIREWALL_SETTINGS_UPDATED = 'security.firewall.settings.updated';
|
||||
|
||||
private ?string $ipAddress = null;
|
||||
private ?string $deviceFingerprint = null;
|
||||
private ?string $userAgent = null;
|
||||
private ?string $requestPath = null;
|
||||
private ?string $requestMethod = null;
|
||||
private ?string $userId = null;
|
||||
private ?string $reason = null;
|
||||
private int $severity = self::SEVERITY_INFO;
|
||||
|
||||
// Severity levels
|
||||
public const SEVERITY_DEBUG = 0;
|
||||
public const SEVERITY_INFO = 1;
|
||||
@@ -51,11 +42,25 @@ class SecurityEvent extends Event
|
||||
public const SEVERITY_ERROR = 3;
|
||||
public const SEVERITY_CRITICAL = 4;
|
||||
|
||||
public function __construct(string $name, array $data = [])
|
||||
{
|
||||
parent::__construct($name, $data);
|
||||
private readonly int $severity;
|
||||
|
||||
$this->severity = self::getSeverityForEvent($name);
|
||||
public function __construct(
|
||||
string $name,
|
||||
array $data = [],
|
||||
?string $tenantId = null,
|
||||
?string $identityId = null,
|
||||
private readonly ?string $ipAddress = null,
|
||||
private readonly ?string $deviceFingerprint = null,
|
||||
private readonly ?string $userAgent = null,
|
||||
private readonly ?string $requestPath = null,
|
||||
private readonly ?string $requestMethod = null,
|
||||
private readonly ?string $userId = null,
|
||||
private readonly ?string $reason = null,
|
||||
?int $severity = null,
|
||||
) {
|
||||
parent::__construct($name, $data, $tenantId, $identityId);
|
||||
|
||||
$this->severity = $severity ?? self::getSeverityForEvent($name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,13 +70,30 @@ class SecurityEvent extends Event
|
||||
string $name,
|
||||
?string $ipAddress = null,
|
||||
?string $deviceFingerprint = null,
|
||||
array $data = []
|
||||
array $data = [],
|
||||
?string $tenantId = null,
|
||||
?string $identityId = null,
|
||||
?string $userAgent = null,
|
||||
?string $requestPath = null,
|
||||
?string $requestMethod = null,
|
||||
?string $userId = null,
|
||||
?string $reason = null,
|
||||
?int $severity = null,
|
||||
): self {
|
||||
$event = new self($name, $data);
|
||||
$event->ipAddress = $ipAddress;
|
||||
$event->deviceFingerprint = $deviceFingerprint;
|
||||
|
||||
return $event;
|
||||
return new self(
|
||||
$name,
|
||||
$data,
|
||||
$tenantId,
|
||||
$identityId,
|
||||
$ipAddress,
|
||||
$deviceFingerprint,
|
||||
$userAgent,
|
||||
$requestPath,
|
||||
$requestMethod,
|
||||
$userId,
|
||||
$reason,
|
||||
$severity,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,15 +103,26 @@ class SecurityEvent extends Event
|
||||
string $ipAddress,
|
||||
?string $deviceFingerprint = null,
|
||||
?string $userId = null,
|
||||
?string $reason = null
|
||||
?string $reason = null,
|
||||
?string $tenantId = null,
|
||||
?string $identityId = null,
|
||||
?string $userAgent = null,
|
||||
?string $requestPath = null,
|
||||
?string $requestMethod = null,
|
||||
): self {
|
||||
$event = self::create(self::AUTH_FAILURE, $ipAddress, $deviceFingerprint, [
|
||||
'userId' => $userId,
|
||||
'reason' => $reason,
|
||||
]);
|
||||
$event->userId = $userId;
|
||||
$event->reason = $reason;
|
||||
return $event;
|
||||
return self::create(
|
||||
self::AUTH_FAILURE,
|
||||
$ipAddress,
|
||||
$deviceFingerprint,
|
||||
['userId' => $userId, 'reason' => $reason],
|
||||
$tenantId,
|
||||
$identityId,
|
||||
$userAgent,
|
||||
$requestPath,
|
||||
$requestMethod,
|
||||
$userId,
|
||||
$reason,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,13 +131,17 @@ class SecurityEvent extends Event
|
||||
public static function authSuccess(
|
||||
string $ipAddress,
|
||||
?string $deviceFingerprint = null,
|
||||
string $userId = null
|
||||
?string $userId = null,
|
||||
?string $tenantId = null,
|
||||
): self {
|
||||
$event = self::create(self::AUTH_SUCCESS, $ipAddress, $deviceFingerprint, [
|
||||
'userId' => $userId,
|
||||
]);
|
||||
$event->userId = $userId;
|
||||
return $event;
|
||||
return self::create(
|
||||
self::AUTH_SUCCESS,
|
||||
$ipAddress,
|
||||
$deviceFingerprint,
|
||||
['userId' => $userId],
|
||||
tenantId: $tenantId,
|
||||
userId: $userId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,18 +150,16 @@ class SecurityEvent extends Event
|
||||
public static function bruteForceDetected(
|
||||
string $ipAddress,
|
||||
int $failureCount,
|
||||
int $windowSeconds
|
||||
int $windowSeconds,
|
||||
?string $tenantId = null,
|
||||
): self {
|
||||
$event = self::create(self::BRUTE_FORCE_DETECTED, $ipAddress, null, [
|
||||
'failureCount' => $failureCount,
|
||||
'windowSeconds' => $windowSeconds,
|
||||
]);
|
||||
$event->reason = sprintf(
|
||||
'%d failed attempts in %d seconds',
|
||||
$failureCount,
|
||||
$windowSeconds
|
||||
return self::create(
|
||||
self::BRUTE_FORCE_DETECTED,
|
||||
$ipAddress,
|
||||
data: ['failureCount' => $failureCount, 'windowSeconds' => $windowSeconds],
|
||||
tenantId: $tenantId,
|
||||
reason: sprintf('%d failed attempts in %d seconds', $failureCount, $windowSeconds),
|
||||
);
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,20 +169,21 @@ class SecurityEvent extends Event
|
||||
string $ipAddress,
|
||||
int $requestCount,
|
||||
int $windowSeconds,
|
||||
?string $endpoint = null
|
||||
?string $endpoint = null,
|
||||
?string $tenantId = null,
|
||||
): self {
|
||||
$event = self::create(self::RATE_LIMIT_EXCEEDED, $ipAddress, null, [
|
||||
'requestCount' => $requestCount,
|
||||
'windowSeconds' => $windowSeconds,
|
||||
'endpoint' => $endpoint,
|
||||
]);
|
||||
$event->requestPath = $endpoint;
|
||||
$event->reason = sprintf(
|
||||
'%d requests in %d seconds',
|
||||
$requestCount,
|
||||
$windowSeconds
|
||||
return self::create(
|
||||
self::RATE_LIMIT_EXCEEDED,
|
||||
$ipAddress,
|
||||
data: [
|
||||
'requestCount' => $requestCount,
|
||||
'windowSeconds' => $windowSeconds,
|
||||
'endpoint' => $endpoint,
|
||||
],
|
||||
tenantId: $tenantId,
|
||||
requestPath: $endpoint,
|
||||
reason: sprintf('%d requests in %d seconds', $requestCount, $windowSeconds),
|
||||
);
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,15 +194,19 @@ class SecurityEvent extends Event
|
||||
?string $deviceFingerprint = null,
|
||||
?string $ruleId = null,
|
||||
?string $ruleScope = null,
|
||||
?string $reason = null
|
||||
?string $reason = null,
|
||||
?string $tenantId = null,
|
||||
?string $identityId = null,
|
||||
): self {
|
||||
$event = self::create(self::ACCESS_DENIED, $ipAddress, $deviceFingerprint, [
|
||||
'ruleId' => $ruleId,
|
||||
'ruleScope' => $ruleScope,
|
||||
'reason' => $reason,
|
||||
]);
|
||||
$event->reason = $reason;
|
||||
return $event;
|
||||
return self::create(
|
||||
self::ACCESS_DENIED,
|
||||
$ipAddress,
|
||||
$deviceFingerprint,
|
||||
['ruleId' => $ruleId, 'ruleScope' => $ruleScope, 'reason' => $reason],
|
||||
$tenantId,
|
||||
$identityId,
|
||||
reason: $reason,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,86 +242,39 @@ class SecurityEvent extends Event
|
||||
return $this->ipAddress;
|
||||
}
|
||||
|
||||
public function setIpAddress(?string $ipAddress): self
|
||||
{
|
||||
$this->ipAddress = $ipAddress;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDeviceFingerprint(): ?string
|
||||
{
|
||||
return $this->deviceFingerprint;
|
||||
}
|
||||
|
||||
public function setDeviceFingerprint(?string $deviceFingerprint): self
|
||||
{
|
||||
$this->deviceFingerprint = $deviceFingerprint;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserAgent(): ?string
|
||||
{
|
||||
return $this->userAgent;
|
||||
}
|
||||
|
||||
public function setUserAgent(?string $userAgent): self
|
||||
{
|
||||
$this->userAgent = $userAgent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRequestPath(): ?string
|
||||
{
|
||||
return $this->requestPath;
|
||||
}
|
||||
|
||||
public function setRequestPath(?string $requestPath): self
|
||||
{
|
||||
$this->requestPath = $requestPath;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRequestMethod(): ?string
|
||||
{
|
||||
return $this->requestMethod;
|
||||
}
|
||||
|
||||
public function setRequestMethod(?string $requestMethod): self
|
||||
{
|
||||
$this->requestMethod = $requestMethod;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserId(): ?string
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function setUserId(?string $userId): self
|
||||
{
|
||||
$this->userId = $userId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReason(): ?string
|
||||
{
|
||||
return $this->reason;
|
||||
}
|
||||
|
||||
public function setReason(?string $reason): self
|
||||
{
|
||||
$this->reason = $reason;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSeverity(): int
|
||||
{
|
||||
return $this->severity;
|
||||
}
|
||||
|
||||
public function setSeverity(int $severity): self
|
||||
{
|
||||
$this->severity = $severity;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user