From 4ac2958e905ded8afad7c483d1446e645e3cc287 Mon Sep 17 00:00:00 2001 From: mrilyew <99399973+mrilyew@users.noreply.github.com> Date: Wed, 11 Dec 2024 18:07:02 +0300 Subject: [PATCH] account.ban, account.unban, account.getBanned --- VKAPI/Handlers/Account.php | 68 ++++++++++++++++++++++++++++++++ Web/Models/Entities/User.php | 66 ++++++++++++++++++++++++++++--- install/sqls/00052-blacklist.sql | 1 + openvk-example.yml | 5 ++- 4 files changed, 132 insertions(+), 8 deletions(-) diff --git a/VKAPI/Handlers/Account.php b/VKAPI/Handlers/Account.php index dcdf18c0..c1f3ef23 100644 --- a/VKAPI/Handlers/Account.php +++ b/VKAPI/Handlers/Account.php @@ -228,4 +228,72 @@ final class Account extends VKAPIRequestHandler return (object) ['votes' => $this->getUser()->getCoins()]; } + + function ban(int $owner_id): int + { + $this->requireUser(); + $this->willExecuteWriteAction(); + + if($owner_id < 0) + return 1; + + if($owner_id == $this->getUser()->getId()) + $this->fail(15, "Access denied: cannot blacklist yourself"); + + $config_limit = OPENVK_ROOT_CONF['openvk']['preferences']['blacklists']['limit'] ?? 100; + $user_blocks = $this->getUser()->getBlacklistSize(); + if(($user_blocks + 1) > $config_limit) + $this->fail(-7856, "Blacklist limit exceeded"); + + $entity = get_entity_by_id($owner_id); + if(!$entity || $entity->isDeleted()) + return 0; + + if($entity->isBlacklistedBy($this->getUser())) + return 1; + + $this->getUser()->addToBlacklist($entity); + + return 1; + } + + function unban(int $owner_id): int + { + $this->requireUser(); + $this->willExecuteWriteAction(); + + if($owner_id < 0) + return 1; + + if($owner_id == $this->getUser()->getId()) + return 1; + + $entity = get_entity_by_id($owner_id); + if(!$entity || $entity->isDeleted()) + return 0; + + if(!$entity->isBlacklistedBy($this->getUser())) + return 1; + + $this->getUser()->removeFromBlacklist($entity); + + return 1; + } + + function getBanned(int $offset = 0, int $count = 100, string $fields = ""): object + { + $this->requireUser(); + + $result = (object)[ + 'count' => $this->getUser()->getBlacklistSize(), + 'items' => [], + ]; + $banned = $this->getUser()->getBlacklist($offset, $count); + foreach($banned as $ban) { + if(!$ban) continue; + $result->items[] = $ban->toVkApiStruct($this->getUser(), $fields); + } + + return $result; + } } diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index 45a54ecb..03b2fe5f 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -510,9 +510,6 @@ class User extends RowModel return $permStatus === User::PRIVACY_EVERYONE; else if($user->getId() === $this->getId()) return true; - else if ($this->isBlacklistedBy($user)) { - return $user->isAdmin() && !OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["blacklists"]["applyToAdmins"]; - } if($permission != "messages.write" && !$this->canBeViewedBy($user)) return false; @@ -1297,7 +1294,7 @@ class User extends RowModel return $this->getRecord()->profile_type; } - function canBeViewedBy(?User $user = NULL): bool + function canBeViewedBy(?User $user = NULL, bool $blacklist_check = true): bool { if(!is_null($user)) { if($this->getId() == $user->getId()) { @@ -1308,6 +1305,10 @@ class User extends RowModel return true; } + if($blacklist_check && ($this->isBlacklistedBy($user) || $user->isBlacklistedBy($this))) { + return false; + } + if($this->getProfileType() == 0) { return true; } else { @@ -1494,9 +1495,62 @@ class User extends RowModel return DatabaseConnection::i()->getContext()->table("ignored_sources")->where("owner", $this->getId())->count(); } - function isBlacklistedBy($user): bool + function isBlacklistedBy(?User $user = NULL): bool { - return false; + if(!$user) + return false; + + $ctx = DatabaseConnection::i()->getContext(); + $data = [ + "author" => $user->getId(), + "target" => $this->getRealId(), + ]; + + $sub = $ctx->table("blacklist_relations")->where($data); + return $sub->count() > 0; + } + + function addToBlacklist(?User $user) + { + DatabaseConnection::i()->getContext()->table("blacklist_relations")->insert([ + "author" => $this->getRealId(), + "target" => $user->getRealId(), + "created" => time(), + ]); + + return true; + } + + function removeFromBlacklist(?User $user): bool + { + DatabaseConnection::i()->getContext()->table("blacklist_relations")->where([ + "author" => $this->getRealId(), + "target" => $user->getRealId(), + ])->delete(); + + return true; + } + + function getBlacklist(int $offset = 0, int $limit = 10) + { + $sources = DatabaseConnection::i()->getContext()->table("blacklist_relations")->where("author", $this->getId())->limit($limit, $offset)->order('created ASC'); + $output_array = []; + + foreach($sources as $source) { + $entity_id = (int)$source->target ; + $entity = (new Users)->get($entity_id); + if(!$entity) + continue; + + $output_array[] = $entity; + } + + return $output_array; + } + + function getBlacklistSize() + { + return DatabaseConnection::i()->getContext()->table("blacklist_relations")->where("author", $this->getId())->count(); } use Traits\TBackDrops; diff --git a/install/sqls/00052-blacklist.sql b/install/sqls/00052-blacklist.sql index 252f8602..a665dc7c 100644 --- a/install/sqls/00052-blacklist.sql +++ b/install/sqls/00052-blacklist.sql @@ -5,3 +5,4 @@ CREATE TABLE `blacklist_relations` ( `created` BIGINT UNSIGNED NOT NULL, PRIMARY KEY (`index`) ) ENGINE = InnoDB; +ALTER TABLE `blacklist_relations` ADD INDEX(`author`, `target`); diff --git a/openvk-example.yml b/openvk-example.yml index b7674a2d..b64a589e 100644 --- a/openvk-example.yml +++ b/openvk-example.yml @@ -38,8 +38,9 @@ openvk: maxViolations: 50 maxViolationsAge: 120 autoban: true - blacklists: - applyToAdmins: true + blacklists: + limit: 100 + applyToAdmins: true registration: enable: true disablingReason: ""