mirror of
https://github.com/openvk/openvk
synced 2025-07-01 13:38:15 +03:00
draft
This commit is contained in:
parent
bdac64a4ae
commit
5898b9a455
5 changed files with 110 additions and 56 deletions
|
@ -38,14 +38,6 @@ trait TSubscribable
|
|||
if (!($sub->fetch())) {
|
||||
$ctx->table("subscriptions")->insert($data);
|
||||
|
||||
# todo change
|
||||
|
||||
if (str_contains(static::class, "Club")) {
|
||||
\openvk\Web\Util\EventRateLimiter::i()->writeEvent("groups.sub", $user, $this);
|
||||
} else {
|
||||
\openvk\Web\Util\EventRateLimiter::i()->writeEvent("friends.outgoing_sub", $user, $this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1044,8 +1044,6 @@ class User extends RowModel
|
|||
"anonymous" => $anonymous,
|
||||
"sent" => time(),
|
||||
]);
|
||||
|
||||
\openvk\Web\Util\EventRateLimiter::i()->writeEvent("gifts.send", $sender, $this);
|
||||
}
|
||||
|
||||
public function ban(string $reason, bool $deleteSubscriptions = true, $unban_time = null, ?int $initiator = null): void
|
||||
|
@ -1741,4 +1739,42 @@ class User extends RowModel
|
|||
{
|
||||
return DatabaseConnection::i()->getContext()->table("blacklist_relations")->where("author", $this->getId())->count();
|
||||
}
|
||||
|
||||
public function recieveEventsData(array $list): array
|
||||
{
|
||||
$ev_str = $this->getRecord()->events_counters;
|
||||
$values = [];
|
||||
|
||||
if (!$ev_str) {
|
||||
for ($i = 0; $i < sizeof(array_keys($list)); $i++) {
|
||||
$values[] = 0;
|
||||
}
|
||||
} else {
|
||||
$keys = array_keys($list);
|
||||
$values = unpack("S*", base64_decode($ev_str));
|
||||
}
|
||||
|
||||
return [
|
||||
'counters' => $values,
|
||||
'refresh_time' => $this->getRecord()->events_refresh_time,
|
||||
];
|
||||
}
|
||||
|
||||
public function stateEvents(array $list): void
|
||||
{
|
||||
$this->stateChanges("events_counters", base64_encode(pack("S*", array_values($list))));
|
||||
}
|
||||
|
||||
public function resetEvents(array $list, int $restriction_length)
|
||||
{
|
||||
$values = [];
|
||||
|
||||
for ($i = 0; $i < sizeof(array_keys($list)); $i++) {
|
||||
$values[] = 0;
|
||||
}
|
||||
|
||||
$this->stateEvents($values);
|
||||
$this->stateChanges("events_refresh_time", $restriction_length + time());
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,8 +84,6 @@ final class GroupPresenter extends OpenVKPresenter
|
|||
|
||||
$club->toggleSubscription($this->user->identity);
|
||||
|
||||
\openvk\Web\Util\EventRateLimiter::i()->writeEvent("groups.create", $this->user->identity, $club);
|
||||
|
||||
$this->redirect("/club" . $club->getId());
|
||||
} else {
|
||||
$this->flashFail("err", tr("error"), tr("error_no_group_name"));
|
||||
|
|
|
@ -432,8 +432,6 @@ final class WallPresenter extends OpenVKPresenter
|
|||
}
|
||||
}
|
||||
|
||||
\openvk\Web\Util\EventRateLimiter::i()->writeEvent("wall.post", $this->user->identity, $wallOwner);
|
||||
|
||||
if ($should_be_suggested) {
|
||||
$this->redirect("/club" . $wallOwner->getId() . "/suggested");
|
||||
} else {
|
||||
|
|
|
@ -8,23 +8,6 @@ use openvk\Web\Models\Entities\User;
|
|||
use openvk\Web\Models\RowModel;
|
||||
use Chandler\Patterns\TSimpleSingleton;
|
||||
|
||||
class UserEvent
|
||||
{
|
||||
private $data;
|
||||
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function write($edb): bool
|
||||
{
|
||||
$edb->getConnection()->query("INSERT INTO `user-events` VALUES (?, ?, ?, ?, ?)", ...array_values($this->data));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class EventRateLimiter
|
||||
{
|
||||
use TSimpleSingleton;
|
||||
|
@ -35,58 +18,105 @@ class EventRateLimiter
|
|||
public function __construct()
|
||||
{
|
||||
$this->config = OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["eventsLimit"];
|
||||
|
||||
$this->availableFields = array_keys($this->config['list']);
|
||||
}
|
||||
|
||||
/*
|
||||
Checks count of actions for last x seconds, returns true if limit has exceed
|
||||
Checks count of actions for last hours
|
||||
|
||||
x is OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["eventsLimit"]["restrictionTime"]
|
||||
Uses config path OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["eventsLimit"]
|
||||
|
||||
Returns:
|
||||
|
||||
true — limit has exceed and the action must be restricted
|
||||
|
||||
false — the action can be performed
|
||||
*/
|
||||
public function tryToLimit(?User $user, string $event_type, bool $distinct = true): bool
|
||||
{
|
||||
if (!$this->config['enable']) {
|
||||
$isEnabled = $this->config['enable'];
|
||||
$isIgnoreForAdmins = $this->config['ignoreForAdmins'];
|
||||
$restrictionTime = $this->config['restrictionTime'];
|
||||
$eventsList = $this->config['list'];
|
||||
|
||||
if (!$isEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->config['ignoreForAdmins'] && $user->isAdmin()) {
|
||||
if ($isIgnoreForAdmins && $user->isAdmin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$limitForThisEvent = $this->config['list'][$event_type];
|
||||
$compareTime = time() - $this->config['restrictionTime'];
|
||||
$limitForThatEvent = $eventsList[$event_type];
|
||||
$stat = $this->getEvent($event_type, $user);
|
||||
bdump($stat);
|
||||
|
||||
$query = "SELECT COUNT(".($distinct ? "DISTINCT(`receiverId`)" : "*").") as `cnt` FROM `user-events` WHERE `initiatorId` = ? AND `eventType` = ? AND `eventTime` > ?";
|
||||
$is_restrict_over = $stat["refresh_time"] < time() - $restrictionTime;
|
||||
|
||||
$count = $result->fetch()->cnt;
|
||||
#bdump($count); exit();
|
||||
if ($is_restrict_over) {
|
||||
$user->resetEvents($eventsList, $restrictionTime);
|
||||
|
||||
return $count > $limitForThisEvent;
|
||||
return false;
|
||||
}
|
||||
|
||||
$is = $stat["compared"] > $limitForThatEvent;
|
||||
|
||||
if ($is === false) {
|
||||
$this->incrementEvent($event_type, $user);
|
||||
}
|
||||
|
||||
return $is;
|
||||
}
|
||||
|
||||
public function getEvent(string $event_type, User $by_user): array
|
||||
{
|
||||
$ev_data = $by_user->recieveEventsData($this->config['list']);
|
||||
$values = $ev_data['counters'];
|
||||
$i = 0;
|
||||
|
||||
$compared = [];
|
||||
bdump($values);
|
||||
|
||||
foreach ($this->config['list'] as $name => $value) {
|
||||
bdump($value);
|
||||
$compared[$name] = $values[$i];
|
||||
$i += 1;
|
||||
}
|
||||
|
||||
return [
|
||||
"compared" => $compared,
|
||||
"refresh_time" => $ev_data["refresh_time"]
|
||||
];
|
||||
}
|
||||
|
||||
/*
|
||||
Writes new event to `openvk-eventdb`.`user-events`
|
||||
Updates counter for user
|
||||
*/
|
||||
public function writeEvent(string $event_type, User $initiator, ?RowModel $reciever = null): bool
|
||||
public function incrementEvent(string $event_type, User $initiator): bool
|
||||
{
|
||||
if (!$this->config['enable']) {
|
||||
$isEnabled = $this->config['enable'];
|
||||
$eventsList = OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["eventsLimit"];
|
||||
|
||||
if (!$isEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'initiatorId' => $initiator->getId(),
|
||||
'initiatorIp' => null,
|
||||
'receiverId' => null,
|
||||
'eventType' => $event_type,
|
||||
'eventTime' => time()
|
||||
];
|
||||
$ev_data = $initiator->recieveEventsData($eventsList);
|
||||
$values = $ev_data['counters'];
|
||||
$i = 0;
|
||||
|
||||
if ($reciever) {
|
||||
$data['receiverId'] = $reciever->getRealId();
|
||||
$compared = [];
|
||||
|
||||
foreach ($eventsList as $name => $value) {
|
||||
$compared[$name] = $values[$i];
|
||||
$i += 1;
|
||||
}
|
||||
|
||||
$newEvent = new UserEvent($data);
|
||||
$newEvent->write($e);
|
||||
$compared[$event_type] += 1;
|
||||
|
||||
bdump($compared);
|
||||
$initiator->stateEvents($compared);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue