getRecord()->ip); } function getDiscoveryDate(): DateTime { return new DateTime($this->getRecord()->first_seen); } function isBanned(): bool { return (bool) $this->getRecord()->banned; } function ban(): void { $this->stateChanges("banned", true); $this->save(); } function pardon(): void { $this->stateChanges("banned", false); $this->save(); } function clear(): void { $this->stateChanges("rate_limit_counter_start", 0); $this->stateChanges("rate_limit_counter", 0); $this->stateChanges("rate_limit_violation_counter_start", 0); $this->stateChanges("rate_limit_violation_counter", 0); $this->save(); } function rateLimit(int $actionComplexity = 1): int { $counterSessionStart = $this->getRecord()->rate_limit_counter_start; $vCounterSessionStart = $this->getRecord()->rate_limit_violation_counter_start; $aCounter = $this->getRecord()->rate_limit_counter; $vCounter = $this->getRecord()->rate_limit_violation_counter; $config = (object) OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]; try { if((time() - $config->time) > $counterSessionStart) { $counterSessionStart = time(); $aCounter = $actionComplexity; return static::RL_RESET; } if(($aCounter + $actionComplexity) <= $config->actions) { $aCounter += $actionComplexity; return static::RL_CANEXEC; } if((time() - $config->maxViolationsAge) > $vCounterSessionStart) { $vCounterSessionStart = time(); $vCounter = 1; return static::RL_VIOLATION; } $vCounter += 1; if($vCounter >= $config->maxViolations) { $this->stateChanges("banned", true); return static::RL_BANNED; } return static::RL_VIOLATION; } finally { $this->stateChanges("rate_limit_counter_start", $counterSessionStart); $this->stateChanges("rate_limit_counter", $aCounter); $this->stateChanges("rate_limit_violation_counter_start", $vCounterSessionStart); $this->stateChanges("rate_limit_violation_counter", $vCounter); $this->save(); } } function setIp(string $ip): void { $ip = inet_pton($ip); if(!$ip) throw new \UnexpectedValueException("Malformed IP address"); $this->stateChanges("ip", $ip); } function save(): void { if(is_null($this->getRecord())) $this->stateChanges("first_seen", time()); parent::save(); } }