Making WordPress.org

Changeset 11620


Ignore:
Timestamp:
03/02/2022 06:07:14 AM (3 years ago)
Author:
dd32
Message:

Login: Add an admin UI to manage blocked words/phrases/email domains for registration spam.

This also allows whitelisting/blocking individual IP addresses.

Location:
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/admin/ui.php

    r11262 r11620  
    1313        1
    1414    );
     15
     16    add_submenu_page(
     17        'user-registrations',
     18        'Settings',
     19        'Settings',
     20        'promote_users',
     21        'user-registration-settings',
     22        'wporg_login_admin_settings_page',
     23        'dashicons-admin-settings'
     24    );
     25
    1526});
    1627
     
    97108}
    98109
     110function wporg_login_admin_settings_page() {
     111    if ( $_POST && check_admin_referer( 'update_login_settings' ) ) {
     112        $recaptcha_v3_threshold = wp_unslash( $_POST['recaptcha_v3_threshold'] ?? '' );
     113        if ( $recaptcha_v3_threshold ) {
     114            $recaptcha_v3_threshold = sprintf( "%.1f", $recaptcha_v3_threshold );
     115            update_option( 'recaptcha_v3_threshold', $recaptcha_v3_threshold );
     116        }
     117
     118        $block_words = wp_unslash( $_POST['registration_block_words'] ?? '' );
     119        if ( $block_words ) {
     120            $block_words = explode( "\n", $block_words );
     121            $block_words = array_values( array_unique( array_filter( array_map( 'trim', $block_words ) ) ) );
     122
     123            // Sanity; Don't let it change more than 20%.
     124            if ( count( $block_words ) < count( get_option( 'registration_block_words' ) ) * 0.8 ) {
     125                wp_die( "Are you sure you wanted to do that? You attempted to change registration_block_words to less than 80% of the previous value." );
     126            }
     127
     128            update_option( 'registration_block_words', $block_words );
     129        }
     130
     131        $banned_email_domains = wp_unslash( $_POST['banned_email_domains'] ?? '' );
     132        if ( $banned_email_domains ) {
     133            $banned_email_domains = explode( "\n", $banned_email_domains );
     134            $banned_email_domains = array_values( array_unique( array_filter( array_map( 'trim', $banned_email_domains ) ) ) );
     135
     136            // Sanity; Don't let it change more than 20%.
     137            if ( count( $banned_email_domains ) < count( get_site_option( 'banned_email_domains' ) ) * 0.8 ) {
     138                wp_die( "Are you sure you wanted to do that? You attempted to change banned_email_domains to less than 80% of the previous value." );
     139            }
     140
     141            // Network-wide option.
     142            update_site_option( 'banned_email_domains', $banned_email_domains );
     143        }
     144
     145        $ip_block = wp_unslash( $_POST['ip_block'] ?? '' );
     146        $ip_allow = wp_unslash( $_POST['ip_allow'] ?? '' );
     147        if ( $ip_block || $ip_allow ) {
     148            wp_cache_add_global_groups( array( 'registration-limit' ) );
     149
     150            if ( $ip_allow ) {
     151                wp_cache_set( $ip_allow, 'whitelist', 'registration-limit', DAY_IN_SECONDS );
     152            }
     153            if ( $ip_block ) {
     154                wp_cache_set( $ip_block, 999, 'registration-limit', DAY_IN_SECONDS );
     155            }
     156        }
     157
     158        echo '<div class="notice notice-success"><p>Settings saved.</p></div>';
     159    }
     160
     161    echo '<div class="wrap">';
     162    echo '<h1 class="wp-heading-inline">Registration &amp; Login Settings</h1>';
     163    echo '<hr class="wp-header-end">';
     164    echo '<form method="POST">';
     165    wp_nonce_field( 'update_login_settings' );
     166    echo '<table class="form-table">';
     167
     168    printf(
     169        '<tr>
     170            <th>reCaptcha v3 low-score threshold for Registration</th>
     171            <td><input name="recaptcha_v3_threshold" type="number" min="0.0" max="1.0" step="0.1" name="" value="%s"></td>
     172        </tr>',
     173        esc_attr( get_option( 'recaptcha_v3_threshold', 0.2 ) )
     174    );
     175
     176    printf(
     177        '<tr>
     178            <th>Block words for registration</th>
     179            <td>
     180                <textarea name="registration_block_words" rows="10" cols="80">%s</textarea>
     181                <p><em>Any registrations with any of these phrases within their username, email address, or profile fields will be put into manual review. One phrase per line.</em></p>
     182            </td>
     183        </tr>',
     184        esc_textarea( implode( "\n", get_option( 'registration_block_words', [] ) ) )
     185    );
     186
     187    printf(
     188        '<tr>
     189            <th>Banned Email Domains</th>
     190            <td>
     191                <textarea name="banned_email_domains" rows="10" cols="80">%s</textarea>
     192                <p id="banned-email-domains-desc"><em>These email domains are WordPress.org-wide. No emails will be sent to them. No users can set their email address to it.<br>One email domain per line. This is the same list as <a href="https://wordpress.org/wp-admin/network/settings.php#banned_email_domains">https://wordpress.org/wp-admin/network/settings.php#banned_email_domains</a>.</em></p>
     193            </td>
     194        </tr>',
     195        esc_textarea( implode( "\n", get_site_option( 'banned_email_domains', [] ) ) ),
     196    );
     197
     198    echo '<tr>
     199        <th>IP Block for 24hrs</th>
     200        <td>
     201            <input class="regular-text" type="text" name="ip_block" minlength="7" maxlength="15" size="15" pattern="^((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$" placeholder="xxx.xxx.xxx.xxx">
     202            <p><em>One IP only. IP will be blocked from registrations for 24hrs. </em></p>
     203        </td>
     204    </tr>';
     205
     206    echo '<tr>
     207        <th>IP Allow for 24hrs</th>
     208        <td>
     209            <input class="regular-text" type="text" name="ip_allow" minlength="7" maxlength="15" size="15" pattern="^((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$" placeholder="xxx.xxx.xxx.xxx">
     210            <p><em>One IP only. IP will bypass per-IP limits on registrations for 24hrs. Will also bypass Jetpack Protect login limiter.</em></p>
     211        </td>
     212    </tr>';
     213
     214    echo '</table>';
     215    echo '<p class="submit">
     216        <input type="submit" name="submit" id="submit" class="button button-primary" value="Save Changes">
     217    </p>';
     218    echo '</form>';
     219    echo '</div>';
     220}
     221
    99222add_action( 'admin_post_login_resend_email', function() {
    100223    if ( ! current_user_can( 'promote_users' ) ) {
     
    231354
    232355        // bbPress roles still aren't quite right, need to switch away and back..
    233         // This is hacky, but otherwise the bbp_set_user_role() call below will appear to succeed, but no role aleration will actually happen.
     356        // This is hacky, but otherwise the bbp_set_user_role() call below will appear to succeed, but no role alteration will actually happen.
    234357        restore_current_blog();
    235358        switch_to_blog( WPORG_SUPPORT_FORUMS_BLOGID );
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/functions-registration.php

    r11505 r11620  
    4646
    4747/**
    48  * Handles creating a "Pending" registration that will later be converted to an actual user  account.
     48 * Handles creating a "Pending" registration that will later be converted to an actual user account.
    4949 */
    5050function wporg_login_create_pending_user( $user_login, $user_email, $meta = array() ) {
     
    9696    }
    9797
     98    $passes_block_words = wporg_login_check_against_block_words( $pending_user );
     99
    98100    $pending_user['cleared'] = (
    99101        'allow' === $pending_user['meta']['heuristics'] &&
    100         (float)$pending_user['scores']['pending'] >= (float) get_option( 'recaptcha_v3_threshold', 0.2 )
     102        (float)$pending_user['scores']['pending'] >= (float) get_option( 'recaptcha_v3_threshold', 0.2 ) &&
     103        $passes_block_words
    101104    );
    102105
     
    398401    }
    399402
     403    // If not manually approved, check against block_words.
     404    if ( $pending_user['cleared'] < 2 ) {
     405        $passes_block_words = wporg_login_check_against_block_words( $pending_user );
     406        if ( ! $passes_block_words ) {
     407            $pending_user['cleared'] = 0;
     408        }
     409    }
     410
    400411    if ( $pending_user ) {
    401412        wporg_update_pending_user( $pending_user );
     
    407418    return true;
    408419}
     420
     421/**
     422 * Check a pending user object against the 'block words' setting.
     423 *
     424 * @return bool
     425 */
     426function wporg_login_check_against_block_words( $user ) {
     427    $block_words = get_option( 'registration_block_words', [] );
     428
     429    foreach ( $block_words as $word ) {
     430        if (
     431            false !== stripos( $user['user_login'], $word ) ||
     432            false !== stripos( $user['user_email'], $word ) ||
     433            false !== stripos( $user['meta']['url'], $word ) ||
     434            false !== stripos( $user['meta']['from'], $word ) ||
     435            false !== stripos( $user['meta']['occ'], $word ) ||
     436            false !== stripos( $user['meta']['interests'], $word )
     437        ) {
     438            return false;
     439        }
     440    }
     441
     442    return true;
     443}
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/pending-create.php

    r11380 r11620  
    99
    1010// Migrate to cookies.
    11 if ( !empty( $sso::$matched_route_params['confirm_user'] ) ) {
     11if ( ! empty( $sso::$matched_route_params['confirm_user'] ) ) {
    1212    setcookie( 'wporg_confirm_user', $sso::$matched_route_params['confirm_user'], time()+DAY_IN_SECONDS, '/register/', 'login.wordpress.org', true, true );
    1313    setcookie( 'wporg_confirm_key',  $sso::$matched_route_params['confirm_key'],  time()+DAY_IN_SECONDS, '/register/', 'login.wordpress.org', true, true );
     
    158158    </p>
    159159
    160     <div class="user-pass1-wrap">
     160    <div class="user-pass1-wrap" <?php echo ( $pending_user['cleared'] ? '' : "style='display:none;'" ); ?>>
    161161        <p>
    162162            <label for="pass1"><?php _e( 'Password', 'wporg' ); ?></label>
     
    187187
    188188    <p class="login-submit">
    189         <input data-sitekey="<?php echo esc_attr( RECAPTCHA_INVIS_PUBKEY ); ?>" data-callback='onSubmit' type="submit" name="wp-submit" id="wp-submit" class="g-recaptcha button button-primary button-large" value="<?php esc_attr_e( 'Create Account', 'wporg' ); ?>" />
     189        <input data-sitekey="<?php echo esc_attr( RECAPTCHA_INVIS_PUBKEY ); ?>" data-callback='onSubmit' type="submit" name="wp-submit" id="wp-submit" class="g-recaptcha button button-primary button-large" value="<?php ( $pending_user['cleared'] ? esc_attr_e( 'Create Account', 'wporg' ) : esc_attr_e( 'Save Profile Information', 'wporg' ) ); ?>" />
    190190    </p>
    191191
Note: See TracChangeset for help on using the changeset viewer.