• John Walker posted an update in the group Group logo of UpdatesUpdates 1 month, 2 weeks ago

    2019 June 30

    Today's project is doing something about the fact that when new
    users sign up and are placed in the Pending category we are not
    shown their IP address.  This makes it harder to vet these
    sign-ups by checking in spam databases.  Code in the Stop
    Spammers plug-in:
    adds a "User IP" column to the administrator Users page, but
    does not show this information for Pending users (those who have
    not responded to a user registration E-mail).  First of all,
    let's see where this elusive IP address is hidden.  It's not in
    the wp_users table where you might first look.  To get the last
    IP address from which a user accessed the site, here's how you
    do it from MySQL.

    Log in to MySQL as Ratburger and select the Ratburger-db database. mysql -u Ratburger -p Password:

    USE Ratburger-db; Look up the user name in the wp_users table. SELECT * FROM wp_users WHERE user_login = "Lousewort"; +-----+--------------+------------------------------------+---------------+--------------------------------------+----------+---------------------+---------------------+-------------+--------------+ | ID | user_login | user_pass | user_nicename | user_email | user_url | user_registered | user_activation_key | user_status | display_name | +-----+--------------+------------------------------------+---------------+--------------------------------------+----------+---------------------+---------------------+-------------+--------------+ | 362 | Lousewort | REDACTED | lousewort | | | 2019-06-30 09:31:01 | | 2 | F. Lousewort | +-----+--------------+------------------------------------+---------------+--------------------------------------+----------+---------------------+---------------------+-------------+--------------+ Now take the ID (party card number) for the user and retrieve the signup_ip field from the wp_usermeta table. SELECT * FROM wp_usermeta WHERE user_id = 362 AND meta_key = "signup_ip"; +----------+---------+-----------+---------------+ | umeta_id | user_id | meta_key | meta_value | +----------+---------+-----------+---------------+ | 8759 | 362 | signup_ip | | +----------+---------+-----------+---------------+ The meta_value will give you the IP address.

    Within the WordPress code, you retrieve this information with: $ip = get_user_meta($user_id, 'signup_ip', true); where $user_id is the numerical user ID.

    Now, the easiest (and truth be told) sufficient way to avoid all of this faffing around is to add the IP address to the User Approval E-mail which is sent by the New User Approve plug-in in ~/plug/new-user-approve/new-user-approve.php function admin_approval_email(), which includes a hook, "new_user_approve_request_approval_message" which filters the assembled message before sending it to administrators. This hook function is called with arguments of the message as originally composed, the $user_login (user name), and the user's E-mail. Irritatingly, it does not pass the user ID, so we have to look that up in the user database in our hook function.

    Naturally, this being WordPress, there is one more twist of the knife awaiting anybody who undertakes this seemingly straightforward task. At the time admin_approval_email() gets called, Stop Spammer Registration has not yet set the "signup_ip" user meta field to the requester's IP address, so when you retrieve it, you get nothing. In the rb_add_IP_address_to_user_approve_Email() function I added to ~/theme/functions.php to filter the User Approval E-mail, I have to obtain the user's IP address directly from $_SERVER['REMOTE_ADDR'] instead of the database. This appears to work, and has now been tested with both IPv4 and IPv6 addresses. This takes care of adding the IP address to the notification E-mail, and required no local code: everything is done in the theme's functions.php file by filtering the E-mail message in the New User Approve plug-in.

    Now we move on to adding the IP address to the pending users table which is generated by: ~/plug/buddypress/bp-members/classes/class-bp-members-list-table.php (note that there is another, very similar, file called class-bp-members-ms-list-table.php which is used by lemmings who enable "multi-site" mode shortly before their WordPress empire collapses like the one-hoss shay).

    The columns in this table are defined by get_columns(), which returns an array of column names that can be filtered by "bp_members_signup_columns". I added a new rb_bp_members_signup_columns() function to ~/theme/functions.php which patches itself into this chain and defines a new column: 'ip_addr' => __( 'IP Address', 'ratburger' ), in the table. When the Pending Users table is displayed, any column whose name is not predefined in class-bp-members-list-table.php results in a call to column_default() in that file, where user code may add a filter on "bp_members_signup_custom_column". I added such a filter in ~/theme/functions.php, pointing to a new function, rb_bp_members_signup_custom_column() in that file. It, in turn, checks for our new "ip_addr" column and, if that's the one being rendered, looks up the user ID with get_user_by() (the $signup_object->id field is a cruel joke which has nothing to do with the actual ID), then calls get_user_meta() to retrieve the IP address, which it emits into the output stream. Again, as all of this is in ~/theme/functions.php, there is no local code added to any core or plug-in file to support this new feature.

    To aid in debugging code which has to run as Administrator, I added an RB_chef() function to ~/theme/functions.php which returns true only when running under my administrator account.

    Committed today's changes (Build 325) and published on GitHub.