Support: Allow agents to prevent users from creating tickets

This commit is contained in:
Maxim Leshchenko 2022-03-26 21:48:42 +01:00
parent f505887d7f
commit 6588734caa
No known key found for this signature in database
GPG key ID: BB9C44A8733FBEEE
8 changed files with 137 additions and 13 deletions

View file

@ -215,6 +215,11 @@ class User extends RowModel
return $this->getRecord()->block_reason; return $this->getRecord()->block_reason;
} }
function getBanInSupportReason(): ?string
{
return $this->getRecord()->block_in_support_reason;
}
function getType(): int function getType(): int
{ {
return $this->getRecord()->type; return $this->getRecord()->type;
@ -674,6 +679,11 @@ class User extends RowModel
return !is_null($this->getBanReason()); return !is_null($this->getBanReason());
} }
function isBannedInSupport(): bool
{
return !is_null($this->getBanInSupportReason());
}
function isOnline(): bool function isOnline(): bool
{ {
return time() - $this->getRecord()->online <= 300; return time() - $this->getRecord()->online <= 300;

View file

@ -1,7 +1,7 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace openvk\Web\Presenters; namespace openvk\Web\Presenters;
use openvk\Web\Models\Entities\Ticket; use openvk\Web\Models\Entities\Ticket;
use openvk\Web\Models\Repositories\Tickets; use openvk\Web\Models\Repositories\{Tickets, Users};
use openvk\Web\Models\Entities\TicketComment; use openvk\Web\Models\Entities\TicketComment;
use openvk\Web\Models\Repositories\TicketComments; use openvk\Web\Models\Repositories\TicketComments;
use openvk\Web\Util\Telegram; use openvk\Web\Util\Telegram;
@ -34,7 +34,13 @@ final class SupportPresenter extends OpenVKPresenter
$this->template->tickets = $this->tickets->getTicketsByUserId($this->user->id, $this->template->page); $this->template->tickets = $this->tickets->getTicketsByUserId($this->user->id, $this->template->page);
} }
if($this->template->mode === "new")
$this->template->banReason = $this->user->identity->getBanInSupportReason();
if($_SERVER["REQUEST_METHOD"] === "POST") { if($_SERVER["REQUEST_METHOD"] === "POST") {
if($this->user->identity->isBannedInSupport())
$this->flashFail("err", tr("not_enough_permissions"), tr("not_enough_permissions_comment"));
if(!empty($this->postParam("name")) && !empty($this->postParam("text"))) { if(!empty($this->postParam("name")) && !empty($this->postParam("text"))) {
$this->willExecuteWriteAction(); $this->willExecuteWriteAction();
@ -268,4 +274,32 @@ final class SupportPresenter extends OpenVKPresenter
exit(header("HTTP/1.1 200 OK")); exit(header("HTTP/1.1 200 OK"));
} }
function renderQuickBanInSupport(int $id): void
{
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
$this->assertNoCSRF();
$user = (new Users)->get($id);
if(!$user)
exit(json_encode([ "error" => "User does not exist" ]));
$user->setBlock_In_Support_Reason($this->queryParam("reason"));
$user->save();
$this->returnJson([ "success" => true, "reason" => $this->queryParam("reason") ]);
}
function renderQuickUnbanInSupport(int $id): void
{
$this->assertPermission("openvk\Web\Models\Entities\TicketReply", "write", 0);
$this->assertNoCSRF();
$user = (new Users)->get($id);
if(!$user)
exit(json_encode([ "error" => "User does not exist" ]));
$user->setBlock_In_Support_Reason(null);
$user->save();
$this->returnJson([ "success" => true ]);
}
} }

View file

@ -26,6 +26,15 @@
<br /> <br />
{if $isNew} {if $isNew}
{if !is_null($banReason)}
<center>
<img src="/assets/packages/static/openvk/img/oof.apng" alt="{_'banned_alt'}" style="width: 20%;" />
</center>
<p>
{tr("banned_in_support_1", htmlentities($thisUser->getCanonicalName()))|noescape}<br/>
{tr("banned_in_support_2", htmlentities($banReason))|noescape}
</p>
{else}
<div class="new"> <div class="new">
<form action="/support" method="post" style="margin:0;"> <form action="/support" method="post" style="margin:0;">
<center> <center>
@ -38,6 +47,7 @@
</div> </div>
{/if} {/if}
{/if} {/if}
{/if}
{if $isMain} {if $isMain}
<h4>{_support_faq}</h4><br /> <h4>{_support_faq}</h4><br />

View file

@ -94,6 +94,16 @@
</a> </a>
{/if} {/if}
{if $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
<a href="javascript:toggleBanInSupport()" class="profile_link">
{if $user->isBannedInSupport()}
{_unban_in_support_user_action}
{else}
{_ban_in_support_user_action}
{/if}
</a>
{/if}
<a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && $user->getGiftCount() == 0" href="/gifts?act=pick&user={$user->getId()}" class="profile_link">{_send_gift}</a> <a n:if="OPENVK_ROOT_CONF['openvk']['preferences']['commerce'] && $user->getGiftCount() == 0" href="/gifts?act=pick&user={$user->getId()}" class="profile_link">{_send_gift}</a>
<a n:if="$user->getPrivacyPermission('messages.write', $thisUser)" href="/im?sel={$user->getId()}" class="profile_link">{_"send_message"}</a> <a n:if="$user->getPrivacyPermission('messages.write', $thisUser)" href="/im?sel={$user->getId()}" class="profile_link">{_"send_message"}</a>
@ -526,7 +536,7 @@
function warnUser() { function warnUser() {
uBanMsgTxt = "Вы собираетесь предупредить пользователя " + {$user->getCanonicalName()} + "."; uBanMsgTxt = "Вы собираетесь предупредить пользователя " + {$user->getCanonicalName()} + ".";
uBanMsgTxt += "<br/>Мы отправим уведомление пользователю в личные сообщения от имени аккаунта администратора."; uBanMsgTxt += "<br/>Мы отправим уведомление пользователю в личные сообщения от имени аккаунта администратора.";
uBanMsgTxt += "<br/><br/><b>Текст предупреждения</b>: <input type='text' id='uWarnMsgInput' placeholder='придумайте что-нибудь крутое' />" uBanMsgTxt += "<br/><br/><b>Текст предупреждения</b>: <input type='text' id='uWarnMsgInput' placeholder='придумайте что-нибудь крутое' />";
MessageBox("Выдать предупреждение " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [ MessageBox("Выдать предупреждение " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
(function() { (function() {
@ -546,6 +556,51 @@
} }
</script> </script>
<script n:if="isset($thisUser) && $thisUser->getChandlerUser()->can('write')->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)">
{if $user->isBannedInSupport()}
function toggleBanInSupport() {
uBanMsgTxt = "Вы собираетесь разблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
uBanMsgTxt += "<br/>Сейчас он заблокирован по причине <strong>" + {$user->getBanInSupportReason()} + "</strong>.";
MessageBox("Разблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
(function() {
xhr = new XMLHttpRequest();
xhr.open("GET", "/admin/support/unban/" + {$user->getId()} + "?hash=" + {rawurlencode($csrfToken)}, true);
xhr.onload = (function() {
if(xhr.responseText.indexOf("success") === -1)
MessageBox("Ошибка", "Не удалось разблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
else
MessageBox("Операция успешна", "Пользователь разблокирован в поддержке", ["OK"], [Function.noop]);
});
xhr.send(null);
}),
Function.noop
]);
}
{else}
function toggleBanInSupport() {
uBanMsgTxt = "Вы собираетесь заблокировать в поддержке пользователя " + {$user->getCanonicalName()} + ".";
uBanMsgTxt += "<br/><br/><b>Причина бана</b>: <input type='text' id='uBanMsgInput' placeholder='придумайте что-нибудь крутое' />";
MessageBox("Заблокировать в поддержке " + {$user->getFirstName()}, uBanMsgTxt, ["Подтвердить", "Отмена"], [
(function() {
res = document.querySelector("#uBanMsgInput").value;
xhr = new XMLHttpRequest();
xhr.open("GET", "/admin/support/ban/" + {$user->getId()} + "?reason=" + res + "&hash=" + {rawurlencode($csrfToken)}, true);
xhr.onload = (function() {
if(xhr.responseText.indexOf("success") === -1)
MessageBox("Ошибка", "Не удалось заблокировать пользователя в поддержке...", ["OK"], [Function.noop]);
else
MessageBox("Операция успешна", "Пользователь заблокирован в поддержке", ["OK"], [Function.noop]);
});
xhr.send(null);
}),
Function.noop
]);
}
{/if}
</script>
<script n:if="isset($thisUser) && $user->getId() == $thisUser->getId()" n:syntax="off"> <script n:if="isset($thisUser) && $user->getId() == $thisUser->getId()" n:syntax="off">
function setStatusEditorShown(shown) { function setStatusEditorShown(shown) {
document.getElementById("status_editor").style.display = shown ? "block" : "none"; document.getElementById("status_editor").style.display = shown ? "block" : "none";

View file

@ -273,6 +273,10 @@ routes:
handler: "Admin->quickBan" handler: "Admin->quickBan"
- url: "/admin/warn/{num}" - url: "/admin/warn/{num}"
handler: "Admin->quickWarn" handler: "Admin->quickWarn"
- url: "/admin/support/ban/{num}"
handler: "Support->quickBanInSupport"
- url: "/admin/support/unban/{num}"
handler: "Support->quickUnbanInSupport"
- url: "/method/{text}.{text}" - url: "/method/{text}.{text}"
handler: "VKAPI->route" handler: "VKAPI->route"
- url: "/token" - url: "/token"

View file

@ -0,0 +1 @@
ALTER TABLE `profiles` ADD COLUMN `block_in_support_reason` text COLLATE utf8mb4_unicode_520_ci DEFAULT NULL AFTER `block_reason`;

View file

@ -688,6 +688,9 @@
"ticket_changed" = "Ticket changed"; "ticket_changed" = "Ticket changed";
"ticket_changed_comment" = "The changes will take effect in a few seconds."; "ticket_changed_comment" = "The changes will take effect in a few seconds.";
"banned_in_support_1" = "Sorry, <b>$1</b>, but now you can't create tickets.";
"banned_in_support_2" = "And the reason for this is simple: <b>$1</b>. Unfortunately, this time we had to take away this opportunity from you forever.";
/* Invite */ /* Invite */
"invite" = "Invite"; "invite" = "Invite";
@ -832,6 +835,8 @@
"manage_group_action" = "Manage group"; "manage_group_action" = "Manage group";
"ban_user_action" = "Ban user"; "ban_user_action" = "Ban user";
"warn_user_action" = "Warn user"; "warn_user_action" = "Warn user";
"ban_in_support_user_action" = "Ban in support";
"unban_in_support_user_action" = "Unban in support";
/* Paginator (deprecated) */ /* Paginator (deprecated) */

View file

@ -725,6 +725,9 @@
"ticket_changed" = "Тикет изменён"; "ticket_changed" = "Тикет изменён";
"ticket_changed_comment" = "Изменения вступят силу через несколько секунд."; "ticket_changed_comment" = "Изменения вступят силу через несколько секунд.";
"banned_in_support_1" = "Извините, <b>$1</b>, но теперь вам нельзя создавать обращения.";
"banned_in_support_2" = "А причина этому проста: <b>$1</b>. К сожалению, на этот раз нам пришлось отобрать у вас эту возможность навсегда.";
/* Invite */ /* Invite */
"invite" = "Пригласить"; "invite" = "Пригласить";
@ -875,6 +878,8 @@
"manage_group_action" = "Управление группой"; "manage_group_action" = "Управление группой";
"ban_user_action" = "Заблокировать пользователя"; "ban_user_action" = "Заблокировать пользователя";
"warn_user_action" = "Предупредить пользователя"; "warn_user_action" = "Предупредить пользователя";
"ban_in_support_user_action" = "Заблокировать в поддержке";
"unban_in_support_user_action" = "Разблокировать в поддержке";
/* Paginator (deprecated) */ /* Paginator (deprecated) */