Merge pull request #908 from Zankaria/ip-notes-queries-refactor

Add a wrapper for ip notes
This commit is contained in:
Lorenzo Yario 2025-02-22 14:49:58 -06:00 committed by GitHub
commit 3230aaec58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 110 additions and 29 deletions

View File

@ -0,0 +1,76 @@
<?php
namespace Vichan\Data;
use Vichan\Data\Driver\CacheDriver;
class IpNoteQueries {
private \PDO $pdo;
private CacheDriver $cache;
public function __construct(\PDO $pdo, CacheDriver $cache) {
$this->pdo = $pdo;
$this->cache = $cache;
}
/**
* Get all the notes relative to an IP.
*
* @param string $ip The IP of the notes. THE STRING IS NOT VALIDATED.
* @return array Returns an array of notes sorted by the most recent. Includes the username of the mods.
*/
public function getByIp(string $ip) {
$ret = $this->cache->get("ip_note_queries_$ip");
if ($ret !== null) {
return $ret;
}
$query = $this->pdo->prepare('SELECT `ip_notes`.*, `username` FROM `ip_notes` LEFT JOIN `mods` ON `mod` = `mods`.`id` WHERE `ip` = :ip ORDER BY `time` DESC');
$query->bindValue(':ip', $ip);
$query->execute();
$ret = $query->fetchAll(\PDO::FETCH_ASSOC);
$this->cache->set("ip_note_queries_$ip", $ret);
return $ret;
}
/**
* Creates a new note relative to the given ip.
*
* @param string $ip The IP of the note. THE STRING IS NOT VALIDATED.
* @param int $mod_id The id of the mod who created the note.
* @param string $body The text of the note.
* @return void
*/
public function add(string $ip, int $mod_id, string $body) {
$query = $this->pdo->prepare('INSERT INTO `ip_notes` (`ip`, `mod`, `time`, `body`) VALUES (:ip, :mod, :time, :body)');
$query->bindValue(':ip', $ip);
$query->bindValue(':mod', $mod_id);
$query->bindValue(':time', time());
$query->bindValue(':body', $body);
$query->execute();
$this->cache->delete("ip_note_queries_$ip");
}
/**
* Delete a note only if it's of a particular IP address.
*
* @param int $id The id of the note.
* @param int $ip The expected IP of the note. THE STRING IS NOT VALIDATED.
* @return bool True if any note was deleted.
*/
public function deleteWhereIp(int $id, string $ip): bool {
$query = $this->pdo->prepare('DELETE FROM `ip_notes` WHERE `ip` = :ip AND `id` = :id');
$query->bindValue(':ip', $ip);
$query->bindValue(':id', $id);
$query->execute();
$any = $query->rowCount() != 0;
if ($any) {
$this->cache->delete("ip_note_queries_$ip");
}
return $any;
}
}

View File

@ -2,7 +2,7 @@
namespace Vichan;
use Vichan\Data\Driver\{CacheDriver, HttpDriver, ErrorLogLogDriver, FileLogDriver, LogDriver, StderrLogDriver, SyslogLogDriver};
use Vichan\Data\ReportQueries;
use Vichan\Data\{IpNoteQueries, ReportQueries};
use Vichan\Service\HCaptchaQuery;
use Vichan\Service\SecureImageCaptchaQuery;
use Vichan\Service\ReCaptchaQuery;
@ -106,6 +106,7 @@ function build_context(array $config): Context {
$auto_maintenance = (bool)$c->get('config')['auto_maintenance'];
$pdo = $c->get(\PDO::class);
return new ReportQueries($pdo, $auto_maintenance);
}
},
IpNoteQueries::class => fn($c) => new IpNoteQueries($c->get(\PDO::class), $c->get(CacheDriver::class)),
]);
}

View File

