Новые поля для поиска etc.

This commit is contained in:
n1rwana 2023-08-08 23:49:05 +03:00
parent 544a16dff7
commit c93fb477d5
No known key found for this signature in database
GPG key ID: 1D319A83686EC843
8 changed files with 163 additions and 60 deletions

View file

@ -131,5 +131,10 @@ abstract class DBEntity
$this->changes = []; $this->changes = [];
} }
function getTableName(): string
{
return $this->getTable()->getName();
}
use \Nette\SmartObject; use \Nette\SmartObject;
} }

View file

@ -28,7 +28,7 @@ class Logs
return $this->toLog($this->logs->get($id)); return $this->toLog($this->logs->get($id));
} }
function create(int $user, string $table, string $model, int $type, $object, $changes): void function create(int $user, string $table, string $model, int $type, $object, $changes, ?string $ip = NULL, ?string $useragent = NULL): void
{ {
if (OPENVK_ROOT_CONF["openvk"]["preferences"]["logs"] === true) { if (OPENVK_ROOT_CONF["openvk"]["preferences"]["logs"] === true) {
$fobject = (is_array($object) ? $object : $object->unwrap()); $fobject = (is_array($object) ? $object : $object->unwrap());
@ -65,8 +65,8 @@ class Logs
$log->setXdiff_Old(json_encode($nobject)); $log->setXdiff_Old(json_encode($nobject));
$log->setXdiff_New(json_encode($_changes)); $log->setXdiff_New(json_encode($_changes));
$log->setTs(time()); $log->setTs(time());
$log->setIp(CurrentUser::i()->getIP()); $log->setIp($ip ?? CurrentUser::i()->getIP());
$log->setUserAgent(CurrentUser::i()->getUserAgent()); $log->setUserAgent($useragent ?? CurrentUser::i()->getUserAgent());
$log->save(); $log->save();
} }
} }

View file

@ -130,7 +130,7 @@ final class AuthPresenter extends OpenVKPresenter
} }
$this->authenticator->authenticate($chUser->getId()); $this->authenticator->authenticate($chUser->getId());
(new Logs)->create($user->getId(), "profiles", "openvk\\Web\\Models\\Entities\\User", 0, $user, $user); (new Logs)->create($user->getId(), "profiles", "openvk\\Web\\Models\\Entities\\User", 0, $user, $user, $_SERVER["REMOTE_ADDR"], $_SERVER["HTTP_USER_AGENT"]);
$this->redirect("/id" . $user->getId()); $this->redirect("/id" . $user->getId());
$user->save(); $user->save();
} }

View file

