diff --git a/VKAPI/Handlers/Users.php b/VKAPI/Handlers/Users.php index f48592b5..4c61985c 100644 --- a/VKAPI/Handlers/Users.php +++ b/VKAPI/Handlers/Users.php @@ -2,6 +2,7 @@ namespace openvk\VKAPI\Handlers; use openvk\Web\Models\Entities\User; use openvk\Web\Models\Repositories\Users as UsersRepo; +use openvk\Web\Models\Repositories\Blacklists; final class Users extends VKAPIRequestHandler { @@ -40,12 +41,15 @@ final class Users extends VKAPIRequestHandler "id" => $usr->getId(), "first_name" => $usr->getFirstName(), "last_name" => $usr->getLastName(), - "is_closed" => false, - "can_access_closed" => true, + "is_closed" => (new Blacklists)->isBanned($usr, $authuser), + "can_access_closed" => !(new Blacklists)->isBanned($usr, $authuser), + "blacklisted" => (new Blacklists)->isBanned($usr, $authuser), + "blacklisted_by_me" => (new Blacklists)->isBanned($authuser, $usr) ]; $flds = explode(',', $fields); + if (!(new Blacklists)->isBanned($usr, $authuser)) foreach($flds as $field) { switch($field) { case "verified": @@ -157,10 +161,11 @@ final class Users extends VKAPIRequestHandler } } - if($usr->getOnline()->timestamp() + 300 > time()) - $response[$i]->online = 1; - else - $response[$i]->online = 0; + if (!(new Blacklists)->isBanned($usr, $authuser)) + if($usr->getOnline()->timestamp() + 300 > time()) + $response[$i]->online = 1; + else + $response[$i]->online = 0; } } } @@ -176,8 +181,14 @@ final class Users extends VKAPIRequestHandler $users = new UsersRepo; $this->requireUser(); - - foreach($users->get($user_id)->getFollowers($offset, $count) as $follower) + + $authuser = $this->getUser(); + $target = $users->get($user_id); + + if ((new Blacklists)->isBanned($target, $authuser)) + $this->fail(15, "Access denied: User is blacklisted"); + + foreach($target->getFollowers($offset, $count) as $follower) $followers[] = $follower->getId(); $response = $followers; @@ -186,7 +197,7 @@ final class Users extends VKAPIRequestHandler $response = $this->get(implode(',', $followers), $fields, 0, $count); return (object) [ - "count" => $users->get($user_id)->getFollowersCount(), + "count" => $target->getFollowersCount(), "items" => $response ]; } diff --git a/Web/Models/Entities/BlacklistItem.php b/Web/Models/Entities/BlacklistItem.php new file mode 100644 index 00000000..fcc19452 --- /dev/null +++ b/Web/Models/Entities/BlacklistItem.php @@ -0,0 +1,31 @@ +getRecord()->index; + } + + function getAuthor(): ?User + { + return (new Users)->get($this->getRecord()->author); + } + + function getTarget(): ?User + { + return (new Users)->get($this->getRecord()->target); + } + + function getCreationDate(): DateTime + { + return new DateTime($this->getRecord()->created); + } +} \ No newline at end of file diff --git a/Web/Models/Entities/User.php b/Web/Models/Entities/User.php index 348631e4..ac7524a4 100644 --- a/Web/Models/Entities/User.php +++ b/Web/Models/Entities/User.php @@ -5,7 +5,7 @@ use openvk\Web\Themes\{Themepack, Themepacks}; use openvk\Web\Util\DateTime; use openvk\Web\Models\RowModel; use openvk\Web\Models\Entities\{Photo, Message, Correspondence, Gift}; -use openvk\Web\Models\Repositories\{Photos, Users, Clubs, Albums, Gifts, Notifications}; +use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Photos, Gifts, Notifications, Blacklists}; use openvk\Web\Models\Exceptions\InvalidUserNameException; use Nette\Database\Table\ActiveRow; use Chandler\Database\DatabaseConnection; @@ -440,6 +440,9 @@ class User extends RowModel return $permStatus === User::PRIVACY_EVERYONE; else if($user->getId() === $this->getId()) return true; + else if ((new Blacklists)->isBanned($this, $user)) { + return $user->isAdmin() && !OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["blacklists"]["applyToAdmins"]; + } switch($permStatus) { case User::PRIVACY_ONLY_FRIENDS: @@ -1094,6 +1097,11 @@ class User extends RowModel return (bool) $this->getRecord()->activated; } + function isAdmin(): bool + { + return $this->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL); + } + function getUnbanTime(): ?string { return !is_null($this->getRecord()->unblock_time) ? date('d.m.Y', $this->getRecord()->unblock_time) : NULL; diff --git a/Web/Models/Repositories/Blacklists.php b/Web/Models/Repositories/Blacklists.php new file mode 100644 index 00000000..66cce946 --- /dev/null +++ b/Web/Models/Repositories/Blacklists.php @@ -0,0 +1,42 @@ +context = DB::i()->getContext(); + $this->blacklists = $this->context->table("blacklists"); + } + + function getList(User $user, $page = 1): \Traversable + { + foreach($this->blacklists->where("author", $user->getId())->order("created DESC")->page($page, 10) as $blacklistItem) + yield new BlacklistItem($blacklistItem); + } + + function getByAuthorAndTarget(int $author, int $target): ?BlacklistItem + { + return new BlacklistItem($this->blacklists->where(["author" => $author, "target" => $target])->fetch()); + } + + function getCount(User $user): int + { + return sizeof($this->blacklists->where("author", $user->getId())->fetch()); + } + + function isBanned(User $author, User $target): bool + { + if (!$author || !$target) + return FALSE; + + return !is_null($this->getByAuthorAndTarget($author->getId(), $target->getId())); + } +} diff --git a/Web/Presenters/BlacklistPresenter.php b/Web/Presenters/BlacklistPresenter.php new file mode 100644 index 00000000..37ed36ec --- /dev/null +++ b/Web/Presenters/BlacklistPresenter.php @@ -0,0 +1,43 @@ +blacklists = $blacklists; + } + + function renderAddToBlacklist(): void + { + $this->willExecuteWriteAction(); + $this->assertUserLoggedIn(); + + $record = new BlacklistItem; + $target = (new Users)->get((int) $this->postParam("id")); + + $record->setAuthor($this->user->identity->getId()); + $record->setTarget($this->postParam("id")); + $record->setCreated(time()); + $record->save(); + + $this->flashFail("succ", tr("success"), tr("user_blacklisted", $target->getCanonicalName())); + } + + function renderRemoveFromBlacklist(): void + { + $this->willExecuteWriteAction(); + $this->assertUserLoggedIn(); + + $record = $this->blacklists->getByAuthorAndTarget($this->user->identity->getId(), $this->postParam("id")); + $name = $record->getTarget()->getCanonicalName(); + $record->delete(false); + + $this->flashFail("succ", tr("success"), tr("user_removed_from_the_blacklist", $name)); + } +} diff --git a/Web/Presenters/PhotosPresenter.php b/Web/Presenters/PhotosPresenter.php index 02d6ae46..a7a3ebb9 100644 --- a/Web/Presenters/PhotosPresenter.php +++ b/Web/Presenters/PhotosPresenter.php @@ -1,7 +1,7 @@ notFound(); if (!$user->getPrivacyPermission('photos.read', $this->user->identity ?? NULL)) $this->flashFail("err", tr("forbidden"), tr("forbidden_comment")); + $this->template->albums = $this->albums->getUserAlbums($user, $this->queryParam("p") ?? 1); $this->template->count = $this->albums->getUserAlbumsCount($user); $this->template->owner = $user; @@ -136,6 +137,11 @@ final class PhotosPresenter extends OpenVKPresenter if(!$album) $this->notFound(); if($album->getPrettyId() !== $owner . "_" . $id || $album->isDeleted()) $this->notFound(); + + if ((new Blacklists)->isBanned($album->getOwner(), $this->user->identity)) { + if (!$this->user->identity->isAdmin() OR $this->user->identity->isAdmin() AND OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["blacklists"]["applyToAdmins"]) + $this->flashFail("err", tr("forbidden"), tr("user_blacklisted_you")); + } if($owner > 0 /* bc we currently don't have perms for clubs */) { $ownerObject = (new Users)->get($owner); @@ -158,7 +164,12 @@ final class PhotosPresenter extends OpenVKPresenter { $photo = $this->photos->getByOwnerAndVID($ownerId, $photoId); if(!$photo || $photo->isDeleted()) $this->notFound(); - + + if ((new Blacklists)->isBanned($photo->getOwner(), $this->user->identity)) { + if (!$this->user->identity->isAdmin() OR $this->user->identity->isAdmin() AND OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["blacklists"]["applyToAdmins"]) + $this->flashFail("err", tr("forbidden"), tr("user_blacklisted_you")); + } + if(!is_null($this->queryParam("from"))) { if(preg_match("%^album([0-9]++)$%", $this->queryParam("from"), $matches) === 1) { $album = $this->albums->get((int) $matches[1]); diff --git a/Web/Presenters/UserPresenter.php b/Web/Presenters/UserPresenter.php index 9cfa3654..4eca5038 100644 --- a/Web/Presenters/UserPresenter.php +++ b/Web/Presenters/UserPresenter.php @@ -5,7 +5,7 @@ use openvk\Web\Util\Sms; use openvk\Web\Themes\Themepacks; use openvk\Web\Models\Entities\{Photo, Post, EmailChangeVerification}; use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification}; -use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Videos, Notes, Vouchers, EmailChangeVerifications}; +use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Videos, Notes, Vouchers, EmailChangeVerifications, Blacklists}; use openvk\Web\Models\Exceptions\InvalidUserNameException; use openvk\Web\Util\Validator; use Chandler\Security\Authenticator; @@ -15,20 +15,34 @@ use Nette\Database\UniqueConstraintViolationException; final class UserPresenter extends OpenVKPresenter { - private $users; public $deactivationTolerant = false; protected $presenterName = "user"; + private $users; + private $blacklists; - function __construct(Users $users) + function __construct(Users $users, Blacklists $blacklists) { $this->users = $users; - + $this->blacklists = $blacklists; + parent::__construct(); } function renderView(int $id): void { $user = $this->users->get($id); + + if ($this->user->identity) + if ($this->blacklists->isBanned($user, $this->user->identity)) { + if ($this->user->identity->isAdmin()) { + if (OPENVK_ROOT_CONF["openvk"]["preferences"]["security"]["blacklists"]["applyToAdmins"]) { + $this->flashFail("err", tr("forbidden"), tr("user_blacklisted_you")); + } + } else { + $this->flashFail("err", tr("forbidden"), tr("user_blacklisted_you")); + } + } + if(!$user || $user->isDeleted()) { if(!is_null($user) && $user->isDeactivated()) { $this->template->_template = "User/deactivated.xml"; @@ -45,8 +59,11 @@ final class UserPresenter extends OpenVKPresenter $this->template->videosCount = (new Videos)->getUserVideosCount($user); $this->template->notes = (new Notes)->getUserNotes($user, 1, 4); $this->template->notesCount = (new Notes)->getUserNotesCount($user); - + $this->template->blacklists = (new Blacklists); + $this->template->user = $user; + $this->template->isBlacklistedThem = $this->template->blacklists->isBanned($this->user->identity, $user); + $this->template->isBlacklistedByThem = $this->template->blacklists->isBanned($user, $this->user->identity); } } @@ -498,7 +515,7 @@ final class UserPresenter extends OpenVKPresenter $this->flash("succ", tr("changes_saved"), tr("changes_saved_comment")); } $this->template->mode = in_array($this->queryParam("act"), [ - "main", "security", "privacy", "finance", "finance.top-up", "interface" + "main", "security", "privacy", "finance", "finance.top-up", "interface", "blacklist" ]) ? $this->queryParam("act") : "main"; @@ -512,6 +529,11 @@ final class UserPresenter extends OpenVKPresenter $this->template->qrCodeType = substr($qrCode[0], 5); $this->template->qrCodeData = $qrCode[1]; } + + if($this->template->mode == "blacklist") { + $this->template->items = $this->blacklists->getList($user); + $this->template->count = $this->blacklists->getCount($user); + } $this->template->user = $user; $this->template->themes = Themepacks::i()->getThemeList(); diff --git a/Web/Presenters/VideosPresenter.php b/Web/Presenters/VideosPresenter.php index 4e4d484a..113e4e87 100644 --- a/Web/Presenters/VideosPresenter.php +++ b/Web/Presenters/VideosPresenter.php @@ -1,7 +1,7 @@ users->get($owner); if(!$user) $this->notFound(); - if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL)) + if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL)) { + if ((new Blacklists)->isBanned($user, $this->user->identity)) + $this->flashFail("err", tr("forbidden"), tr("user_blacklisted_you")); + $this->flashFail("err", tr("forbidden"), tr("forbidden_comment")); + } if($this->videos->getByOwnerAndVID($owner, $vId)->isDeleted()) $this->notFound(); diff --git a/Web/Presenters/templates/User/Settings.xml b/Web/Presenters/templates/User/Settings.xml index e61f900d..4c078efa 100644 --- a/Web/Presenters/templates/User/Settings.xml +++ b/Web/Presenters/templates/User/Settings.xml @@ -13,6 +13,7 @@ {var $isFinance = $mode === 'finance'} {var $isFinanceTU = $mode === 'finance.top-up'} {var $isInterface = $mode === 'interface'} +{var $isBlackList = $mode === 'blacklist'}
@@ -30,6 +31,9 @@ +
@@ -683,7 +687,49 @@ - + + {elseif $isBlackList} + {if $count < 1} + {include "../components/nothing.xml"} + {/if} +
+ + + + + + + + +
+ + Фотография пользователя + + + + + {$item->getTarget()->getCanonicalName()} + + + +
+ + + + + + + +
Дата добавления:{$item->getCreationDate()}
+
+
{/if}
diff --git a/Web/Presenters/templates/User/View.xml b/Web/Presenters/templates/User/View.xml index 1fa71026..9ab1a1eb 100644 --- a/Web/Presenters/templates/User/View.xml +++ b/Web/Presenters/templates/User/View.xml @@ -165,6 +165,19 @@ {/if} {/if} {tr("followers", $user->getFollowersCount())} + {if $isBlacklistedThem} + + {else} + + {/if}
{var $completeness = $user->getProfileCompletenessReport()} @@ -380,6 +393,11 @@
+
+ {admin_privacy_warning}: +
+ {_user_blacklisted_you} +
{strpos($alert, "@") === 0 ? tr(substr($alert, 1)) : $alert}
{var $thatIsThisUser = isset($thisUser) && $user->getId() == $thisUser->getId()}