Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(privacy): add blacklist #695

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions VKAPI/Handlers/Users.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -40,12 +41,15 @@ function get(string $user_ids = "0", string $fields = "", int $offset = 0, int $
"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),
n1rwana marked this conversation as resolved.
Show resolved Hide resolved
"blacklisted" => (new Blacklists)->isBanned($usr, $authuser),
"blacklisted_by_me" => (new Blacklists)->isBanned($authuser, $usr)
n1rwana marked this conversation as resolved.
Show resolved Hide resolved
];

$flds = explode(',', $fields);

if (!(new Blacklists)->isBanned($usr, $authuser))
foreach($flds as $field) {
switch($field) {
case "verified":
Expand Down Expand Up @@ -157,10 +161,11 @@ function get(string $user_ids = "0", string $fields = "", int $offset = 0, int $
}
}

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;
}
}
}
Expand All @@ -176,8 +181,14 @@ function getFollowers(int $user_id, string $fields = "", int $offset = 0, int $c
$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;
Expand All @@ -186,7 +197,7 @@ function getFollowers(int $user_id, string $fields = "", int $offset = 0, int $c
$response = $this->get(implode(',', $followers), $fields, 0, $count);

return (object) [
"count" => $users->get($user_id)->getFollowersCount(),
"count" => $target->getFollowersCount(),
"items" => $response
];
}
Expand Down
31 changes: 31 additions & 0 deletions Web/Models/Entities/BlacklistItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\RowModel;
use openvk\Web\Util\DateTime;
use openvk\Web\Models\Entities\{User, Manager};
use openvk\Web\Models\Repositories\{Users, Clubs};

class BlacklistItem extends RowModel
{
protected $tableName = "blacklists";

function getId(): int
{
return $this->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);
}
}
10 changes: 9 additions & 1 deletion Web/Models/Entities/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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;
Expand Down Expand Up @@ -440,6 +440,9 @@ function getPrivacyPermission(string $permission, ?User $user = NULL): bool
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:
Expand Down Expand Up @@ -1094,6 +1097,11 @@ function isActivated(): bool
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;
Expand Down
42 changes: 42 additions & 0 deletions Web/Models/Repositories/Blacklists.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use openvk\Web\Models\Entities\{User, BlacklistItem};
use openvk\Web\Models\Repositories\{Clubs, Users};
use Nette\Database\Table\ActiveRow;
use Chandler\Database\DatabaseConnection as DB;

class Blacklists
{
private $context;
private $blacklists;

function __construct()
{
$this->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()));
}
}
43 changes: 43 additions & 0 deletions Web/Presenters/BlacklistPresenter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php declare(strict_types=1);
namespace openvk\Web\Presenters;
use openvk\Web\Models\Entities\{BlacklistItem};
use openvk\Web\Models\Repositories\{Blacklists, Users};
use Chandler\Database\DatabaseConnection as DB;

final class BlacklistPresenter extends OpenVKPresenter
{
private $blacklists;

function __construct(Blacklists $blacklists)
{
$this->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));
}
}
15 changes: 13 additions & 2 deletions Web/Presenters/PhotosPresenter.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php declare(strict_types=1);
namespace openvk\Web\Presenters;
use openvk\Web\Models\Entities\{Club, Photo, Album};
use openvk\Web\Models\Repositories\{Photos, Albums, Users, Clubs};
use openvk\Web\Models\Repositories\{Photos, Albums, Users, Clubs, Blacklists};
use Nette\InvalidStateException as ISE;

final class PhotosPresenter extends OpenVKPresenter
Expand All @@ -27,6 +27,7 @@ function renderAlbumList(int $owner): void
if(!$user) $this->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;
Expand Down Expand Up @@ -136,6 +137,11 @@ function renderAlbum(int $owner, int $id): void
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);
Expand All @@ -158,7 +164,12 @@ function renderPhoto(int $ownerId, int $photoId): void
{
$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]);
Expand Down
34 changes: 28 additions & 6 deletions Web/Presenters/UserPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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;
Expand All @@ -15,20 +15,34 @@

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";
Expand All @@ -45,8 +59,11 @@ function renderView(int $id): void
$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);
}
}

Expand Down Expand Up @@ -498,7 +515,7 @@ function renderSettings(): void
$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";

Expand All @@ -512,6 +529,11 @@ function renderSettings(): void
$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();
Expand Down
8 changes: 6 additions & 2 deletions Web/Presenters/VideosPresenter.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php declare(strict_types=1);
namespace openvk\Web\Presenters;
use openvk\Web\Models\Entities\Video;
use openvk\Web\Models\Repositories\{Users, Videos};
use openvk\Web\Models\Repositories\{Users, Videos, Blacklists};
use Nette\InvalidStateException as ISE;

final class VideosPresenter extends OpenVKPresenter
Expand Down Expand Up @@ -40,8 +40,12 @@ function renderView(int $owner, int $vId): void
{
$user = $this->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();

Expand Down
Loading