@ -1,12 +1,16 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace openvk\Web\Presenters; namespace openvk\Web\Presenters;
use Nette\Database\DriverException; use Nette\Database\DriverException;
use Nette\Utils\Finder; use Nette\Utils\Finder;
use Chandler\Database\DatabaseConnection; use Chandler\Database\DatabaseConnection;
use openvk\Web\Models\Entities\Club; use openvk\Web\Models\Entities\Club;
use openvk\Web\Models\Entities\Comment; use openvk\Web\Models\Entities\Comment;
use openvk\Web\Models\Entities\Log;
use openvk\Web\Models\Entities\NoSpamLog; use openvk\Web\Models\Entities\NoSpamLog;
use openvk\Web\Models\Entities\User; use openvk\Web\Models\Entities\User;
use openvk\Web\Models\Repositories\Logs;
use openvk\Web\Models\Repositories\NoSpamLogs; use openvk\Web\Models\Repositories\NoSpamLogs;
final class NoSpamPresenter extends OpenVKPresenter final class NoSpamPresenter extends OpenVKPresenter
@ -63,11 +67,11 @@ final class NoSpamPresenter extends OpenVKPresenter
$this->template->_template = "NoSpam/Templates.xml"; $this->template->_template = "NoSpam/Templates.xml";
$filter = []; $filter = [];
if ($this->queryParam("id")) { if ($this->queryParam("id")) {
$filter["id"] = (int) $this->queryParam("id"); $filter["id"] = (int)$this->queryParam("id");
} }
$this->template->templates = iterator_to_array((new NoSpamLogs)->getList($filter)); $this->template->templates = iterator_to_array((new NoSpamLogs)->getList($filter));
} else { } else {
$template = (new NoSpamLogs)->get((int) $this->postParam("id")); $template = (new NoSpamLogs)->get((int)$this->postParam("id"));
if (!$template || $template->isRollbacked()) if (!$template || $template->isRollbacked())
$this->returnJson(["success" => false, "error" => "Шаблон не найден"]); $this->returnJson(["success" => false, "error" => "Шаблон не найден"]);
@ -81,7 +85,7 @@ final class NoSpamPresenter extends OpenVKPresenter
try { try {
$item = new $model; $item = new $model;
$table_name = $item->getTableName(); $table_name = $item->getTableName();
$item = $db->table($table_name)->get((int) $_item); $item = $db->table($table_name)->get((int)$_item);
if (!$item) continue; if (!$item) continue;
$item = new $model($item); $item = new $model($item);
@ -135,15 +139,53 @@ final class NoSpamPresenter extends OpenVKPresenter
$this->assertNoCSRF(); $this->assertNoCSRF();
$this->willExecuteWriteAction(); $this->willExecuteWriteAction();
function searchByAdditionalParams(?string $table = NULL, ?string $where = NULL, ?string $ip = NULL, ?string $useragent = NULL, ?int $ts = NULL, ?int $te = NULL, ?int $user = NULL)
{
$db = DatabaseConnection::i()->getContext();
if ($table && ($ip || $useragent || $ts || $te || $user)) {
$conditions = [];
if ($ip) $conditions[] = "`ip` REGEXP '$ip'";
if ($useragent) $conditions[] = "`useragent` REGEXP '$useragent'";
if ($ts) $conditions[] = "`ts` < $ts";
if ($te) $conditions[] = "`ts` > $te";
if ($user) $conditions[] = "`user` = $user";
$logs = $db->query("SELECT * FROM `logs` WHERE (`object_table` = '$table') AND (" . implode(" AND ", $conditions) . ") GROUP BY `object_id`");
$response = [];
if (!$where) {
foreach ($logs as $log) {
$log = (new Logs)->get($log->id);
$response[] = $log->getObject()->unwrap();
}
} else {
foreach ($logs as $log) {
$log = (new Logs)->get($log->id);
$object = $log->getObject()->unwrap();
if (!$object) continue;
foreach ($db->query("SELECT * FROM `$table` WHERE $where")->fetchAll() as $o) {
if ($object->id === $o["id"]) {
$response[] = $object;
}
}
}
}
return $response;
}
}
try { try {
$where = $this->postParam("where"); $where = $this->postParam("where");
$ip = $this->postParam("ip"); $ip = $this->postParam("ip");
$useragent = $this->postParam("useragent"); $useragent = $this->postParam("useragent");
$searchTerm = $this->postParam("q"); $searchTerm = $this->postParam("q");
$ts = $this->postParam("ts"); $ts = (int)$this->postParam("ts");
$te = $this->postParam("te"); $te = (int)$this->postParam("te");
$user = (int)$this->postParam("user");
if (!$ip && !$useragent && !$searchTerm && !$ts && !$te && !$where && !$searchTerm) if (!$ip && !$useragent && !$searchTerm && !$ts && !$te && !$where && !$searchTerm && !$user)
$this->returnJson(["success" => false, "error" => "Нет запроса. Заполните поле \"подстрока\" или введите запрос \"WHERE\" в поле под ним."]); $this->returnJson(["success" => false, "error" => "Нет запроса. Заполните поле \"подстрока\" или введите запрос \"WHERE\" в поле под ним."]);
$model_name = NoSpamPresenter::ENTITIES_NAMESPACE . "\\" . $this->postParam("model"); $model_name = NoSpamPresenter::ENTITIES_NAMESPACE . "\\" . $this->postParam("model");
@ -160,8 +202,7 @@ final class NoSpamPresenter extends OpenVKPresenter
$table = $model->getTableName(); $table = $model->getTableName();
$columns = $db->getStructure()->getColumns($table); $columns = $db->getStructure()->getColumns($table);
$rows = []; if ($searchTerm) {
if (!$where) {
$conditions = []; $conditions = [];
$need_deleted = false; $need_deleted = false;
foreach ($columns as $column) { foreach ($columns as $column) {
@ -171,12 +212,19 @@ final class NoSpamPresenter extends OpenVKPresenter
$conditions[] = "`$column[name]` REGEXP '$searchTerm'"; $conditions[] = "`$column[name]` REGEXP '$searchTerm'";
} }
} }
$conditions = implode(" OR ", $conditions);
$where = "(" . implode(" OR ", $conditions) . ")"; $where = ($where ? " AND ($conditions)" : $conditions);
if ($need_deleted) $where .= " AND `deleted` = 0"; if ($need_deleted) $where .= " AND `deleted` = 0";
} }
$rows = [];
if ($ip || $useragent || $ts || $te || $user) {
$rows = searchByAdditionalParams($table, $where, $ip, $useragent, $ts, $te, $user);
}
$result = $db->query("SELECT * FROM `$table` WHERE $where"); $result = $db->query("SELECT * FROM `$table` WHERE $where");
if (count($rows) === 0)
$rows = $result->fetchAll(); $rows = $result->fetchAll();
if (!in_array((int)$this->postParam("ban"), [1, 2, 3])) { if (!in_array((int)$this->postParam("ban"), [1, 2, 3])) {
@ -215,7 +263,7 @@ final class NoSpamPresenter extends OpenVKPresenter
} else { } else {
$log->setRequest($where); $log->setRequest($where);
} }
$log->setBan_Type((int) $this->postParam("ban")); $log->setBan_Type((int)$this->postParam("ban"));
$log->setCount(count($rows)); $log->setCount(count($rows));
$log->setTime(time()); $log->setTime(time());
$log->setItems(implode(",", $ids)); $log->setItems(implode(",", $ids));

View file

@ -5,7 +5,7 @@
{block content} {block content}
{include "Tabs.xml", mode => "form"} {include "Tabs.xml", mode => "form"}
<br /> <br/>
<div style="display: flex; border: 1px solid #ECECEC; padding: 8px;"> <div style="display: flex; border: 1px solid #ECECEC; padding: 8px;">
<div id="noSpam-form" style="width: 50%; border-right: 1px solid #ECECEC;"> <div id="noSpam-form" style="width: 50%; border-right: 1px solid #ECECEC;">
<table cellspacing="7" cellpadding="0" width="100%" border="0"> <table cellspacing="7" cellpadding="0" width="100%" border="0">
@ -16,16 +16,15 @@
</td> </td>
<td> <td>
<select name="model" id="model" style="margin-left: -2px;"> <select name="model" id="model" style="margin-left: -2px;">
<option selected>Не выбрано</option> <option selected value="none">Не выбрано</option>
<option n:foreach="$models as $model" value="{$model}"> <option n:foreach="$models as $model" value="{$model}">{$model}</option>
{$model}
</option>
</select> </select>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div style="border-top: 1px solid #ECECEC; margin: 8px 0;" /> <div style="border-top: 1px solid #ECECEC; margin: 8px 0;"/>
<div id="noSpam-fields" style="display: none;">
<table cellspacing="7" cellpadding="0" width="100%" border="0"> <table cellspacing="7" cellpadding="0" width="100%" border="0">
<tbody> <tbody>
<tr style="width: 129px; border-top: 1px solid #ECECEC;"> <tr style="width: 129px; border-top: 1px solid #ECECEC;">
@ -36,13 +35,20 @@
<input type="text" name="regex" placeholder="Regex" id="regex"> <input type="text" name="regex" placeholder="Regex" id="regex">
</td> </td>
</tr> </tr>
{* "Это могли бы быть мы с тобой, но" в овк нет логов :( *} <tr style="width: 129px; border-top: 1px solid #ECECEC;">
{*<tr style="width: 129px"> <td>
<span class="nobold">Пользователь:</span>
</td>
<td>
<input type="text" name="user" placeholder="ID" id="user">
</td>
</tr>
<tr style="width: 129px">
<td> <td>
<span class="nobold">IP:</span> <span class="nobold">IP:</span>
</td> </td>
<td> <td>
<input type="text" name="ip" placeholder="или подсеть"> <input type="text" name="ip" id="ip" placeholder="или подсеть">
</td> </td>
</tr> </tr>
<tr style="width: 129px"> <tr style="width: 129px">
@ -50,7 +56,7 @@
<span class="nobold">Юзер-агент:</span> <span class="nobold">Юзер-агент:</span>
</td> </td>
<td> <td>
<input type="text" name="useragent" placeholder="Mozila 1.0 Blablabla/test"> <input type="text" name="useragent" id="useragent" placeholder="Mozila 1.0 Blablabla/test">
</td> </td>
</tr> </tr>
<tr style="width: 129px"> <tr style="width: 129px">
@ -58,7 +64,7 @@
<span class="nobold">Время раньше, чем:</span> <span class="nobold">Время раньше, чем:</span>
</td> </td>
<td> <td>
<input type="date" name="ds"> <input type="datetime-local" name="ts" id="ts">
</td> </td>
</tr> </tr>
<tr style="width: 129px"> <tr style="width: 129px">
@ -66,16 +72,15 @@
<span class="nobold">Время позже, чем:</span> <span class="nobold">Время позже, чем:</span>
</td> </td>
<td> <td>
<input type="date" name="de"> <input type="datetime-local" name="te" id="te">
</td> </td>
</tr>*} </tr>
</tbody> </tbody>
</table> </table>
<br /> <textarea style="resize: vertical; width: calc(100% - 6px)" placeholder='city = "Воскресенск" && id = 1'
<center><b>ИЛИ</b></center> name="where" id="where"/>
<br /> <span style="color: grey; font-size: 8px;">WHERE для поиска по разделу</span>
<textarea style="resize: vertical; width: calc(100% - 6px)" placeholder='city = "Воскресенск" && id = 1' name="where" id="where" /> <div style="border-top: 1px solid #ECECEC; margin: 8px 0;"/>
<div style="border-top: 1px solid #ECECEC; margin: 8px 0;" />
<table cellspacing="7" cellpadding="0" width="100%" border="0"> <table cellspacing="7" cellpadding="0" width="100%" border="0">
<tbody> <tbody>
<tr style="width: 129px; border-top: 1px solid #ECECEC;"> <tr style="width: 129px; border-top: 1px solid #ECECEC;">
@ -92,24 +97,35 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div style="border-top: 1px solid #ECECEC; margin: 8px 0;" /> <div style="border-top: 1px solid #ECECEC; margin: 8px 0;"/>
<center> <center>
<div id="noSpam-buttons"> <div id="noSpam-buttons">
<input id="search" type="submit" value="Поиск" class="button" /> <input id="search" type="submit" value="Поиск" class="button"/>
<input id="apply" type="submit" value="Применить" class="button" style="display: none;" /> <input id="apply" type="submit" value="Применить" class="button" style="display: none;"/>
</div> </div>
<div id="noSpam-loader" style="display: none;"> <div id="noSpam-loader" style="display: none;">
<img src="/assets/packages/static/openvk/img/loading_mini.gif" style="width: 40px;"> <img src="/assets/packages/static/openvk/img/loading_mini.gif" style="width: 40px;">
</div> </div>
</center> </center>
</div> </div>
<div id="noSpam-model-not-selected">
<center id="noSpam-model-not-selected-text" style="padding: 71px 25px;">Выберите раздел для начала работы</center>
<center id="noSpam-model-not-selected-loader" style="display: none;">
<img src="/assets/packages/static/openvk/img/loading_mini.gif" style="width: 40px; margin: 125px 0;">
</center>
</div>
</div>
<div style="width: 50%;"> <div style="width: 50%;">
<center id="noSpam-results-loader" style="display: none;"> <center id="noSpam-results-loader" style="display: none;">
<img src="/assets/packages/static/openvk/img/loading_mini.gif" style="width: 40px; margin: 125px 0;"> <img src="/assets/packages/static/openvk/img/loading_mini.gif" style="width: 40px; margin: 125px 0;">
</center> </center>
<center id="noSpam-results-text" style="margin: 125px 25px;">Здесь будут отображаться результаты поиска</center> <center id="noSpam-results-text" style="margin: 125px 25px;">Здесь будут отображаться результаты поиска</center>
<div id="noSpam-results-block" style="display: none;"> <div id="noSpam-results-block" style="display: none;">
<h4 style="padding: 8px;">Результаты поиска (<span id="noSpam-results-count" style="color: inherit; font-weight: inherit;"></span> шт.)</h4> <h4 style="padding: 8px;">Результаты поиска
<span style="color: #a2a2a2; font-weight: inherit">
(<span id="noSpam-results-count" style="color: #a2a2a2; font-weight: inherit;"></span> шт.)
</span>
</h4>
<ul style="padding-inline-start:18px;" id="noSpam-results-list"></ul> <ul style="padding-inline-start:18px;" id="noSpam-results-list"></ul>
</div> </div>
</div> </div>
@ -127,6 +143,11 @@
let model = $("#model").val(); let model = $("#model").val();
let regex = $("#regex").val(); let regex = $("#regex").val();
let where = $("#where").val(); let where = $("#where").val();
let ip = $("#ip").val();
let useragent = $("#useragent").val();
let ts = $("#ts").val() ? Math.floor(new Date($("#ts").val()).getTime() / 1000) : null;
let te = $("#te").val() ? Math.floor(new Date($("#te").val()).getTime() / 1000) : null;
let user = $("#user").val();
await $.ajax({ await $.ajax({
type: "POST", type: "POST",
@ -136,6 +157,11 @@
q: regex, q: regex,
where: where, where: where,
ban: ban, ban: ban,
ip: ip,
useragent: useragent,
ts: ts,
te: te,
user: user,
hash: {=$csrfToken} hash: {=$csrfToken}
}, },
success: (response) => { success: (response) => {
@ -182,12 +208,33 @@
} }
$("#search").on("click", () => { search(); }); $("#search").on("click", () => { search(); });
$("#regex, #where").keypress((e) => { $("input, textarea").keypress((e) => {
if (e.which === 13 && !e.shiftKey) { if (e.which === 13 && !e.shiftKey) {
e.preventDefault(); e.preventDefault();
search(); search();
} }
}); });
$("#apply").on("click", () => { search(Number($("#noSpam-ban-type").val())); }) $("#apply").on("click", () => { search(Number($("#noSpam-ban-type").val())); })
$("#model").on("change", async (e) => {
if (e.target.value !== "none") {
$("#noSpam-fields").hide();
$("#noSpam-model-not-selected").show();
$("#noSpam-model-not-selected-text").hide();
$("#noSpam-model-not-selected-loader").show();
setTimeout(() => {
$("#noSpam-model-not-selected").hide();
$("#noSpam-fields").show();
$("#noSpam-model-not-selected-loader").hide();
}, 100)
} else {
$("#noSpam-fields").hide();
$("#noSpam-model-not-selected").show();
$("#noSpam-model-not-selected-loader").show();
setTimeout(() => {
$("#noSpam-model-not-selected-text").show();
$("#noSpam-model-not-selected-loader").hide();
}, 100)
}
})
</script> </script>
{/block} {/block}

View file

@ -3,6 +3,6 @@
<a n:attr="id => ($mode === 'form' ? 'act_tab_a' : 'ki')" href="/noSpam">Бан по шаблону</a> <a n:attr="id => ($mode === 'form' ? 'act_tab_a' : 'ki')" href="/noSpam">Бан по шаблону</a>
</div> </div>
<div n:attr="id => ($mode === 'templates' ? 'activetabs' : 'ki')" class="tab"> <div n:attr="id => ($mode === 'templates' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($mode === 'templates' ? 'act_tab_a' : 'ki')" href="/noSpam?act=templates">Шаблоны</a> <a n:attr="id => ($mode === 'templates' ? 'act_tab_a' : 'ki')" href="/noSpam?act=templates">Действующие шаблоны</a>
</div> </div>
</div> </div>

View file

@ -89,8 +89,10 @@
// Full width block // Full width block
$(".navigation").hide(); $(".navigation").hide();
$(".page_content").width("100%"); $(".page_content").width("100%");
$(".page_body").width("100%").css("margin-right", 0).css("margin-top", "-5px"); $(".page_body").width("100%").css("margin-right", 0).css("margin-top", "-2px");
$(".tabs").width("100%"); $(".tabs").width("100%");
$(".sidebar").css("margin", 0);
$(".page_header").css("position", "initial");
function openTableField(name, id) { function openTableField(name, id) {
MessageBox(name, $(`#${ name}-${ id}`).text(), ["OK"], [Function.noop]); MessageBox(name, $(`#${ name}-${ id}`).text(), ["OK"], [Function.noop]);

View file

@ -671,6 +671,7 @@ input[type~="phone"],
input[type="search"], input[type="search"],
input[type~="search"], input[type~="search"],
input[type~="date"], input[type~="date"],
input[type~="datetime-local"],
select { select {
border: 1px solid #C0CAD5; border: 1px solid #C0CAD5;
padding: 3px; padding: 3px;