Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions cleantalk.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,24 @@
$apbct->setConnectionReports();
// SFW update sentinel
$apbct->setSFWUpdateSentinel();
// User IP Keeper - used for checkers
$apbct->setLoginIPKeeper();

add_action('wp_login', 'apbct_wp_login_actions', 10, 2);

/**
* Actions for hook 'wp-login'.
* @param $user_login
* @param $wp_user
*
* @return void
*/
function apbct_wp_login_actions($_user_login, $wp_user)
{
global $apbct;
$apbct->login_ip_keeper->addUserIP($wp_user);
apbct_add_admin_ip_to_swf_whitelist($wp_user);
}

// Disabling comments
if ( $apbct->settings['comments__disable_comments__all'] || $apbct->settings['comments__disable_comments__posts'] || $apbct->settings['comments__disable_comments__pages'] || $apbct->settings['comments__disable_comments__media'] ) {
Expand Down
3 changes: 0 additions & 3 deletions inc/cleantalk-common.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ function apbct_array($array)
// It uses for BuddyPress registrations to avoid double checks
$ct_negative_comment = null;


add_action('wp_login', 'apbct_add_admin_ip_to_swf_whitelist', 10, 2);

/**
* Public action 'plugins_loaded' - Loads locale, see http://codex.wordpress.org/Function_Reference/load_plugin_textdomain
*/
Expand Down
28 changes: 13 additions & 15 deletions lib/Cleantalk/ApbctWP/FindSpam/ListTable/BadUsers.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public function prepare_items() // phpcs:ignore PSR1.Methods.CamelCapsMethodNam
*/
public function column_ct_username($item) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
global $apbct;
$user_obj = isset($item['ct_user_obj']) ? $item['ct_user_obj'] : null;
if (is_null($user_obj)) {
return '';
Expand All @@ -95,22 +96,19 @@ public function column_ct_username($item) // phpcs:ignore PSR1.Methods.CamelCaps
$column_content .= '<br/>';

// IP
$user_meta = get_user_meta($user_obj->ID, 'session_tokens', true);
if ( ! empty($user_meta) && is_array($user_meta) ) {
$user_meta = array_values($user_meta);
if ( ! empty($user_meta[0]['ip']) ) {
$ip = $user_meta[0]['ip'];
$column_content .= "<a href='user-edit.php?user_id=$user_obj->ID'>$ip</a>"
. (! $this->apbct->white_label
? "<a href='https://cleantalk.org/blacklists/$ip ' target='_blank'>"
. "&nbsp;<img src='" . APBCT_URL_PATH . "/inc/images/new_window.gif' alt='Ico: open in new window' border='0' style='float:none' />"
. "</a>"
: '');
} else {
$column_content .= esc_html__('No IP address', 'cleantalk-spam-protect');
}
$ip_from_keeper = $apbct->login_ip_keeper->getIP($user_obj->ID);
$ip_from_keeper = null !== $ip_from_keeper
? $ip_from_keeper
: null;
if ( !empty($ip_from_keeper) ) {
$column_content .= "<a href='user-edit.php?user_id=$user_obj->ID'>$ip_from_keeper</a>"
. (! $this->apbct->white_label
? "<a href='https://cleantalk.org/blacklists/$ip_from_keeper ' target='_blank'>"
. "&nbsp;<img src='" . APBCT_URL_PATH . "/inc/images/new_window.gif' alt='Ico: open in new window' border='0' style='float:none' />"
. "</a>"
: '');
} else {
$column_content .= esc_html__('No IP address', 'cleantalk-spam-protect');
$column_content .= esc_html__('No IP adress', 'cleantalk-spam-protect');
}

$actions = array(
Expand Down
26 changes: 12 additions & 14 deletions lib/Cleantalk/ApbctWP/FindSpam/ListTable/Users.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public function column_cb($item) // phpcs:ignore PSR1.Methods.CamelCapsMethodNam
*/
public function column_ct_username($item) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
global $apbct;
$user_obj = $item['ct_username'];
$email = $user_obj->user_email;

Expand All @@ -120,20 +121,17 @@ public function column_ct_username($item) // phpcs:ignore PSR1.Methods.CamelCaps
$column_content .= '<br/>';

// IP
$user_meta = get_user_meta($user_obj->ID, 'session_tokens', true);
if ( ! empty($user_meta) && is_array($user_meta) ) {
$user_meta = array_values($user_meta);
if ( ! empty($user_meta[0]['ip']) ) {
$ip = $user_meta[0]['ip'];
$column_content .= "<a href='user-edit.php?user_id=$user_obj->ID'>$ip</a>"
. (! $this->apbct->white_label
? "<a href='https://cleantalk.org/blacklists/$ip ' target='_blank'>"
. "&nbsp;<img src='" . APBCT_URL_PATH . "/inc/images/new_window.gif' alt='Ico: open in new window' border='0' style='float:none' />"
. "</a>"
: '');
} else {
$column_content .= esc_html__('No IP adress', 'cleantalk-spam-protect');
}
$ip_from_keeper = $apbct->login_ip_keeper->getIP($user_obj->ID);
$ip_from_keeper = null !== $ip_from_keeper
? $ip_from_keeper
: null;
if ( !empty($ip_from_keeper) ) {
$column_content .= "<a href='user-edit.php?user_id=$user_obj->ID'>$ip_from_keeper</a>"
. (! $this->apbct->white_label
? "<a href='https://cleantalk.org/blacklists/$ip_from_keeper ' target='_blank'>"
. "&nbsp;<img src='" . APBCT_URL_PATH . "/inc/images/new_window.gif' alt='Ico: open in new window' border='0' style='float:none' />"
. "</a>"
: '');
} else {
$column_content .= esc_html__('No IP adress', 'cleantalk-spam-protect');
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Cleantalk/ApbctWP/FindSpam/ListTable/UsersScan.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public static function getExtraTableNavInsertDeleteUsers()
if ( defined('APBCT_IS_LOCALHOST') && APBCT_IS_LOCALHOST ) {
$out .= '<div class="ctlk---red bar" style="padding: 10px">';
$out .= '<span>These actions available only for test purpose and buttons are visible only in local env:</span>';
$out .= '<button type="button" class="button button-small action ct_insert_users" style="margin:0 5px">Insert 500 users</button>';
$out .= '<button type="button" class="button button-small action ct_insert_users" style="margin:0 5px">Insert 50 users</button>';
$out .= '<button type="button" class="button button-small action ct_insert_users__delete" style="margin:0 5px">Delete inserted users</button>';
$out .= '</div>';
}
Expand Down
57 changes: 57 additions & 0 deletions lib/Cleantalk/ApbctWP/FindSpam/LoginIPKeeper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Cleantalk\ApbctWP\FindSpam;

use Cleantalk\Common\Helper;
use Cleantalk\Common\TT;

/**
* Class LoginIPKeeper
*
* This class is responsible for managing user IP data, storing it in WordPress options,
* and performing operations such as adding, retrieving, and rotating user IP records.
*/
class LoginIPKeeper
{
/**
* @var string WordPress option name for storing user IP data.
*/
private static $wp_meta_name = '_cleantalk_ip_keeper_data';

/**
* Save the provided in user's IP and last login from session_tokens.
*
* @param \WP_User $wp_user
*
* @return void
*/
public function addUserIP($wp_user)
{
// run record adding to user meta
if ($wp_user instanceof \WP_User && 0 !== $wp_user->ID) {
$session_tokens = get_user_meta($wp_user->ID, 'session_tokens', true);
$data = reset($session_tokens);
if ($data) {
$ip = TT::getArrayValueAsString($data, 'ip');
if ( Helper::ipValidate($ip) ) {
update_user_meta($wp_user->ID, self::$wp_meta_name, $ip);
}
}
}
}

/**
* Retrieves data from user meta of a user by his user ID.
*
* @param int|string $user_id User ID to search for.
*
* @return string|null The selected record property value of user meta data.
* @psalm-suppress PossiblyUnusedMethod
*/
public function getIP($user_id)
{
$user_id = TT::toInt($user_id);
$ip = get_user_meta($user_id, self::$wp_meta_name, true);
return Helper::ipValidate($ip) ? $ip : null;
}
}
50 changes: 17 additions & 33 deletions lib/Cleantalk/ApbctWP/FindSpam/UsersChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,19 @@ private static function removeSkipRoles(array $users, array $skip_roles)
*/
private static function removeUsersWithoutIPEmail(array $users)
{
global $apbct;
foreach ($users as $index => $user) {
if ( (bool)get_user_meta($user->ID, 'ct_bad') === true ) {
delete_user_meta($user->ID, 'ct_marked_as_spam');
unset($users[$index]);
continue;
}

$user_meta = self::getUserMeta($user->ID);
$ip_of_user_meta = TT::getArrayValueAsString($user_meta, 'ip');
$user_ip = ! empty($ip_of_user_meta) ? trim($ip_of_user_meta) : false;
$ip_from_keeper = $apbct->login_ip_keeper->getIP($user->ID);
$ip_from_keeper = null !== $ip_from_keeper
? $ip_from_keeper
: false;
$user_ip = $ip_from_keeper;
$user_email = ! empty($user->user_email) ? trim($user->user_email) : false;

// Validate IP and Email
Expand Down Expand Up @@ -488,6 +491,7 @@ private static function getLogData()
*/
public static function ctGetCsvFile()
{
global $apbct;
AJAXService::checkNonceRestrictingNonAdmins('security');

$text = 'login,email,ip' . PHP_EOL;
Expand All @@ -505,18 +509,15 @@ public static function ctGetCsvFile()

$u = get_users($params);
foreach ( $u as $iValue ) {
// gain IP from meta session_tokens
$ip_of_user_meta = 'N/A';
$user_meta_session_tokens = get_user_meta($iValue->ID, 'session_tokens', true);
if (!empty($user_meta_session_tokens) && is_array($user_meta_session_tokens)) {
$user_meta_array = reset($user_meta_session_tokens);
$user_meta_array = !empty($user_meta_array) && is_array($user_meta_array) ? $user_meta_array : false;
$ip_of_user_meta = $user_meta_array ? TT::getArrayValueAsString($user_meta_array, 'ip') : $ip_of_user_meta;
}
// gain IP from keeper
$ip_from_keeper = $apbct->login_ip_keeper->getIP($iValue->ID);
$ip_from_keeper = null !== $ip_from_keeper
? $ip_from_keeper
: 'N/A';

$text .= $iValue->user_login . ',';
$text .= $iValue->data->user_email . ',';
$text .= $ip_of_user_meta;
$text .= $ip_from_keeper;
$text .= PHP_EOL;
}

Expand All @@ -535,7 +536,7 @@ public static function ctAjaxInsertUsers()
{
AJAXService::checkNonceRestrictingNonAdmins('security');

global $wpdb;
global $wpdb, $apbct;

//* TEST DELETION
if ( ! empty(Post::get('delete')) ) {
Expand All @@ -555,7 +556,7 @@ public static function ctAjaxInsertUsers()
}

// TEST INSERTION
$to_insert = 500;
$to_insert = 50;
$query = 'SELECT network FROM `' . APBCT_TBL_FIREWALL_DATA . '` LIMIT ' . $to_insert . ';';

$result = $wpdb->get_results(
Expand Down Expand Up @@ -589,7 +590,7 @@ public static function ctAjaxInsertUsers()
}

update_user_meta($curr_user->ID, 'session_tokens', array($rnd => array('ip' => $ips[$i])));

$apbct->login_ip_keeper->addUserIP($curr_user);
if ( is_int($user_id) ) {
$inserted++;
}
Expand All @@ -606,7 +607,7 @@ public static function ctAjaxDeleteAllUsers($count_all = 0)
{
AJAXService::checkNonceRestrictingNonAdmins('security');

global $wpdb;
global $wpdb, $apbct;

$r = self::getCountSpammers();

Expand Down Expand Up @@ -729,23 +730,6 @@ public static function getCountBadUsers()
return (int) $count_bad;
}

/**
* @param $user_id
*
* @return array
*/
public static function getUserMeta($user_id)
{
$user_meta = get_user_meta($user_id, 'session_tokens', true);

if ( is_array($user_meta) ) {
$user_meta = array_values($user_meta);
return reset($user_meta);
}

return array();
}

/**
* All users checking
*
Expand Down
14 changes: 14 additions & 0 deletions lib/Cleantalk/ApbctWP/State.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use AllowDynamicProperties;
use ArrayObject;
use Cleantalk\ApbctWP\FindSpam\LoginIPKeeper;
use Cleantalk\ApbctWP\Firewall\SFWUpdateSentinel;

/**
Expand Down Expand Up @@ -236,6 +237,9 @@ class State extends \Cleantalk\Common\State
'wl_support_faq' => 'https://wordpress.org/plugins/cleantalk-spam-protect/faq/',
'wl_support_url' => 'https://wordpress.org/support/plugin/cleantalk-spam-protect',
'wl_support_email' => 'support@cleantalk.org',

//IP keeper data
'ip_keeper_data' => array()
);

/**
Expand Down Expand Up @@ -379,6 +383,11 @@ class State extends \Cleantalk\Common\State
*/
public $sfw_update_sentinel;

/**
* @var LoginIPKeeper
*/
public $login_ip_keeper;

private $auto_save_defaults_list = array();

public $errors;
Expand Down Expand Up @@ -993,6 +1002,11 @@ public function setSFWUpdateSentinel()
$this->sfw_update_sentinel = new SFWUpdateSentinel();
}

public function setLoginIPKeeper()
{
$this->login_ip_keeper = new \Cleantalk\ApbctWP\FindSpam\LoginIPKeeper();
}

/**
* Get connection reports object. Init one if the connection_reports attribute
* is empty or not an object of ConnectionReports
Expand Down
55 changes: 55 additions & 0 deletions tests/ApbctWP/LoginIPKeeperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

use PHPUnit\Framework\TestCase;
use Cleantalk\ApbctWP\FindSpam\LoginIPKeeper;

class LoginIPKeeperTest extends TestCase
{
/**
* @var LoginIPKeeper
*/
private $loginIPKeeper;

protected function setUp(): void
{
$this->loginIPKeeper = new LoginIPKeeper();
}

public function testAddRecord()
{
// Create a WordPress user
$user_id = wp_create_user('testuser', 'password', 'testuser@example.com');
$wp_user = get_user_by('id', $user_id);

// Set session tokens
$session_tokens = [
'token1' => [
'ip' => '192.168.1.1',
],
];
update_user_meta($wp_user->ID, 'session_tokens', $session_tokens);

// Call the method
$this->loginIPKeeper->addUserIP($wp_user);

// Assert that the meta record was updated
$ip = get_user_meta($wp_user->ID, '_cleantalk_ip_keeper_data', true);

$this->assertEquals('192.168.1.1', $ip);
}

public function testGetMetaRecordValue()
{
// Create a WordPress user
$user_id = wp_create_user('testuser2', 'password', 'testuser2@example.com');

// Set meta data
update_user_meta($user_id, '_cleantalk_ip_keeper_data', '192.168.1.1');

// Call the method
$result = $this->loginIPKeeper->getIP($user_id);

// Assert the result
$this->assertEquals('192.168.1.1', $result);
}
}