mirror of
https://github.com/openvk/openvk
synced 2024-12-22 16:42:32 +03:00
[noSpam] Параметры блокировки (#960)
* Параметры блокировки * Защита от SQLi и доработка поиска * Фикс блокировки, если дата разблокировки не указана
This commit is contained in:
parent
e433e46b36
commit
245f8690c6
3 changed files with 191 additions and 149 deletions
|
@ -363,7 +363,7 @@ final class AdminPresenter extends OpenVKPresenter
|
||||||
if (str_contains($this->queryParam("reason"), "*"))
|
if (str_contains($this->queryParam("reason"), "*"))
|
||||||
exit(json_encode([ "error" => "Incorrect reason" ]));
|
exit(json_encode([ "error" => "Incorrect reason" ]));
|
||||||
|
|
||||||
$unban_time = strtotime($this->queryParam("date")) ?: NULL;
|
$unban_time = strtotime($this->queryParam("date")) ?: "permanent";
|
||||||
|
|
||||||
$user = $this->users->get($id);
|
$user = $this->users->get($id);
|
||||||
if(!$user)
|
if(!$user)
|
||||||
|
|
|
@ -177,26 +177,25 @@ final class NoSpamPresenter extends OpenVKPresenter
|
||||||
if ($conditions) {
|
if ($conditions) {
|
||||||
$logs = $db->query("SELECT * FROM `ChandlerLogs` $whereStart $conditions GROUP BY `object_id`, `object_model`");
|
$logs = $db->query("SELECT * FROM `ChandlerLogs` $whereStart $conditions GROUP BY `object_id`, `object_model`");
|
||||||
|
|
||||||
if (!$where) {
|
foreach ($logs as $log) {
|
||||||
foreach ($logs as $log) {
|
$log = (new Logs)->get($log->id);
|
||||||
$log = (new Logs)->get($log->id);
|
$object = $log->getObject()->unwrap();
|
||||||
$response[] = $log->getObject()->unwrap();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foreach ($logs as $log) {
|
|
||||||
$log = (new Logs)->get($log->id);
|
|
||||||
$object = $log->getObject()->unwrap();
|
|
||||||
|
|
||||||
if (!$object) continue;
|
if (!$object) continue;
|
||||||
|
if ($where) {
|
||||||
if (str_starts_with($where, " AND")) {
|
if (str_starts_with($where, " AND")) {
|
||||||
$where = substr_replace($where, "", 0, strlen(" AND"));
|
$where = substr_replace($where, "", 0, strlen(" AND"));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($db->query("SELECT * FROM `$table` WHERE $where")->fetchAll() as $o) {
|
$a = $db->query("SELECT * FROM `$table` WHERE $where")->fetchAll();
|
||||||
if ($object->id === $o["id"]) {
|
foreach ($a as $o) {
|
||||||
|
if ($object->id == $o["id"]) {
|
||||||
$response[] = $object;
|
$response[] = $object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$response[] = $object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,70 +205,72 @@ final class NoSpamPresenter extends OpenVKPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = [];
|
$response = [];
|
||||||
$processed = 0;
|
$processed = 0;
|
||||||
|
|
||||||
$where = $this->postParam("where");
|
$where = $this->postParam("where");
|
||||||
$ip = $this->postParam("ip");
|
$ip = addslashes($this->postParam("ip"));
|
||||||
$useragent = $this->postParam("useragent");
|
$useragent = addslashes($this->postParam("useragent"));
|
||||||
$searchTerm = $this->postParam("q");
|
$searchTerm = addslashes($this->postParam("q"));
|
||||||
$ts = (int)$this->postParam("ts");
|
$ts = (int)$this->postParam("ts");
|
||||||
$te = (int)$this->postParam("te");
|
$te = (int)$this->postParam("te");
|
||||||
$user = $this->postParam("user");
|
$user = addslashes($this->postParam("user"));
|
||||||
|
|
||||||
if (!$ip && !$useragent && !$searchTerm && !$ts && !$te && !$where && !$searchTerm && !$user)
|
if ($where) {
|
||||||
$this->returnJson(["success" => false, "error" => "Нет запроса. Заполните поле \"подстрока\" или введите запрос \"WHERE\" в поле под ним."]);
|
$where = explode(";", $where)[0];
|
||||||
|
|
||||||
$models = explode(",", $this->postParam("models"));
|
|
||||||
|
|
||||||
foreach ($models as $_model) {
|
|
||||||
$model_name = NoSpamPresenter::ENTITIES_NAMESPACE . "\\" . $_model;
|
|
||||||
if (!class_exists($model_name)) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$model = new $model_name;
|
if (!$ip && !$useragent && !$searchTerm && !$ts && !$te && !$where && !$searchTerm && !$user)
|
||||||
|
$this->returnJson(["success" => false, "error" => "Нет запроса. Заполните поле \"подстрока\" или введите запрос \"WHERE\" в поле под ним."]);
|
||||||
|
|
||||||
$c = new \ReflectionClass($model_name);
|
$models = explode(",", $this->postParam("models"));
|
||||||
if ($c->isAbstract() || $c->getName() == NoSpamPresenter::ENTITIES_NAMESPACE . "\\Correspondence") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$db = DatabaseConnection::i()->getContext();
|
foreach ($models as $_model) {
|
||||||
$table = $model->getTableName();
|
$model_name = NoSpamPresenter::ENTITIES_NAMESPACE . "\\" . $_model;
|
||||||
$columns = $db->getStructure()->getColumns($table);
|
if (!class_exists($model_name)) {
|
||||||
|
continue;
|
||||||
if ($searchTerm) {
|
|
||||||
$conditions = [];
|
|
||||||
$need_deleted = false;
|
|
||||||
foreach ($columns as $column) {
|
|
||||||
if ($column["name"] == "deleted") {
|
|
||||||
$need_deleted = true;
|
|
||||||
} else {
|
|
||||||
$conditions[] = "`$column[name]` REGEXP '$searchTerm'";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$conditions = implode(" OR ", $conditions);
|
|
||||||
|
|
||||||
$where = ($this->postParam("where") ? " AND ($conditions)" : "($conditions)");
|
$model = new $model_name;
|
||||||
if ($need_deleted) $where .= " AND (`deleted` = 0)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$rows = [];
|
$c = new \ReflectionClass($model_name);
|
||||||
if ($ip || $useragent || $ts || $te || $user) {
|
if ($c->isAbstract() || $c->getName() == NoSpamPresenter::ENTITIES_NAMESPACE . "\\Correspondence") {
|
||||||
$rows = searchByAdditionalParams($table, $where, $ip, $useragent, $ts, $te, $user);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($rows) === 0) {
|
$db = DatabaseConnection::i()->getContext();
|
||||||
if (!$searchTerm) {
|
$table = $model->getTableName();
|
||||||
if (str_starts_with($where, " AND")) {
|
$columns = $db->getStructure()->getColumns($table);
|
||||||
if ($searchTerm && !$this->postParam("where")) {
|
|
||||||
$where = substr_replace($where, "", 0, strlen(" AND"));
|
if ($searchTerm) {
|
||||||
|
$conditions = [];
|
||||||
|
$need_deleted = false;
|
||||||
|
foreach ($columns as $column) {
|
||||||
|
if ($column["name"] == "deleted") {
|
||||||
|
$need_deleted = true;
|
||||||
} else {
|
} else {
|
||||||
$where = "(" . $this->postParam("where") . ")" . $where;
|
$conditions[] = "`$column[name]` REGEXP '$searchTerm'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$conditions = implode(" OR ", $conditions);
|
||||||
|
|
||||||
|
$where = ($this->postParam("where") ? " AND ($conditions)" : "($conditions)");
|
||||||
|
if ($need_deleted) $where .= " AND (`deleted` = 0)";
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = [];
|
||||||
|
|
||||||
|
if (str_starts_with($where, " AND")) {
|
||||||
|
if ($searchTerm && !$this->postParam("where")) {
|
||||||
|
$where = substr_replace($where, "", 0, strlen(" AND"));
|
||||||
|
} else {
|
||||||
|
$where = "(" . $this->postParam("where") . ")" . $where;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ip || $useragent || $ts || $te || $user) {
|
||||||
|
$rows = searchByAdditionalParams($table, $where, $ip, $useragent, $ts, $te, $user);
|
||||||
|
} else {
|
||||||
if (!$where) {
|
if (!$where) {
|
||||||
$rows = [];
|
$rows = [];
|
||||||
} else {
|
} else {
|
||||||
|
@ -277,99 +278,105 @@ final class NoSpamPresenter extends OpenVKPresenter
|
||||||
$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])) {
|
||||||
foreach ($rows as $key => $object) {
|
foreach ($rows as $key => $object) {
|
||||||
$object = (array)$object;
|
$object = (array)$object;
|
||||||
$_obj = [];
|
$_obj = [];
|
||||||
foreach ($object as $key => $value) {
|
foreach ($object as $key => $value) {
|
||||||
foreach ($columns as $column) {
|
foreach ($columns as $column) {
|
||||||
if ($column["name"] === $key && in_array(strtoupper($column["nativetype"]), ["BLOB", "BINARY", "VARBINARY", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB"])) {
|
if ($column["name"] === $key && in_array(strtoupper($column["nativetype"]), ["BLOB", "BINARY", "VARBINARY", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB"])) {
|
||||||
$value = "[BINARY]";
|
$value = "[BINARY]";
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$_obj[$key] = $value;
|
|
||||||
$_obj["__model_name"] = $_model;
|
|
||||||
}
|
|
||||||
$response[] = $_obj;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$ids = [];
|
|
||||||
|
|
||||||
foreach ($rows as $object) {
|
|
||||||
$object = new $model_name($db->table($table)->get($object->id));
|
|
||||||
if (!$object) continue;
|
|
||||||
$ids[] = $object->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
$log = new NoSpamLog;
|
|
||||||
$log->setUser($this->user->id);
|
|
||||||
$log->setModel($_model);
|
|
||||||
if ($searchTerm) {
|
|
||||||
$log->setRegex($searchTerm);
|
|
||||||
} else {
|
|
||||||
$log->setRequest($where);
|
|
||||||
}
|
|
||||||
$log->setBan_Type((int)$this->postParam("ban"));
|
|
||||||
$log->setCount(count($rows));
|
|
||||||
$log->setTime(time());
|
|
||||||
$log->setItems(implode(",", $ids));
|
|
||||||
$log->save();
|
|
||||||
|
|
||||||
$banned_ids = [];
|
|
||||||
foreach ($rows as $object) {
|
|
||||||
$object = new $model_name($db->table($table)->get($object->id));
|
|
||||||
if (!$object) continue;
|
|
||||||
|
|
||||||
$owner = NULL;
|
|
||||||
$methods = ["getOwner", "getUser", "getRecipient", "getInitiator"];
|
|
||||||
|
|
||||||
if (method_exists($object, "ban")) {
|
|
||||||
$owner = $object;
|
|
||||||
} else {
|
|
||||||
foreach ($methods as $method) {
|
|
||||||
if (method_exists($object, $method)) {
|
|
||||||
$owner = $object->$method();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($owner instanceof User && $owner->getId() === $this->user->id) {
|
|
||||||
if (count($rows) === 1) {
|
|
||||||
$this->returnJson(["success" => false, "error" => "\"Производственная травма\" — Вы не можете блокировать или удалять свой же контент"]);
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array((int)$this->postParam("ban"), [2, 3])) {
|
|
||||||
if ($owner) {
|
|
||||||
$_id = ($owner instanceof Club ? $owner->getId() * -1 : $owner->getId());
|
|
||||||
if (!in_array($_id, $banned_ids)) {
|
|
||||||
if ($owner instanceof User) {
|
|
||||||
$owner->ban("**content-noSpamTemplate-" . $log->getId() . "**", false, time() + $owner->getNewBanTime(), $this->user->id);
|
|
||||||
} else {
|
|
||||||
$owner->ban("Подозрительная активность");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$banned_ids[] = $_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$_obj[$key] = $value;
|
||||||
|
$_obj["__model_name"] = $_model;
|
||||||
}
|
}
|
||||||
|
$response[] = $_obj;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$ids = [];
|
||||||
|
|
||||||
|
foreach ($rows as $object) {
|
||||||
|
$object = new $model_name($db->table($table)->get($object->id));
|
||||||
|
if (!$object) continue;
|
||||||
|
$ids[] = $object->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array((int)$this->postParam("ban"), [1, 3]))
|
$log = new NoSpamLog;
|
||||||
$object->delete();
|
$log->setUser($this->user->id);
|
||||||
|
$log->setModel($_model);
|
||||||
|
if ($searchTerm) {
|
||||||
|
$log->setRegex($searchTerm);
|
||||||
|
} else {
|
||||||
|
$log->setRequest($where);
|
||||||
|
}
|
||||||
|
$log->setBan_Type((int)$this->postParam("ban"));
|
||||||
|
$log->setCount(count($rows));
|
||||||
|
$log->setTime(time());
|
||||||
|
$log->setItems(implode(",", $ids));
|
||||||
|
$log->save();
|
||||||
|
|
||||||
|
$banned_ids = [];
|
||||||
|
foreach ($rows as $object) {
|
||||||
|
$object = new $model_name($db->table($table)->get($object->id));
|
||||||
|
if (!$object) continue;
|
||||||
|
|
||||||
|
$owner = NULL;
|
||||||
|
$methods = ["getOwner", "getUser", "getRecipient", "getInitiator"];
|
||||||
|
|
||||||
|
if (method_exists($object, "ban")) {
|
||||||
|
$owner = $object;
|
||||||
|
} else {
|
||||||
|
foreach ($methods as $method) {
|
||||||
|
if (method_exists($object, $method)) {
|
||||||
|
$owner = $object->$method();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($owner instanceof User && $owner->getId() === $this->user->id) {
|
||||||
|
if (count($rows) === 1) {
|
||||||
|
$this->returnJson(["success" => false, "error" => "\"Производственная травма\" — Вы не можете блокировать или удалять свой же контент"]);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array((int)$this->postParam("ban"), [2, 3])) {
|
||||||
|
$reason = mb_strlen(trim($this->postParam("ban_reason"))) > 0 ? addslashes($this->postParam("ban_reason")) : ("**content-noSpamTemplate-" . $log->getId() . "**");
|
||||||
|
$is_forever = (string)$this->postParam("is_forever") === "true";
|
||||||
|
$unban_time = $is_forever ? 0 : (int)$this->postParam("unban_time") ?? NULL;
|
||||||
|
|
||||||
|
if ($owner) {
|
||||||
|
$_id = ($owner instanceof Club ? $owner->getId() * -1 : $owner->getId());
|
||||||
|
if (!in_array($_id, $banned_ids)) {
|
||||||
|
if ($owner instanceof User) {
|
||||||
|
if (!$unban_time && !$is_forever)
|
||||||
|
$unban_time = time() + $owner->getNewBanTime();
|
||||||
|
|
||||||
|
$owner->ban($reason, false, $unban_time, $this->user->id);
|
||||||
|
} else {
|
||||||
|
$owner->ban("Подозрительная активность");
|
||||||
|
}
|
||||||
|
|
||||||
|
$banned_ids[] = $_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array((int)$this->postParam("ban"), [1, 3]))
|
||||||
|
$object->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
$processed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$processed++;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$this->returnJson(["success" => true, "processed" => $processed, "count" => count($response), "list" => $response]);
|
$this->returnJson(["success" => true, "processed" => $processed, "count" => count($response), "list" => $response]);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->returnJson(["success" => false, "error" => $e->getMessage()]);
|
$this->returnJson(["success" => false, "error" => $e->getMessage()]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,13 +106,31 @@
|
||||||
<span class="nobold">Параметры блокировки:</span>
|
<span class="nobold">Параметры блокировки:</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select name="ban_type" id="noSpam-ban-type">
|
<select name="ban_type" id="noSpam-ban-type" style="width: 140px;">
|
||||||
<option value="1">Только откат</option>
|
<option value="1">Только откат</option>
|
||||||
<option value="2">Только блокировка</option>
|
<option value="2">Только блокировка</option>
|
||||||
<option value="3">Откат и блокировка</option>
|
<option value="3">Откат и блокировка</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr class="banSettings" style="width: 129px; border-top: 1px solid #ECECEC; display: none;">
|
||||||
|
<td>
|
||||||
|
<span class="nobold">Причина:</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="ban-reason" id="ban-reason" style="width: 140px;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="banSettings" style="width: 129px; border-top: 1px solid #ECECEC; display: none;">
|
||||||
|
<td>
|
||||||
|
<span class="nobold">До:</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="datetime-local" name="unban-time" id="unban-time" style="width: 140px;" />
|
||||||
|
<br />
|
||||||
|
<input type="checkbox" name="is_forever" id="is-forever" /> навсегда
|
||||||
|
</td>
|
||||||
|
</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;"/>
|
||||||
|
@ -158,7 +176,6 @@
|
||||||
$("#noSpam-results-loader").show();
|
$("#noSpam-results-loader").show();
|
||||||
$("#noSpam-loader").show();
|
$("#noSpam-loader").show();
|
||||||
|
|
||||||
|
|
||||||
let models = [];
|
let models = [];
|
||||||
$(".model").each(function (i) {
|
$(".model").each(function (i) {
|
||||||
let name = $(this).val();
|
let name = $(this).val();
|
||||||
|
@ -178,6 +195,10 @@
|
||||||
let ts = $("#ts").val() ? Math.floor(new Date($("#ts").val()).getTime() / 1000) : null;
|
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 te = $("#te").val() ? Math.floor(new Date($("#te").val()).getTime() / 1000) : null;
|
||||||
let user = $("#user").val();
|
let user = $("#user").val();
|
||||||
|
let ban_reason = $("#ban-reason").val();
|
||||||
|
let unban_time = $("#unban-time").val() ? Math.floor(new Date($("#unban-time").val()).getTime() / 1000) : null;
|
||||||
|
let is_forever = $("#is-forever").prop('checked');
|
||||||
|
console.log(ban_reason, unban_time, is_forever);
|
||||||
|
|
||||||
await $.ajax({
|
await $.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
|
@ -193,6 +214,9 @@
|
||||||
ts: ts,
|
ts: ts,
|
||||||
te: te,
|
te: te,
|
||||||
user: user,
|
user: user,
|
||||||
|
ban_reason: ban_reason,
|
||||||
|
unban_time: unban_time,
|
||||||
|
is_forever: is_forever,
|
||||||
hash: {=$csrfToken}
|
hash: {=$csrfToken}
|
||||||
},
|
},
|
||||||
success: (response) => {
|
success: (response) => {
|
||||||
|
@ -277,6 +301,17 @@
|
||||||
selectChange(e.target.value);
|
selectChange(e.target.value);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$("#noSpam-ban-type").change(async (e) => {
|
||||||
|
if (e.target.value > 1) {
|
||||||
|
$(".banSettings").show();
|
||||||
|
} else {
|
||||||
|
$("#ban-reason").val(null);
|
||||||
|
$("#unban-time").val(null);
|
||||||
|
$("#is-forever").prop('checked', false);
|
||||||
|
$(".banSettings").hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$("#add-model").on("click", () => {
|
$("#add-model").on("click", () => {
|
||||||
console.log($(".model").length);
|
console.log($(".model").length);
|
||||||
$("#models-list").append(`
|
$("#models-list").append(`
|
||||||
|
|
Loading…
Reference in a new issue