@ -4,6 +4,9 @@
* Copyright (c) 2010-2013 Tinyboard Development Group
*/
use Vichan\Context;
use Vichan\Data\IpNoteQueries;
defined('TINYBOARD') or exit;
class Filter {
@ -149,17 +152,13 @@ class Filter {
}
}
public function action() {
public function action(Context $ctx) {
global $board;
$this->add_note = isset($this->add_note) ? $this->add_note : false;
if ($this->add_note) {
$query = prepare('INSERT INTO ``ip_notes`` VALUES (NULL, :ip, :mod, :time, :body)');
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
$query->bindValue(':mod', -1);
$query->bindValue(':time', time());
$query->bindValue(':body', "Autoban message: ".$this->post['body']);
$query->execute() or error(db_error($query));
$note_queries = $ctx->get(IpNoteQueries::class);
$note_queries->add($_SERVER['REMOTE_ADDR'], -1, 'Autoban message: ' . $this->post['body']);
}
if (isset($this->action)) {
switch($this->action) {
@ -233,7 +232,7 @@ function purge_flood_table() {
query("DELETE FROM ``flood`` WHERE `time` < $time") or error(db_error());
}
function do_filters(array $post) {
function do_filters(Context $ctx, array $post) {
global $config;
if (!isset($config['filters']) || empty($config['filters'])) {
@ -268,7 +267,7 @@ function do_filters(array $post) {
$filter = new Filter($filter_array);
$filter->flood_check = $flood_check;
if ($filter->check($post)) {
$filter->action();
$filter->action($ctx);
}
}

View File

@ -3,7 +3,7 @@
* Copyright (c) 2010-2013 Tinyboard Development Group
*/
use Vichan\Context;
use Vichan\Data\ReportQueries;
use Vichan\Data\{IpNoteQueries, ReportQueries};
use Vichan\Functions\Format;
use Vichan\Functions\Net;
use Vichan\Data\Driver\CacheDriver;
@ -878,16 +878,24 @@ function mod_ip_remove_note(Context $ctx, $cloaked_ip, $id) {
$ip = uncloak_ip($cloaked_ip);
$config = $ctx->get('config');
if (!hasPermission($config['mod']['remove_notes']))
if (!hasPermission($config['mod']['remove_notes'])) {
error($config['error']['noaccess']);
}
if (filter_var($ip, FILTER_VALIDATE_IP) === false)
if (\filter_var($ip, \FILTER_VALIDATE_IP) === false) {
error("Invalid IP address.");
}
$query = prepare('DELETE FROM ``ip_notes`` WHERE `ip` = :ip AND `id` = :id');
$query->bindValue(':ip', $ip);
$query->bindValue(':id', $id);
$query->execute() or error(db_error($query));
if (!\is_numeric($id)) {
error('Invalid note ID');
}
$queries = $ctx->get(IpNoteQueries::class);
$deleted = $queries->deleteWhereIp((int)$id, $ip);
if (!$deleted) {
error("Note $id does not exist for $cloaked_ip");
}
modLog("Removed a note for <a href=\"?/IP/{$cloaked_ip}\">{$cloaked_ip}</a>");
@ -928,12 +936,9 @@ function mod_ip(Context $ctx, $cip) {
$_POST['note'] = escape_markup_modifiers($_POST['note']);
markup($_POST['note']);
$query = prepare('INSERT INTO ``ip_notes`` VALUES (NULL, :ip, :mod, :time, :body)');
$query->bindValue(':ip', $ip);
$query->bindValue(':mod', $mod['id']);
$query->bindValue(':time', time());
$query->bindValue(':body', $_POST['note']);
$query->execute() or error(db_error($query));
$note_queries = $ctx->get(IpNoteQueries::class);
$note_queries->add($ip, $mod['id'], $_POST['note']);
modLog("Added a note for <a href=\"?/IP/{$cip}\">{$cip}</a>");
@ -980,9 +985,9 @@ function mod_ip(Context $ctx, $cip) {
}
if (hasPermission($config['mod']['view_notes'])) {
$query = prepare("SELECT ``ip_notes``.*, `username` FROM ``ip_notes`` LEFT JOIN ``mods`` ON `mod` = ``mods``.`id` WHERE `ip` = :ip ORDER BY `time` DESC");
$query->bindValue(':ip', $ip);
$query->execute() or error(db_error($query));
$note_queries = $ctx->get(IpNoteQueries::class);
$note_queries->getByIp($ip);
$args['notes'] = $query->fetchAll(PDO::FETCH_ASSOC);
}

View File

@ -1062,7 +1062,7 @@ if (isset($_POST['delete'])) {
if (!hasPermission($config['mod']['bypass_filters'], $board['uri']) && !$dropped_post) {
require_once 'inc/filters.php';
do_filters($post);
do_filters($context, $post);
}
if ($post['has_file']) {
@ -1245,7 +1245,7 @@ if (isset($_POST['delete'])) {
// Do filters again if OCRing
if ($config['tesseract_ocr'] && !hasPermission($config['mod']['bypass_filters'], $board['uri']) && !$dropped_post) {
do_filters($post);
do_filters($context, $post);
}
if (!hasPermission($config['mod']['postunoriginal'], $board['uri']) && $config['robot_enable'] && checkRobot($post['body_nomarkup']) && !$dropped_post) {