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
|
@ -37,14 +37,6 @@ trait TSubscribable
|
||||||
|
|
||||||
if (!($sub->fetch())) {
|
if (!($sub->fetch())) {
|
||||||
$ctx->table("subscriptions")->insert($data);
|
$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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1044,8 +1044,6 @@ class User extends RowModel
|
||||||
"anonymous" => $anonymous,
|
"anonymous" => $anonymous,
|
||||||
"sent" => time(),
|
"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
|
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();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,8 +83,6 @@ final class GroupPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
$club->toggleSubscription($this->user->identity);
|
$club->toggleSubscription($this->user->identity);
|
||||||
|
|
||||||
\openvk\Web\Util\EventRateLimiter::i()->writeEvent("groups.create", $this->user->identity, $club);
|
|
||||||
|
|
||||||
$this->redirect("/club" . $club->getId());
|
$this->redirect("/club" . $club->getId());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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) {
|
if ($should_be_suggested) {
|
||||||
$this->redirect("/club" . $wallOwner->getId() . "/suggested");
|
$this->redirect("/club" . $wallOwner->getId() . "/suggested");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,23 +8,6 @@ use openvk\Web\Models\Entities\User;
|
||||||
use openvk\Web\Models\RowModel;
|
use openvk\Web\Models\RowModel;
|
||||||
use Chandler\Patterns\TSimpleSingleton;
|
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
|
class EventRateLimiter
|
||||||
{
|
{
|
||||||
use TSimpleSingleton;
|
use TSimpleSingleton;
|
||||||
|
@ -35,58 +18,105 @@ class EventRateLimiter
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->config = OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["eventsLimit"];
|
$this->config = OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["rateLimits"]["eventsLimit"];
|
||||||
|
|
||||||
$this->availableFields = array_keys($this->config['list']);
|
$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
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->config['ignoreForAdmins'] && $user->isAdmin()) {
|
if ($isIgnoreForAdmins && $user->isAdmin()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$limitForThisEvent = $this->config['list'][$event_type];
|
$limitForThatEvent = $eventsList[$event_type];
|
||||||
$compareTime = time() - $this->config['restrictionTime'];
|
$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();
|
|
||||||
|
|
||||||
return $count > $limitForThisEvent;
|
if ($is_restrict_over) {
|
||||||
|
$user->resetEvents($eventsList, $restrictionTime);
|
||||||
|
|
||||||
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = [
|
$ev_data = $initiator->recieveEventsData($eventsList);
|
||||||
'initiatorId' => $initiator->getId(),
|
$values = $ev_data['counters'];
|
||||||
'initiatorIp' => null,
|
$i = 0;
|
||||||
'receiverId' => null,
|
|
||||||
'eventType' => $event_type,
|
|
||||||
'eventTime' => time()
|
|
||||||
];
|
|
||||||
|
|
||||||
if ($reciever) {
|
$compared = [];
|
||||||
$data['receiverId'] = $reciever->getRealId();
|
|
||||||
|
foreach ($eventsList as $name => $value) {
|
||||||
|
$compared[$name] = $values[$i];
|
||||||
|
$i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$newEvent = new UserEvent($data);
|
$compared[$event_type] += 1;
|
||||||
$newEvent->write($e);
|
|
||||||
|
bdump($compared);
|
||||||
|
$initiator->stateEvents($compared);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue