mirror of
https://github.com/openvk/openvk
synced 2025-07-01 05:28:17 +03:00
Better reports
This commit is contained in:
parent
8fb393ca9b
commit
43ae3d28a7
33 changed files with 729 additions and 144 deletions
|
@ -306,11 +306,14 @@ class Application extends RowModel
|
|||
function delete(bool $softly = true): void
|
||||
{
|
||||
if($softly)
|
||||
throw new \UnexpectedValueException("Can't delete apps softly.");
|
||||
throw new \UnexpectedValueException("Can't delete apps softly."); // why
|
||||
|
||||
$cx = DatabaseConnection::i()->getContext();
|
||||
$cx->table("app_users")->where("app", $this->getId())->delete();
|
||||
|
||||
parent::delete(false);
|
||||
}
|
||||
|
||||
function getPublicationTime(): string
|
||||
{ return tr("recently"); }
|
||||
}
|
66
Web/Models/Entities/Ban.php
Normal file
66
Web/Models/Entities/Ban.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Entities;
|
||||
use openvk\Web\Models\RowModel;
|
||||
use openvk\Web\Util\DateTime;
|
||||
use openvk\Web\Models\Repositories\{Users};
|
||||
use Nette\Database\Table\ActiveRow;
|
||||
|
||||
class Ban extends RowModel
|
||||
{
|
||||
protected $tableName = "bans";
|
||||
|
||||
function getId(): int
|
||||
{
|
||||
return $this->getRecord()->id;
|
||||
}
|
||||
|
||||
function getReason(): ?string
|
||||
{
|
||||
return $this->getRecord()->reason;
|
||||
}
|
||||
|
||||
function getUser(): ?User
|
||||
{
|
||||
return (new Users)->get($this->getRecord()->user);
|
||||
}
|
||||
|
||||
function getInitiator(): ?User
|
||||
{
|
||||
return (new Users)->get($this->getRecord()->initiator);
|
||||
}
|
||||
|
||||
function getStartTime(): int
|
||||
{
|
||||
return $this->getRecord()->iat;
|
||||
}
|
||||
|
||||
function getEndTime(): int
|
||||
{
|
||||
return $this->getRecord()->exp;
|
||||
}
|
||||
|
||||
function getTime(): int
|
||||
{
|
||||
return $this->getRecord()->time;
|
||||
}
|
||||
|
||||
function isPermanent(): bool
|
||||
{
|
||||
return $this->getEndTime() === 0;
|
||||
}
|
||||
|
||||
function isRemovedManually(): bool
|
||||
{
|
||||
return (bool) $this->getRecord()->removed_manually;
|
||||
}
|
||||
|
||||
function isOver(): bool
|
||||
{
|
||||
return $this->isRemovedManually();
|
||||
}
|
||||
|
||||
function whoRemoved(): ?User
|
||||
{
|
||||
return (new Users)->get($this->getRecord()->removed_by);
|
||||
}
|
||||
}
|
|
@ -34,7 +34,8 @@ abstract class Postable extends Attachable
|
|||
$oid = (int) $this->getRecord()->owner;
|
||||
if(!$real && $this->isAnonymous())
|
||||
$oid = OPENVK_ROOT_CONF["openvk"]["preferences"]["wall"]["anonymousPosting"]["account"];
|
||||
|
||||
|
||||
$oid = abs($oid);
|
||||
if($oid > 0)
|
||||
return (new Users)->get($oid);
|
||||
else
|
||||
|
|
|
@ -4,7 +4,7 @@ use openvk\Web\Util\DateTime;
|
|||
use Nette\Database\Table\ActiveRow;
|
||||
use openvk\Web\Models\RowModel;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
use openvk\Web\Models\Repositories\{Users, Posts, Photos, Videos, Clubs};
|
||||
use openvk\Web\Models\Repositories\{Applications, Comments, Notes, Users, Posts, Photos, Videos, Clubs};
|
||||
use Chandler\Database\DatabaseConnection as DB;
|
||||
use Nette\InvalidStateException as ISE;
|
||||
use Nette\Database\Table\Selection;
|
||||
|
@ -53,22 +53,25 @@ class Report extends RowModel
|
|||
return $this->getRecord()->user_id;
|
||||
}
|
||||
|
||||
function getUser(): user
|
||||
function getUser(): User
|
||||
{
|
||||
return (new Users)->get($this->getRecord()->user_id);
|
||||
return (new Users)->get((int) $this->getRecord()->user_id);
|
||||
}
|
||||
|
||||
function getContentId(): int
|
||||
{
|
||||
return $this->getRecord()->target_id;
|
||||
return (int) $this->getRecord()->target_id;
|
||||
}
|
||||
|
||||
function getContentObject()
|
||||
{
|
||||
if ($this->getContentType() == "post") return (new Posts)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "photo") return (new Photos)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "video") return (new Videos)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "group") return (new Clubs)->get($this->getContentId());
|
||||
if ($this->getContentType() == "post") return (new Posts)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "photo") return (new Photos)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "video") return (new Videos)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "group") return (new Clubs)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "comment") return (new Comments)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "note") return (new Notes)->get($this->getContentId());
|
||||
else if ($this->getContentType() == "app") return (new Applications)->get($this->getContentId());
|
||||
else return null;
|
||||
}
|
||||
|
||||
|
@ -77,16 +80,17 @@ class Report extends RowModel
|
|||
return (new Posts)->get($this->getContentId())->getOwner();
|
||||
}
|
||||
|
||||
// TODO: Localize that
|
||||
function banUser()
|
||||
function banUser($initiator)
|
||||
{
|
||||
$this->getAuthor()->ban("Banned by report. Ask Technical support for ban reason");
|
||||
$this->getAuthor()->ban("**content-" . $this->getContentType() . "-" . $this->getContentId() . "**", false, time() + $this->getAuthor()->getNewBanTime(), $initiator);
|
||||
}
|
||||
|
||||
function deleteContent()
|
||||
{
|
||||
$this->getAuthor()->adminNotify("Ваш контент, который вы опубликовали " . $this->getContentObject()->getPublicationTime() . " был удалён модераторами инстанса. За повторные или серьёзные нарушения вас могут заблокировать.");
|
||||
$this->getContentObject()->delete();
|
||||
$pubTime = $this->getContentObject()->getPublicationTime();
|
||||
$name = $this->getContentObject()->getName();
|
||||
$this->getAuthor()->adminNotify("Ваш контент, который вы опубликовали $pubTime ($name) был удалён модераторами инстанса. За повторные или серьёзные нарушения вас могут заблокировать.");
|
||||
$this->getContentObject()->delete($this->getContentType() !== "app");
|
||||
$this->setDeleted(1);
|
||||
$this->save();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,18 @@ 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\{Users, Clubs, Albums, Gifts, Notifications};
|
||||
use openvk\Web\Models\Repositories\{Applications,
|
||||
Bans,
|
||||
Comments,
|
||||
Notes,
|
||||
Posts,
|
||||
Users,
|
||||
Clubs,
|
||||
Albums,
|
||||
Gifts,
|
||||
Notifications,
|
||||
Videos,
|
||||
Photos};
|
||||
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
||||
use Nette\Database\Table\ActiveRow;
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
|
@ -236,11 +247,55 @@ class User extends RowModel
|
|||
return $this->getRecord()->alert;
|
||||
}
|
||||
|
||||
function getBanReason(): ?string
|
||||
function getTextForContentBan(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case "post": return "за размещение от Вашего лица таких <b>записей</b>:";
|
||||
case "photo": return "за размещение от Вашего лица таких <b>фотографий</b>:";
|
||||
case "video": return "за размещение от Вашего лица таких <b>видеозаписей</b>:";
|
||||
case "group": return "за подозрительное вступление от Вашего лица <b>в группу:</b>";
|
||||
case "comment": return "за размещение от Вашего лица таких <b>комментариев</b>:";
|
||||
case "note": return "за размещение от Вашего лица таких <b>заметок</b>:";
|
||||
case "app": return "за создание от Вашего имени <b>подозрительных приложений</b>.";
|
||||
default: return "за размещение от Вашего лица такого <b>контента</b>:";
|
||||
}
|
||||
}
|
||||
|
||||
function getRawBanReason(): ?string
|
||||
{
|
||||
return $this->getRecord()->block_reason;
|
||||
}
|
||||
|
||||
function getBanReason(?string $for = null)
|
||||
{
|
||||
$ban = (new Bans)->get((int) $this->getRecord()->block_reason);
|
||||
if (!$ban || $ban->isOver()) return null;
|
||||
|
||||
$reason = $ban->getReason();
|
||||
|
||||
preg_match('/\*\*content-(post|photo|video|group|comment|note|app)-(\d+)\*\*$/', $reason, $matches);
|
||||
if (sizeof($matches) === 3) {
|
||||
if ($for !== "banned") {
|
||||
$reason = "Подозрительная активность";
|
||||
} else {
|
||||
$content_type = $matches[1]; $content_id = (int) $matches[2];
|
||||
$reason = [$this->getTextForContentBan($content_type), $content_type];
|
||||
switch ($content_type) {
|
||||
case "post": $reason[] = (new Posts)->get($content_id); break;
|
||||
case "photo": $reason[] = (new Photos)->get($content_id); break;
|
||||
case "video": $reason[] = (new Videos)->get($content_id); break;
|
||||
case "group": $reason[] = (new Clubs)->get($content_id); break;
|
||||
case "comment": $reason[] = (new Comments)->get($content_id); break;
|
||||
case "note": $reason[] = (new Notes)->get($content_id); break;
|
||||
case "app": $reason[] = (new Applications)->get($content_id); break;
|
||||
default: $reason[] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $reason;
|
||||
}
|
||||
|
||||
function getBanInSupportReason(): ?string
|
||||
{
|
||||
return $this->getRecord()->block_in_support_reason;
|
||||
|
@ -768,7 +823,7 @@ class User extends RowModel
|
|||
]);
|
||||
}
|
||||
|
||||
function ban(string $reason, bool $deleteSubscriptions = true, ?int $unban_time = NULL): void
|
||||
function ban(string $reason, bool $deleteSubscriptions = true, $unban_time = NULL, ?int $initiator = NULL): void
|
||||
{
|
||||
if($deleteSubscriptions) {
|
||||
$subs = DatabaseConnection::i()->getContext()->table("subscriptions");
|
||||
|
@ -781,8 +836,18 @@ class User extends RowModel
|
|||
$subs->delete();
|
||||
}
|
||||
|
||||
$this->setBlock_Reason($reason);
|
||||
$this->setUnblock_time($unban_time);
|
||||
$iat = time();
|
||||
$ban = new Ban;
|
||||
$ban->setUser($this->getId());
|
||||
$ban->setReason($reason);
|
||||
$ban->setInitiator($initiator);
|
||||
$ban->setIat($iat);
|
||||
$ban->setExp($unban_time !== "permanent" ? $unban_time : 0);
|
||||
$ban->setTime($unban_time === "permanent" ? 0 : ($unban_time ? ($unban_time - $iat) : 0));
|
||||
$ban->save();
|
||||
|
||||
$this->setBlock_Reason($ban->getId());
|
||||
// $this->setUnblock_time($unban_time);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
|
@ -956,7 +1021,7 @@ class User extends RowModel
|
|||
|
||||
function adminNotify(string $message): bool
|
||||
{
|
||||
$admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
|
||||
$admId = (int) OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
|
||||
if(!$admId)
|
||||
return false;
|
||||
else if(is_null($admin = (new Users)->get($admId)))
|
||||
|
@ -1021,7 +1086,10 @@ class User extends RowModel
|
|||
|
||||
function getUnbanTime(): ?string
|
||||
{
|
||||
return !is_null($this->getRecord()->unblock_time) ? date('d.m.Y', $this->getRecord()->unblock_time) : NULL;
|
||||
$ban = (new Bans)->get((int) $this->getRecord()->block_reason);
|
||||
if (!$ban || $ban->isOver() || $ban->isPermanent()) return null;
|
||||
|
||||
return date('d.m.Y', $ban->getEndTime());
|
||||
}
|
||||
|
||||
function canUnbanThemself(): bool
|
||||
|
@ -1029,10 +1097,40 @@ class User extends RowModel
|
|||
if (!$this->isBanned())
|
||||
return false;
|
||||
|
||||
if ($this->getRecord()->unblock_time > time() || $this->getRecord()->unblock_time == 0)
|
||||
return false;
|
||||
$ban = (new Bans)->get((int) $this->getRecord()->block_reason);
|
||||
if (!$ban || $ban->isOver() || $ban->isPermanent()) return false;
|
||||
|
||||
return true;
|
||||
return $ban->getEndTime() <= time() && !$ban->isPermanent();
|
||||
}
|
||||
|
||||
function getNewBanTime()
|
||||
{
|
||||
$bans = iterator_to_array((new Bans)->getByUser($this->getid()));
|
||||
if (!$bans || count($bans) === 0)
|
||||
return 0;
|
||||
|
||||
$last_ban = end($bans);
|
||||
if (!$last_ban) return 0;
|
||||
|
||||
if ($last_ban->isPermanent()) return "permanent";
|
||||
|
||||
$values = [0, 3600, 7200, 86400, 172800, 604800, 1209600, 3024000, 9072000];
|
||||
$response = 0;
|
||||
$i = 0;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$i++;
|
||||
if ($last_ban->getTime() === 0 && $value === 0) continue;
|
||||
if ($last_ban->getTime() < $value) {
|
||||
$response = $value;
|
||||
break;
|
||||
} else if ($last_ban->getTime() >= $value) {
|
||||
if ($i < count($values)) continue;
|
||||
$response = "permanent";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
use Traits\TSubscribable;
|
||||
|
|
33
Web/Models/Repositories/Bans.php
Normal file
33
Web/Models/Repositories/Bans.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Models\Repositories;
|
||||
use Chandler\Database\DatabaseConnection as DB;
|
||||
use Nette\Database\Table\{ActiveRow, Selection};
|
||||
use openvk\Web\Models\Entities\Ban;
|
||||
|
||||
class Bans
|
||||
{
|
||||
private $context;
|
||||
private $bans;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->context = DB::i()->getContext();
|
||||
$this->bans = $this->context->table("bans");
|
||||
}
|
||||
|
||||
function toBan(?ActiveRow $ar): ?Ban
|
||||
{
|
||||
return is_null($ar) ? NULL : new Ban($ar);
|
||||
}
|
||||
|
||||
function get(int $id): ?Ban
|
||||
{
|
||||
return $this->toBan($this->bans->get($id));
|
||||
}
|
||||
|
||||
function getByUser(int $user_id): \Traversable
|
||||
{
|
||||
foreach ($this->bans->where("user", $user_id) as $ban)
|
||||
yield new Ban($ban);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Presenters;
|
||||
use openvk\Web\Models\Entities\{Voucher, Gift, GiftCategory, User, BannedLink};
|
||||
use openvk\Web\Models\Repositories\{Users, Clubs, Vouchers, Gifts, BannedLinks};
|
||||
use openvk\Web\Models\Repositories\{Bans, Photos, Posts, Users, Clubs, Videos, Vouchers, Gifts, BannedLinks};
|
||||
use Chandler\Database\DatabaseConnection;
|
||||
|
||||
final class AdminPresenter extends OpenVKPresenter
|
||||
|
@ -343,13 +343,19 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
{
|
||||
$this->assertNoCSRF();
|
||||
|
||||
if (str_contains($this->queryParam("reason"), "*"))
|
||||
exit(json_encode([ "error" => "Incorrect reason" ]));
|
||||
|
||||
$unban_time = strtotime($this->queryParam("date")) ?: NULL;
|
||||
|
||||
$user = $this->users->get($id);
|
||||
if(!$user)
|
||||
exit(json_encode([ "error" => "User does not exist" ]));
|
||||
|
||||
$user->ban($this->queryParam("reason"), true, $unban_time);
|
||||
|
||||
if ($this->queryParam("incr"))
|
||||
$unban_time = time() + $user->getNewBanTime();
|
||||
|
||||
$user->ban($this->queryParam("reason"), true, $unban_time, $this->user->identity->getId());
|
||||
exit(json_encode([ "success" => true, "reason" => $this->queryParam("reason") ]));
|
||||
}
|
||||
|
||||
|
@ -360,9 +366,17 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
$user = $this->users->get($id);
|
||||
if(!$user)
|
||||
exit(json_encode([ "error" => "User does not exist" ]));
|
||||
|
||||
|
||||
$ban = (new Bans)->get((int)$user->getRawBanReason());
|
||||
if (!$ban || $ban->isOver())
|
||||
exit(json_encode([ "error" => "User is not banned" ]));
|
||||
|
||||
$ban->setRemoved_Manually(true);
|
||||
$ban->setRemoved_By($this->user->identity->getId());
|
||||
$ban->save();
|
||||
|
||||
$user->setBlock_Reason(NULL);
|
||||
$user->setUnblock_time(NULL);
|
||||
// $user->setUnblock_time(NULL);
|
||||
$user->save();
|
||||
exit(json_encode([ "success" => true ]));
|
||||
}
|
||||
|
@ -447,4 +461,12 @@ final class AdminPresenter extends OpenVKPresenter
|
|||
|
||||
$this->redirect("/admin/bannedLinks");
|
||||
}
|
||||
|
||||
function renderBansHistory(int $user_id) :void
|
||||
{
|
||||
$user = (new Users)->get($user_id);
|
||||
if (!$user) $this->notFound();
|
||||
|
||||
$this->template->bans = (new Bans)->getByUser($user_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php declare(strict_types=1);
|
||||
namespace openvk\Web\Presenters;
|
||||
use openvk\Web\Models\Entities\{IP, User, PasswordReset, EmailVerification};
|
||||
use openvk\Web\Models\Repositories\{IPs, Users, Restores, Verifications};
|
||||
use openvk\Web\Models\Repositories\{Bans, IPs, Users, Restores, Verifications};
|
||||
use openvk\Web\Models\Exceptions\InvalidUserNameException;
|
||||
use openvk\Web\Util\Validator;
|
||||
use Chandler\Session\Session;
|
||||
|
@ -332,9 +332,16 @@ final class AuthPresenter extends OpenVKPresenter
|
|||
$this->flashFail("err", tr("error"), tr("forbidden"));
|
||||
|
||||
$user = $this->users->get($this->user->id);
|
||||
$ban = (new Bans)->get((int)$user->getRawBanReason());
|
||||
if (!$ban || $ban->isOver() || $ban->isPermanent())
|
||||
$this->flashFail("err", tr("error"), tr("forbidden"));
|
||||
|
||||
$ban->setRemoved_Manually(2);
|
||||
$ban->setRemoved_By($this->user->identity->getId());
|
||||
$ban->save();
|
||||
|
||||
$user->setBlock_Reason(NULL);
|
||||
$user->setUnblock_Time(NULL);
|
||||
// $user->setUnblock_Time(NULL);
|
||||
$user->save();
|
||||
|
||||
$this->flashFail("succ", tr("banned_unban_title"), tr("banned_unban_description"));
|
||||
|
|
|
@ -3,6 +3,8 @@ namespace openvk\Web\Presenters;
|
|||
|
||||
final class BlobPresenter extends OpenVKPresenter
|
||||
{
|
||||
protected $banTolerant = true;
|
||||
|
||||
private function getDirName($dir): string
|
||||
{
|
||||
if(gettype($dir) === "integer") {
|
||||
|
|
|
@ -51,12 +51,7 @@ final class ReportPresenter extends OpenVKPresenter
|
|||
if(!$id)
|
||||
exit(json_encode([ "error" => tr("error_segmentation") ]));
|
||||
|
||||
// At this moment, only Posts will be implemented
|
||||
if(in_array($this->queryParam("type"), ["post", "photo", "video", "group"])) {
|
||||
$post = (new Posts)->get(intval($id));
|
||||
if(!$post)
|
||||
exit(json_encode([ "error" => "Unable to report nonexistent content" ]));
|
||||
|
||||
if(in_array($this->queryParam("type"), ["post", "photo", "video", "group", "comment", "note", "app"])) {
|
||||
$report = new Report;
|
||||
$report->setUser_id($this->user->id);
|
||||
$report->setTarget_id($id);
|
||||
|
@ -78,52 +73,40 @@ final class ReportPresenter extends OpenVKPresenter
|
|||
$this->assertPermission('openvk\Web\Models\Entities\TicketReply', 'write', 0);
|
||||
|
||||
$report = $this->reports->get($id);
|
||||
if(!$report) $this->notFound();
|
||||
if($report->isDeleted()) $this->notFound();
|
||||
if(!$report || $report->isDeleted()) $this->notFound();
|
||||
|
||||
if($this->postParam("ban")) {
|
||||
if(is_null($this->user))
|
||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||
|
||||
$report->banUser();
|
||||
if ($this->postParam("ban")) {
|
||||
$report->deleteContent();
|
||||
$report->banUser($this->user->identity->getId());
|
||||
|
||||
$this->flash("suc", "Смэрть...", "Пользователь успешно забанен.");
|
||||
}else if($this->postParam("delete")){
|
||||
if(is_null($this->user))
|
||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||
|
||||
} else if ($this->postParam("delete")) {
|
||||
$report->deleteContent();
|
||||
|
||||
$this->flash("suc", "Нехай живе!", "Контент удалён, а пользователю прилетело предупреждение.");
|
||||
}else if($this->postParam("ignore")){
|
||||
if(is_null($this->user))
|
||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||
|
||||
} else if ($this->postParam("ignore")) {
|
||||
$report->delete();
|
||||
|
||||
$this->flash("suc", "Нехай живе!", "Жалоба проигнорирована.");
|
||||
}else if($this->postParam("banClubOwner")) {
|
||||
if($report->getContentType() != "group")
|
||||
} else if ($this->postParam("banClubOwner") || $this->postParam("banClub")) {
|
||||
if ($report->getContentType() !== "group")
|
||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||
|
||||
$club = $report->getContentObject();
|
||||
|
||||
if(is_null($club))
|
||||
if (!$club || $club->isBanned())
|
||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||
|
||||
$owner = $club->getOwner();
|
||||
$owner->ban("Banned by report. Ask Technical support for ban reason");
|
||||
if ($this->postParam("banClubOwner")) {
|
||||
$club->getOwner()->ban("**content-" . $report->getContentType() . "-" . $report->getContentId() . "**", false, $club->getOwner()->getNewBanTime(), $this->user->identity->getId());
|
||||
} else {
|
||||
$club->ban("**content-" . $report->getContentType() . "-" . $report->getContentId() . "**");
|
||||
}
|
||||
|
||||
$report->delete();
|
||||
$this->flash("suc", "Смэрть...", "Создатель сообщества успешно забанен.");
|
||||
}else if($this->postParam("banClub")) {
|
||||
if($report->getContentType() != "group")
|
||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||
|
||||
$club = $report->getContentObject();
|
||||
$club->ban("Banned by report. Ask Technical support for ban reason");
|
||||
|
||||
$report->delete();
|
||||
$this->flash("suc", "Смэрть...", "Сообщество успешно забанено.");
|
||||
$this->flash("suc", "Смэрть...", ($this->postParam("banClubOwner") ? "Создатель сообщества успешно забанен." : "Сообщество успешно забанено"));
|
||||
}
|
||||
$this->redirect("/support/reports");
|
||||
|
||||
$this->redirect("/scumfeed");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,19 @@
|
|||
<img src="/assets/packages/static/openvk/img/oof.apng" alt="{_banned_alt}" style="width: 20%;" />
|
||||
</center>
|
||||
<p>
|
||||
{tr("banned_1", htmlentities($thisUser->getCanonicalName()))|noescape}<br/>
|
||||
{tr("banned_2", htmlentities($thisUser->getBanReason()))|noescape}
|
||||
{var $ban = $thisUser->getBanReason("banned")}
|
||||
{if is_string($ban)}
|
||||
{tr("banned_1", htmlentities($thisUser->getCanonicalName()))|noescape}<br/>
|
||||
{tr("banned_2", htmlentities($thisUser->getBanReason()))|noescape}
|
||||
{else}
|
||||
{tr("banned_1", htmlentities($thisUser->getCanonicalName()))|noescape}
|
||||
<div>
|
||||
Эта страница была заморожена {$ban[0]|noescape}
|
||||
{if $ban[1] !== "app"}
|
||||
{include "Report/ViewContent.xml", type => $ban[1], object => $ban[2]}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if !$thisUser->getUnbanTime()}
|
||||
{_banned_perm}
|
||||
|
|
|
@ -186,8 +186,11 @@
|
|||
(<b>{$helpdeskTicketNotAnsweredCount}</b>)
|
||||
{/if}
|
||||
</a>
|
||||
<a href="/admin/reports" class="link">{tr("reports")}</a>
|
||||
{/if}
|
||||
<a n:if="$canAccessHelpdesk" href="/scumfeed" class="link">{tr("reports")}
|
||||
{if $reportNotAnsweredCount > 0}
|
||||
(<b>{$reportNotAnsweredCount}</b>)
|
||||
{/if}
|
||||
</a>
|
||||
<a
|
||||
n:foreach="OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links'] as $menuItem"
|
||||
href="{$menuItem['url']}"
|
||||
|
@ -199,11 +202,6 @@
|
|||
n:foreach="$thisUser->getPinnedClubs() as $club"
|
||||
href="{$club->getURL()}"
|
||||
class="link group_link">{$club->getName()}</a>
|
||||
<a href="/admin/support/reports" class="link" n:if="$canAccessHelpdesk">Reports
|
||||
{if $reportNotAnsweredCount > 0}
|
||||
(<b>{$reportNotAnsweredCount}</b>)
|
||||
{/if}
|
||||
</a>
|
||||
|
||||
<a n:if="$thisUser->getLeftMenuItemStatus('links')" n:foreach="OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links'] as $menuItem" href="{$menuItem['url']}" target="_blank" class="link">{strpos($menuItem["name"], "@") === 0 ? tr(substr($menuItem["name"], 1)) : $menuItem["name"]}</a>
|
||||
|
||||
|
@ -278,8 +276,13 @@
|
|||
<a href="/restore">{_forgot_password}</a>
|
||||
</form>
|
||||
{/ifset}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{ifset $thisUser}
|
||||
{if !$thisUser->isBanned()}
|
||||
</div>
|
||||
{/if}
|
||||
{/ifset}
|
||||
|
||||
<div class="page_body">
|
||||
<div id="wrapH">
|
||||
|
|
86
Web/Presenters/templates/Admin/BansHistory.xml
Normal file
86
Web/Presenters/templates/Admin/BansHistory.xml
Normal file
|
@ -0,0 +1,86 @@
|
|||
{extends "./@layout.xml"}
|
||||
|
||||
{block title}
|
||||
История блокировок
|
||||
{/block}
|
||||
|
||||
{block heading}
|
||||
{include title}
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
<table class="aui aui-table-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Забаненный</th>
|
||||
<th>Инициатор</th>
|
||||
<th>Начало</th>
|
||||
<th>Конец</th>
|
||||
<th>Время</th>
|
||||
<th>Причина</th>
|
||||
<th>Снята</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr n:foreach="$bans as $ban">
|
||||
<td>{$ban->getId()}</td>
|
||||
<td>
|
||||
<span class="aui-avatar aui-avatar-xsmall">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$ban->getUser()->getAvatarUrl('miniscule')}"
|
||||
alt="{$ban->getUser()->getCanonicalName()}" style="object-fit: cover;"
|
||||
role="presentation"/>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<a href="{$ban->getUser()->getURL()}">{$ban->getUser()->getCanonicalName()}</a>
|
||||
|
||||
<span n:if="$ban->getUser()->isBanned()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">
|
||||
{_admin_banned}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="aui-avatar aui-avatar-xsmall">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$ban->getInitiator()->getAvatarUrl('miniscule')}"
|
||||
alt="{$ban->getInitiator()->getCanonicalName()}" style="object-fit: cover;"
|
||||
role="presentation"/>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<a href="{$ban->getInitiator()->getURL()}">{$ban->getInitiator()->getCanonicalName()}</a>
|
||||
|
||||
<span n:if="$ban->getInitiator()->isBanned()"
|
||||
class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">{_admin_banned}
|
||||
</span>
|
||||
</td>
|
||||
<td>{date('d.m.Y в H:i:s', $ban->getStartTime())}</td>
|
||||
<td>{date('d.m.Y в H:i:s', $ban->getEndTime())}</td>
|
||||
<td>{$ban->getTime()}</td>
|
||||
<td>
|
||||
{$ban->getReason()}
|
||||
</td>
|
||||
<td>
|
||||
{if $ban->isRemovedManually()}
|
||||
<span class="aui-avatar aui-avatar-xsmall">
|
||||
<span class="aui-avatar-inner">
|
||||
<img src="{$ban->whoRemoved()->getAvatarUrl('miniscule')}"
|
||||
alt="{$ban->whoRemoved()->getCanonicalName()}" style="object-fit: cover;"
|
||||
role="presentation"/>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<a href="{$ban->whoRemoved()->getURL()}">{$ban->whoRemoved()->getCanonicalName()}</a>
|
||||
|
||||
<span n:if="$ban->whoRemoved()->isBanned()" class="aui-lozenge aui-lozenge-subtle aui-lozenge-removed">
|
||||
{_admin_banned}
|
||||
</span>
|
||||
{else}
|
||||
<b style="color: red;">Активная блокировка</b>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{/block}
|
|
@ -1,4 +1,5 @@
|
|||
{extends "../@layout.xml"}
|
||||
{var $canReport = $owner->getId() !== $thisUser->getId()}
|
||||
|
||||
{block title}
|
||||
{$name}
|
||||
|
@ -6,6 +7,7 @@
|
|||
|
||||
{block header}
|
||||
{$name}
|
||||
<a style="float: right;" onClick="reportApp()" n:if="$canReport ?? false">Пожаловаться</a>
|
||||
{/block}
|
||||
|
||||
{block content}
|
||||
|
@ -33,5 +35,29 @@
|
|||
window.appOrigin = {$origin};
|
||||
</script>
|
||||
|
||||
<script n:if="$canReport ?? false">
|
||||
function reportApp() {
|
||||
uReportMsgTxt = "Вы собираетесь пожаловаться на данное приложение.";
|
||||
uReportMsgTxt += "<br/>Что именно вам кажется недопустимым в этом материале?";
|
||||
uReportMsgTxt += "<br/><br/><b>Причина жалобы</b>: <input type='text' id='uReportMsgInput' placeholder='Причина' />"
|
||||
|
||||
MessageBox("Пожаловаться?", uReportMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
(function() {
|
||||
res = document.querySelector("#uReportMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/report/" + {$id} + "?reason=" + res + "&type=app", true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("reason") === -1)
|
||||
MessageBox("Ошибка", "Не удалось подать жалобу...", ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox("Операция успешна", "Скоро её рассмотрят модераторы", ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
</script>
|
||||
|
||||
{script "js/al_games.js"}
|
||||
{/block}
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
(function() {
|
||||
res = document.querySelector("#uReportMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/report.pl/" + {$club->getId()} + "?reason=" + res + "&type=group", true);
|
||||
xhr.open("GET", "/report/" + {$club->getId()} + "?reason=" + res + "&type=group", true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("reason") === -1)
|
||||
MessageBox("Ошибка", "Не удалось подать жалобу...", ["OK"], [Function.noop]);
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
(function() {
|
||||
res = document.querySelector("#uReportMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/report.pl/" + {$photo->getId()} + "?reason=" + res + "&type=photo", true);
|
||||
xhr.open("GET", "/report/" + {$photo->getId()} + "?reason=" + res + "&type=photo", true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("reason") === -1)
|
||||
MessageBox("Ошибка", "Не удалось подать жалобу...", ["OK"], [Function.noop]);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{* BEGIN ELEMENTS DESCRIPTION *}
|
||||
|
||||
{block link|strip|stripHtml}
|
||||
/admin/support/report{$x->getId()}
|
||||
/admin/report{$x->getId()}
|
||||
{/block}
|
||||
|
||||
{block preview}
|
||||
|
@ -35,6 +35,10 @@
|
|||
{_video}
|
||||
{elseif $x->getContentType() == "group"}
|
||||
{_groups}
|
||||
{elseif $x->getContentType() == "comment"}
|
||||
{_comment}
|
||||
{elseif $x->getContentType() == "app"}
|
||||
{_app}
|
||||
{else}
|
||||
Unknown
|
||||
{/if}
|
||||
|
|
|
@ -10,32 +10,22 @@
|
|||
|
||||
{block content}
|
||||
<p><b>{_comment}: </b>{$report->getReason()}</p>
|
||||
{if $report->getContentType() == "post"}
|
||||
{include "../components/post/oldpost.xml", post => $report->getContentObject()}
|
||||
{elseif $report->getContentType() == "photo"}
|
||||
{include "../components/photo.xml", photo => $report->getContentObject()}
|
||||
{elseif $report->getContentType() == "video"}
|
||||
{include "../components/video.xml", video => $report->getContentObject()}
|
||||
{elseif $report->getContentType() == "group"}
|
||||
{include "../components/group.xml", group => $report->getContentObject()}
|
||||
{else}
|
||||
Error
|
||||
{/if}
|
||||
{include "ViewContent.xml", type => $report->getContentType(), object => $report->getContentObject()}
|
||||
<center>
|
||||
<form n:if="$report->getContentType() != 'group'" action="/admin/reportAction{$report->getId()}" method="post">
|
||||
{include "../components/post/oldpost.xml", post => $report->getContentObject(), forceNoPinLink => TRUE, forceNoDeleteLink => TRUE, forceNoShareLink => TRUE, forceNoLike => TRUE}
|
||||
<center>
|
||||
<form action="/admin/support/reportAction{$report->getId()}" method="post">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input type="submit" name="ban" value="{_ban_user_action}" class="button">
|
||||
<input type="submit" name="delete" value="{_delete}" class="button">
|
||||
<input type="submit" name="ignore" value="{_ignore_report}" class="button">
|
||||
<form action="/admin/reportAction{$report->getId()}" method="post">
|
||||
<center>
|
||||
<form n:if="$report->getContentType() != 'group'" action="/admin/reportAction{$report->getId()}" method="post">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input type="submit" name="ban" value="{_ban_user_action}" class="button">
|
||||
<input type="submit" name="delete" value="{_delete}" class="button">
|
||||
<input type="submit" name="ignore" value="{_ignore_report}" class="button">
|
||||
</form>
|
||||
<form n:if="$report->getContentType() == 'group'" action="/admin/reportAction{$report->getId()}" method="post">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input type="submit" name="banClubOwner" value="Заблокировать создателя" class="button">
|
||||
<input type="submit" name="banClub" value="Заблокировать группу" class="button">
|
||||
<input type="submit" name="ignore" value="{_ignore_report}" class="button">
|
||||
</form>
|
||||
</center>
|
||||
</form>
|
||||
<form n:if="$report->getContentType() == 'group'" action="/admin/reportAction{$report->getId()}" method="post">
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input type="submit" name="banClubOwner" value="Заблокировать создателя" class="button">
|
||||
<input type="submit" name="banClub" value="Заблокировать группу" class="button">
|
||||
<input type="submit" name="ignore" value="{_ignore_report}" class="button">
|
||||
</form>
|
||||
</center>
|
||||
{/block}
|
||||
|
|
30
Web/Presenters/templates/Report/ViewContent.xml
Normal file
30
Web/Presenters/templates/Report/ViewContent.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
{block ViewContent}
|
||||
<div class="container_gray" style="margin-top: 16px; margin-bottom: 16px; max-width: 100%;">
|
||||
{if $type == "post"}
|
||||
{include "../components/post/oldpost.xml",
|
||||
post => $object,
|
||||
forceNoDeleteLink => true,
|
||||
forceNoPinLink => true,
|
||||
forceNoCommentsLink => true,
|
||||
forceNoShareLink => true,
|
||||
forceNoLike => true
|
||||
}
|
||||
{elseif $type == "photo"}
|
||||
{include "./content/photo.xml", photo => $object}
|
||||
{elseif $type == "video"}
|
||||
{include "./content/video.xml", video => $object}
|
||||
{elseif $type == "group"}
|
||||
{include "../components/group.xml", group => $object}
|
||||
{elseif $type == "comment"}
|
||||
{include "../components/comment.xml", comment => $object, timeOnly => true}
|
||||
{elseif $type == "note"}
|
||||
{include "./content/note.xml", note => $object}
|
||||
{elseif $type == "app"}
|
||||
{if $appsSoftDeleting}
|
||||
{include "./content/app.xml", app => $object}
|
||||
{/if}
|
||||
{else}
|
||||
{include "../components/error.xml", description => tr("version_incompatibility")}
|
||||
{/if}
|
||||
</div>
|
||||
{/block}
|
22
Web/Presenters/templates/Report/content/app.xml
Normal file
22
Web/Presenters/templates/Report/content/app.xml
Normal file
|
@ -0,0 +1,22 @@
|
|||
{block content}
|
||||
<div class="content">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="/app{$app->getId()}">
|
||||
<img style="max-width: 75px;" src="{$app->getAvatarUrl()}" />
|
||||
</a>
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
<a href="/app{$app->getId()}">
|
||||
<b>{$app->getName()}</b>
|
||||
</a>
|
||||
<br/>
|
||||
{$app->getDescription()}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/block}
|
18
Web/Presenters/templates/Report/content/note.xml
Normal file
18
Web/Presenters/templates/Report/content/note.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
{block content}
|
||||
<article id="userContent" style="margin: 10px 10px 0;">
|
||||
<div class="note_header">
|
||||
<div class="note_title">
|
||||
<div class="note_title">
|
||||
<a>{$note->getName()}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="byline">
|
||||
<span><a href="{$note->getOwner()->getURL()}">{$note->getOwner()->getCanonicalName()}</a></span> {$note->getPublicationTime()}
|
||||
<span n:if="$note->getEditTime() > $note->getPublicationTime()">({_edited} {$note->getEditTime()})</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left: 6px; width: 535px;">
|
||||
{$note->getText()|noescape}
|
||||
</div>
|
||||
</article>
|
||||
{/block}
|
26
Web/Presenters/templates/Report/content/photo.xml
Normal file
26
Web/Presenters/templates/Report/content/photo.xml
Normal file
|
@ -0,0 +1,26 @@
|
|||
{block content}
|
||||
<div class="content">
|
||||
<center style="margin-bottom: 8pt;">
|
||||
<img src="{$photo->getURLBySizeId('large')}" style="max-width: 80%; max-height: 60vh;" />
|
||||
</center>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
<div>
|
||||
<h4>{_information}</h4>
|
||||
<span style="color: grey;">{_info_description}:</span>
|
||||
{$photo->getDescription() ?? "(" . tr("none") . ")"}<br/>
|
||||
<span style="color: grey;">{_info_uploaded_by}:</span>
|
||||
<a href="{$photo->getOwner()->getURL()}">{$photo->getOwner()->getFullName()}</a><br/>
|
||||
<span style="color: grey;">{_info_upload_date}:</span>
|
||||
{$photo->getPublicationTime()}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/block}
|
32
Web/Presenters/templates/Report/content/video.xml
Normal file
32
Web/Presenters/templates/Report/content/video.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
{block content}
|
||||
<div class="content">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="/video{$video->getPrettyId()}">
|
||||
<div class="video-preview">
|
||||
<img src="{$video->getThumbnailURL()}"
|
||||
alt="{$video->getName()}"
|
||||
style="max-width: 170px; max-height: 127px; margin: auto;" />
|
||||
</div>
|
||||
</a>
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
<a href="/video{$video->getPrettyId()}">
|
||||
<b>
|
||||
{$video->getName()}
|
||||
</b>
|
||||
</a>
|
||||
<br>
|
||||
<p>
|
||||
<span>{$video->getDescription() ?? ""}</span>
|
||||
</p>
|
||||
<span style="color: grey;">{_video_uploaded} {$video->getPublicationTime()}</span><br/>
|
||||
<span style="color: grey;">{_video_updated} {$video->getEditTime() ?? $video->getPublicationTime()}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/block}
|
|
@ -8,7 +8,42 @@
|
|||
{block content}
|
||||
<div class="post-author">
|
||||
<a href="#" style="font-size: 13px;"><b>{$ticket->getName()}</b></a><br />
|
||||
{_author}: <a href="/id{$ticket->getUser()->getId()}">{$ticket->getUser()->getFullName()}</a> | {$ticket->getUser()->getRegistrationIP()} | {_status}: {$ticket->getStatus()}.
|
||||
{_author}:
|
||||
<a href="/id{$ticket->getUser()->getId()}">
|
||||
{$ticket->getUser()->getFullName()}</a>
|
||||
| {$ticket->getUser()->getRegistrationIP()}
|
||||
| {_status}: {$ticket->getStatus()}.
|
||||
| <b n:if="$ticket->getUser()->isBanned()" style="color: red; cursor: pointer;" onclick="$('#ban-reason').toggle();">Блокировка</b>
|
||||
<div id="ban-reason" style="display: none; padding: 8px;">
|
||||
<h4 style="padding: 8px;">Причина блокировки</h4>
|
||||
<div style="padding: 8px;">Так пользователь видит экран с информацией о блокировке:</div>
|
||||
<div style="padding: 16px; border: 1px solid #C4C4C4; margin: 8px;">
|
||||
{var $ban = $ticket->getUser()->getBanReason("banned")}
|
||||
<center>
|
||||
<img src="/assets/packages/static/openvk/img/oof.apng" alt="{_banned_alt}" style="width: 20%;" />
|
||||
</center>
|
||||
<p>
|
||||
{if is_string($ban)}
|
||||
{tr("banned_1", htmlentities($ticket->getUser()->getCanonicalName()))|noescape}<br/>
|
||||
{tr("banned_2", htmlentities($ban))|noescape}
|
||||
{else}
|
||||
{tr("banned_1", htmlentities($ticket->getUser()->getCanonicalName()))|noescape}
|
||||
<div>
|
||||
Эта страница была заморожена {$ban[0]|noescape}
|
||||
{if $ban[1] !== "app"}
|
||||
{include "../Report/ViewContent.xml", type => $ban[1], object => $ban[2]}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if !$ticket->getUser()->getUnbanTime()}
|
||||
{_banned_perm}
|
||||
{else}
|
||||
{tr("banned_until_time", $ticket->getUser()->getUnbanTime())|noescape}
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text" style="padding-top: 10px; border-bottom: #ECECEC solid 1px;">
|
||||
{$ticket->getText()|noescape}
|
||||
|
|
|
@ -92,6 +92,9 @@
|
|||
<a href="javascript:warnUser()" class="profile_link">
|
||||
{_warn_user_action}
|
||||
</a>
|
||||
<a href="/admin/user{$user->getId()}/bans" class="profile_link">
|
||||
Блокировки
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
{if $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
|
||||
|
@ -544,13 +547,15 @@
|
|||
uBanMsgTxt += "<br/><b>Предупреждение</b>: Это действие удалит все подписки пользователя и отпишет всех от него.";
|
||||
uBanMsgTxt += "<br/><br/><b>Причина бана</b>: <input type='text' id='uBanMsgInput' placeholder='придумайте что-нибудь крутое' />"
|
||||
uBanMsgTxt += "<br/><br/><b>Заблокировать до</b>: <input type='date' id='uBanMsgDate' />";
|
||||
uBanMsgTxt += "<br/><br/><input id='uBanMsgIncr' type='checkbox' checked='1'/>Автоматически <b>(до " + {date('d.m.Y H\h', time() + $user->getNewBanTime())} + ")</b>";
|
||||
|
||||
MessageBox("Забанить " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
(function() {
|
||||
res = document.querySelector("#uBanMsgInput").value;
|
||||
date = document.querySelector("#uBanMsgDate").value;
|
||||
incr = document.querySelector("#uBanMsgIncr").checked ? '1' : '0';
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/admin/ban/" + {$user->getId()} + "?reason=" + res + "&date=" + date + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||
xhr.open("GET", "/admin/ban/" + {$user->getId()} + "?reason=" + res + "&incr=" + incr + "&date=" + date + "&hash=" + {rawurlencode($csrfToken)}, true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("success") === -1)
|
||||
MessageBox("Ошибка", "Не удалось забанить пользователя...", ["OK"], [Function.noop]);
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
<p>
|
||||
{tr("user_banned", htmlentities($user->getFirstName()))|noescape}<br/>
|
||||
{_user_banned_comment} <b>{$user->getBanReason()}</b>.<br/>
|
||||
Пользователь заблокирован до: <b>{$user->getUnbanTime()}</b>
|
||||
Пользователь заблокирован
|
||||
<span n:if="$user->getUnbanTime() !== NULL">до: <b>{$user->getUnbanTime()}</b></span>
|
||||
<span n:if="$user->getUnbanTime() === NULL"><b>навсегда</b></span>
|
||||
</p>
|
||||
{if isset($thisUser)}
|
||||
<p n:if="$thisUser->getChandlerUser()->can('access')->model('admin')->whichBelongsTo(NULL) || $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
(function() {
|
||||
res = document.querySelector("#uReportMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/report.pl/" + {$video->getId()} + "?reason=" + res + "&type=video", true);
|
||||
xhr.open("GET", "/report/" + {$video->getId()} + "?reason=" + res + "&type=video", true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("reason") === -1)
|
||||
MessageBox("Ошибка", "Не удалось подать жалобу...", ["OK"], [Function.noop]);
|
||||
|
|
|
@ -29,20 +29,50 @@
|
|||
</div>
|
||||
</div>
|
||||
<div n:if="isset($thisUser) &&! ($compact ?? false)" class="post-menu">
|
||||
<a href="#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}</a> |
|
||||
{if $comment->canBeDeletedBy($thisUser)}
|
||||
<a href="/comment{$comment->getId()}/delete">{_delete}</a> |
|
||||
<a href="#_comment{$comment->getId()}" class="date">{$comment->getPublicationTime()}</a>
|
||||
{if !$timeOnly}
|
||||
|
|
||||
{if $comment->canBeDeletedBy($thisUser)}
|
||||
<a href="/comment{$comment->getId()}/delete">{_delete}</a> |
|
||||
{/if}
|
||||
<a class="comment-reply">{_reply}</a>
|
||||
{if $thisUser->getId() != $comment->getOwner()->getId()}
|
||||
{var $canReport = true}
|
||||
| <a href="javascript:reportComment()">Пожаловаться</a>
|
||||
{/if}
|
||||
<div style="float: right; font-size: .7rem;">
|
||||
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
||||
<div class="heart" style="{if $comment->hasLikeFrom($thisUser)}opacity: 1;{else}opacity: 0.4;{/if}"></div>
|
||||
<span class="likeCnt">{if $comment->getLikesCount() > 0}{$comment->getLikesCount()}{/if}</span>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
<a class="comment-reply">{_reply}</a>
|
||||
<div style="float: right; font-size: .7rem;">
|
||||
<a class="post-like-button" href="/comment{$comment->getId()}/like?hash={rawurlencode($csrfToken)}">
|
||||
<div class="heart" style="{if $comment->hasLikeFrom($thisUser)}opacity: 1;{else}opacity: 0.4;{/if}"></div>
|
||||
<span class="likeCnt">{if $comment->getLikesCount() > 0}{$comment->getLikesCount()}{/if}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<script n:if="$canReport ?? false">
|
||||
function reportComment() {
|
||||
uReportMsgTxt = "Вы собираетесь пожаловаться на данный комментарий.";
|
||||
uReportMsgTxt += "<br/>Что именно вам кажется недопустимым в этом материале?";
|
||||
uReportMsgTxt += "<br/><br/><b>Причина жалобы</b>: <input type='text' id='uReportMsgInput' placeholder='Причина' />"
|
||||
|
||||
MessageBox("Пожаловаться?", uReportMsgTxt, ["Подтвердить", "Отмена"], [
|
||||
(function() {
|
||||
res = document.querySelector("#uReportMsgInput").value;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/report/" + {$comment->getId()} + "?reason=" + res + "&type=comment", true);
|
||||
xhr.onload = (function() {
|
||||
if(xhr.responseText.indexOf("reason") === -1)
|
||||
MessageBox("Ошибка", "Не удалось подать жалобу...", ["OK"], [Function.noop]);
|
||||
else
|
||||
MessageBox("Операция успешна", "Скоро её рассмотрят модераторы", ["OK"], [Function.noop]);
|
||||
});
|
||||
xhr.send(null);
|
||||
}),
|
||||
Function.noop
|
||||
]);
|
||||
}
|
||||
</script>
|
|
@ -1,22 +1,43 @@
|
|||
{block content}
|
||||
<div class="content">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="{$group->getURL()}">
|
||||
<img src="{$group->getAvatarURL()}" width="75" alt="Фотография группы">
|
||||
</a>
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
<a href="{$group->getURL()}">
|
||||
<b>
|
||||
asdasdasd
|
||||
</b>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="content">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<a href="{$group->getURL()}">
|
||||
<img src="{$group->getAvatarURL('miniscule')}" width="75" alt="Фотография группы">
|
||||
</a>
|
||||
</td>
|
||||
<td valign="top" style="width: 100%">
|
||||
<table id="basicInfo" class="ugc-table group_info" cellspacing="0" cellpadding="0" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="label">
|
||||
<span class="nobold">{_name}:</span>
|
||||
</td>
|
||||
<td class="data">
|
||||
<a href="{$group->getURL()}">{$group->getName()}</a>
|
||||
<img n:if="$group->isVerified()"
|
||||
class="name-checkmark"
|
||||
src="/assets/packages/static/openvk/img/checkmark.png"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label">
|
||||
<span class="nobold">{_size}:</span>
|
||||
</td>
|
||||
<td class="data">
|
||||
<a href="/club{$group->getId()}/followers">{tr("participants",
|
||||
$group->getFollowersCount())}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/block}
|
||||
|
|
|
@ -311,9 +311,9 @@ routes:
|
|||
handler: "Report->list"
|
||||
- url: "/admin/report{num}"
|
||||
handler: "Report->view"
|
||||
- url: "/admin/support/report{num}"
|
||||
- url: "/admin/report{num}"
|
||||
handler: "Report->view"
|
||||
- url: "/admin/support/reportAction{num}"
|
||||
- url: "/admin/reportAction{num}"
|
||||
handler: "Report->action"
|
||||
- url: "/report/{num}"
|
||||
handler: "Report->create"
|
||||
|
@ -323,6 +323,8 @@ routes:
|
|||
handler: "Admin->bannedLink"
|
||||
- url: "/admin/bannedLink/id{num}/unban"
|
||||
handler: "Admin->unbanLink"
|
||||
- url: "/admin/user{num}/bans"
|
||||
handler: "Admin->bansHistory"
|
||||
- url: "/upload/photo/{text}"
|
||||
handler: "VKAPI->photoUpload"
|
||||
- url: "/method/{text}.{text}"
|
||||
|
|
19
install/sqls/00032-better-reports.sql
Normal file
19
install/sqls/00032-better-reports.sql
Normal file
|
@ -0,0 +1,19 @@
|
|||
CREATE TABLE `bans`
|
||||
(
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`user` bigint(20) UNSIGNED NOT NULL,
|
||||
`initiator` bigint(20) UNSIGNED NOT NULL,
|
||||
`iat` bigint(20) UNSIGNED NOT NULL,
|
||||
`exp` bigint(20) NOT NULL,
|
||||
`time` bigint(20) NOT NULL,
|
||||
`reason` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`removed_manually` tinyint(1) DEFAULT 0,
|
||||
`removed_by` bigint(20) UNSIGNED NOT NULL DEFAULT 0
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
ALTER TABLE `bans`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
ALTER TABLE `bans`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||
COMMIT;
|
|
@ -1154,3 +1154,5 @@
|
|||
"url_is_banned_default_reason" = "The link you are trying to open may lead you to a site that was created for the purpose of deceiving users with the intention of gaining profit.";
|
||||
"url_is_banned_title" = "Link to a suspicious site";
|
||||
"url_is_banned_proceed" = "Follow the link";
|
||||
|
||||
"recently" = "Recently";
|
||||
|
|
|
@ -1213,3 +1213,5 @@
|
|||
"url_is_banned_default_reason" = "Ссылка, по которой вы попытались перейти, может вести на сайт, который был создан с целью обмана пользователей и получения за счёт этого прибыли.";
|
||||
"url_is_banned_title" = "Ссылка на подозрительный сайт";
|
||||
"url_is_banned_proceed" = "Перейти по ссылке";
|
||||
|
||||
"recently" = "Недавно";
|
||||
|
|
Loading…
Reference in a new issue