WordPress.org

Making WordPress.org

Changeset 9146


Ignore:
Timestamp:
09/23/2019 03:52:23 AM (2 years ago)
Author:
dd32
Message:

Login: Store user registrations in a custom table until they confirm their email address (at which time, we create the actual wp_users records).

This is to combat the significant number of unconfirmed accounts that are created, by separating them it's easier to purge them periodically, but also easier to add extra anti-spam checks as needed.

See #4739.

Location:
sites/trunk
Files:
7 edited
2 copied

Legend:

Unmodified
Added
Removed
  • sites/trunk/common/includes/wporg-sso/wp-plugin.php

    r7695 r9146  
    145145            // Extend registration paths only when registration is open.
    146146            if ( 'user' === get_site_option( 'registration', 'none' ) ) {
     147                // New "pending" registration flow.
     148                $this->valid_sso_paths['pending-profile']  = '/register/create-profile/(?P<profile_user>[^/]+)/(?P<profile_key>[^/]+)';
     149                $this->valid_sso_paths['pending-create']   = '/register/create/(?P<confirm_user>[^/]+)/(?P<confirm_key>[^/]+)';
     150
     151                // Old "Create immediately" flow, kept as in-progress registrations need it.
    147152                $this->valid_sso_paths['register-profile'] = '/register/profile/(?P<profile_user>[^/]+)/(?P<profile_nonce>[^/]+)';
    148153                $this->valid_sso_paths['register-confirm'] = '/register/confirm/(?P<confirm_user>[^/]+)/(?P<confirm_key>[^/]+)';
     154
     155                // Primary registration route.
    149156                $this->valid_sso_paths['register']         = '/register';
    150157            }
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/functions-registration.php

    r6493 r9146  
    1313
    1414    $resp = wp_remote_post( 'https://www.google.com/recaptcha/api/siteverify', array( 'body' => $verify ) );
    15 
    1615    if ( is_wp_error( $resp ) || 200 != wp_remote_retrieve_response_code( $resp ) ) {
    1716        return false;
     
    2423
    2524/**
    26  * Handles registrations and redirects thereafter
    27  */
    28 function wporg_login_create_user( $user_login, $user_email, $user_mailinglist = false ) {
    29     global $wpdb;
     25 * Handles creating a "Pending" registration that will later be converted to an actual user  account.
     26 */
     27function wporg_login_create_pending_user( $user_login, $user_email, $user_mailinglist = false ) {
     28    global $wpdb, $wp_hasher;
    3029
    3130    // Allow for w.org plugins to block registrations based on spam checks, etc.
     
    3736    }
    3837
    39     $user_id = wpmu_create_user( wp_slash( $user_login ), wp_generate_password(), wp_slash( $user_email ) );
    40     if ( ! $user_id ) {
     38    $activation_key = wp_generate_password( 24, false, false );
     39    $profile_key    = wp_generate_password( 24, false, false );
     40
     41    $hashed_activation_key = time() . ':' . wp_hash_password( $activation_key );
     42    $hashed_profile_key    = time() . ':' . wp_hash_password( $profile_key );
     43
     44    $pending_user = array(
     45        'user_login' => $user_login,
     46        'user_email' => $user_email,
     47        'user_registered' => gmdate('Y-m-d  H:i:s'),
     48        'user_activation_key' => $hashed_activation_key,
     49        'user_profile_key' => $hashed_profile_key,
     50        'meta' => array(
     51            'user_mailinglist' => $user_mailinglist,
     52            'registration_ip'  => $_SERVER['REMOTE_ADDR'], // Spam & fraud control. Will be discarded after the account is created.
     53        ),
     54        'scores' => array()
     55    );
     56
     57    $inserted = wporg_update_pending_user( $pending_user );
     58    if ( ! $inserted ) {
    4159        wp_die( __( 'Error! Something went wrong with your registration. Try again?', 'wporg' ) );
    42     }
    43 
    44     // Insert a hashed activation key
    45     $activation_key = wp_generate_password( 24, false, false );
    46     if ( empty( $wp_hasher ) ) {
    47         require_once ABSPATH . WPINC . '/class-phpass.php';
    48         $wp_hasher = new PasswordHash( 8, true );
    49     }
    50     $hashed_activation_key = time() . ':' . $wp_hasher->HashPassword( $activation_key );
    51 
    52     $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed_activation_key ), array( 'ID' => $user_id ) );
    53     clean_user_cache( $user_id );
    54 
    55     if ( $user_mailinglist ) {
    56         update_user_meta( $user_id, 'notify_list', 'true' );
    5760    }
    5861
     
    6265    $body .= sprintf( __( 'Your username is: %s', 'wporg' ), $user_login ) . "\n";
    6366    $body .= __( 'You can create a password at the following URL:', 'wporg' ) . "\n";
    64     $body .= home_url( "/register/confirm/{$user_login}/{$activation_key}/" );
     67    $body .= home_url( "/register/create/{$user_login}/{$activation_key}/" );
    6568    $body .= "\n\n";
    6669    $body .= __( '-- The WordPress.org Team', 'wporg' );
     
    7578    );
    7679
    77     wp_set_current_user( $user_id );
    78     $nonce = wp_create_nonce( 'login-register-profile-edit' );
    79     wp_set_current_user( 0 );
    80 
    81     wp_safe_redirect( '/register/profile/' . $user_login . '/' . $nonce );
     80    $url = home_url( sprintf(
     81        '/register/create-profile/%s/%s/',
     82        $user_login,
     83        $profile_key
     84    ) );
     85
     86    wp_safe_redirect( $url );
    8287    die();
    8388}
    8489
    85 function wporg_login_save_profile_fields() {
     90/**
     91 * Fetches a pending user record from the database by username or Email.
     92 */
     93function wporg_get_pending_user( $login_or_email ) {
     94    global $wpdb;
     95
     96    $pending_user = $wpdb->get_row( $wpdb->prepare(
     97        "SELECT * FROM `{$wpdb->base_prefix}user_pending_registrations` WHERE ( `user_login` = %s OR `user_email` = %s ) LIMIT 1",
     98        $login_or_email,
     99        $login_or_email
     100    ), ARRAY_A );
     101
     102    if ( ! $pending_user ) {
     103        return false;
     104    }
     105
     106    $pending_user['meta']   = json_decode( $pending_user['meta'], true );
     107    $pending_user['scores'] = json_decode( $pending_user['scores'], true );
     108
     109    return $pending_user;
     110}
     111
     112/**
     113 * Update the pending user record, similar to `wp_update_user()` but for the not-yet-created user record.
     114 */
     115function wporg_update_pending_user( $pending_user ) {
     116    global $wpdb;
     117    $pending_user['meta']   = json_encode( $pending_user['meta'] );
     118    $pending_user['scores'] = json_encode( $pending_user['scores'] );
     119
     120    if ( empty( $pending_user['pending_id'] ) ) {
     121        unset( $pending_user['pending_id'] );
     122        return $wpdb->insert(
     123            "{$wpdb->base_prefix}user_pending_registrations",
     124            $pending_user
     125        );
     126    } else {
     127        return $wpdb->update(
     128            "{$wpdb->base_prefix}user_pending_registrations",
     129            $pending_user,
     130            array( 'pending_id' => $pending_user['pending_id'] )
     131        );
     132    }
     133
     134}
     135
     136/**
     137 * Create a user record from a pending record.
     138 */
     139function wporg_login_create_user_from_pending( $pending_user, $password = false ) {
     140    global $wpdb;
     141
     142    // Insert user, no password tho.
     143    $user_login = $pending_user['user_login'];
     144    $user_email = $pending_user['user_email'];
     145    $user_mailinglist = !empty( $pending_user['meta']['user_mailinglist'] ) && $pending_user['meta']['user_mailinglist'];
     146
     147    if ( ! $password ) {
     148        $password = wp_generate_password();
     149    }
     150
     151    $user_id = wpmu_create_user(
     152        wp_slash( $user_login ),
     153        $password,
     154        wp_slash( $user_email )
     155    );
     156    if ( ! $user_id ) {
     157        wp_die( __( 'Error! Something went wrong with your registration. Try again?', 'wporg' ) );
     158    }
     159
     160    // Update the registration date to the earlier one.
     161    wp_update_user( array(
     162        'ID' => $user_id,
     163        'user_registered' => $pending_user['user_registered']
     164    ) );
     165
     166    // Update the pending record with the new details.
     167    $pending_user['created'] = 1;
     168    $pending_user['created_date'] = gmdate( 'Y-m-d H:i:s' );
     169    $pending_user['meta']['confirmed_ip'] = $_SERVER['REMOTE_ADDR']; // Spam/Fraud purposes, will be deleted once not needed.
     170    wporg_update_pending_user( $pending_user );
     171
     172    if ( $user_mailinglist ) {
     173        update_user_meta( $user_id, 'notify_list', 'true' );
     174    }
     175
     176    foreach ( array( 'url', 'from', 'occ', 'interests' ) as $field ) {
     177        if ( !empty( $pending_user['meta'][ $field ] ) ) {
     178            $value = $pending_user['meta'][ $field ];
     179            if ( 'url' == $field ) {
     180                wp_update_user( array( 'ID' => $user_id, 'user_url' => $value ) );
     181            } else {
     182                if ( $value ) {
     183                    update_user_meta( $user_id, $field, $value );
     184                } else {
     185                    delete_user_meta( $user_id, $field );
     186                }
     187            }
     188        }
     189    }
     190
     191    return get_user_by( 'id', $user_id );
     192}
     193
     194/**
     195 * Save the user profile fields, potentially prior to user creation and prior to email confirmation.
     196 */
     197function wporg_login_save_profile_fields( $pending_user = false ) {
    86198    if ( ! $_POST || empty( $_POST['user_fields'] ) ) {
    87         return;
     199        return false;
    88200    }
    89201    $fields = array( 'url', 'from', 'occ', 'interests' );
     
    93205            $value = sanitize_text_field( wp_unslash( $_POST['user_fields'][ $field ] ) );
    94206            if ( 'url' == $field ) {
    95                 wp_update_user( array(
    96                     'ID' => get_current_user_id(),
    97                     'user_url' => esc_url_raw( $value ),
    98                 ) );
     207                if ( $pending_user ) {
     208                    $pending_user['meta'][ $field ] = esc_url_raw( $value );
     209                } else {
     210                    wp_update_user( array(
     211                        'ID' => get_current_user_id(),
     212                        'user_url' => esc_url_raw( $value ),
     213                    ) );
     214                }
    99215            } else {
    100                 update_user_meta( get_current_user_id(), $field, $value );
     216                if ( $pending_user ) {
     217                    $pending_user['meta'][ $field ] = $value;
     218                } else {
     219                    if ( $value ) {
     220                        update_user_meta( get_current_user_id(), $field, $value );
     221                    } else {
     222                        delete_user_meta( get_current_user_id(), $field );
     223                    }
     224                }
    101225            }
    102226        }
    103227    }
    104 }
     228
     229    if ( $pending_user ) {
     230        wporg_update_pending_user( $pending_user );
     231    }
     232
     233    return true;
     234}
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/functions-restapi.php

    r6493 r9146  
    3636    }
    3737
     38    // Check we don't have a pending registration for that username.
     39    if ( $pending = wporg_get_pending_user( $login ) ) {
     40        return [
     41            'available' => false,
     42            'error' => __( 'That username is already in use.', 'wporg' ) . '<br>' . __( 'The registration is still pending, please check your email for the confirmation link.', 'wporg' ),
     43            'avatar' => get_avatar( $pending->user_email, 64 ),
     44        ];
     45    }
     46
    3847    // Perform general validations.
    3948    $validate_signup_error = $validate_signup['errors']->get_error_message( 'user_name' );
     
    6170    }
    6271
     72    // Check we don't have a pending registration for that email.
     73    if ( $pending = wporg_get_pending_user( $email ) ) {
     74        return [
     75            'available' => false,
     76            'error' => __( 'That email address already has an account.', 'wporg' ) . '<br>' . __( 'The registration is still pending, please check your email for the confirmation link.', 'wporg' ),
     77            'avatar' => get_avatar( $email, 64 ),
     78        ];
     79    }
     80
    6381    $validate_signup = wpmu_validate_user_signup( '', $email );
    6482    $validate_signup_error = $validate_signup['errors']->get_error_message( 'user_email' );
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/functions.php

    r8608 r9146  
    191191}
    192192add_filter( 'insert_user_meta', 'wporg_login_limit_user_meta', 1 );
     193
     194/**
     195 * Remove the default contact methods.
     196 * This prevents the user meta being created unless they edit their profiles.
     197 */
     198add_filter( 'user_contactmethods', '__return_empty_array' );
    193199
    194200/**
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/partials/register-profilefields.php

    r6493 r9146  
    88 */
    99
    10 $user = get_user_by( 'id', get_current_user_id() );
     10if ( empty( $fields ) ) {
     11    $user = get_user_by( 'id', get_current_user_id() );
    1112
    12 $fields = [
    13     'url'       => $user->user_url ?: '',
    14     'from'      => $user->from ?: '',
    15     'occ'       => $user->occ ?: '',
    16     'interests' => $user->interests ?: '',
    17 ];
     13    $fields = [
     14        'url'       => $user->user_url ?: '',
     15        'from'      => $user->from ?: '',
     16        'occ'       => $user->occ ?: '',
     17        'interests' => $user->interests ?: '',
     18    ];
     19}
    1820
    1921?>
    2022<p class="login-website">
    2123    <label for="user_website"><?php _e( 'Website', 'wporg' ); ?></label>
    22     <input type="text" name="user_fields[url]" id="user_url" class="input" value="<?php echo esc_attr( $fields['url'] ); ?>" size="20" placeholder="https://" />
     24    <input type="text" name="user_fields[url]" id="user_url" class="input" value="<?php echo esc_attr( $fields['url'] ?? '' ); ?>" size="20" placeholder="https://" />
    2325</p>
    2426
    2527<p class="login-location">
    2628    <label for="user_location"><?php _e( 'Location', 'wporg' ); ?></label>
    27     <input type="text" name="user_fields[from]" id="user_location" class="input" value="<?php echo esc_attr( $fields['from'] ); ?>" size="20" />
     29    <input type="text" name="user_fields[from]" id="user_location" class="input" value="<?php echo esc_attr( $fields['from'] ?? '' ); ?>" size="20" />
    2830</p>
    2931
    3032<p class="login-occupation">
    3133    <label for="user_occupation"><?php _e( 'Occupation', 'wporg' ); ?></label>
    32     <input type="text" name="user_fields[occ]" id="user_occupation" class="input" value="<?php echo esc_attr( $fields['occ'] ); ?>" size="20" />
     34    <input type="text" name="user_fields[occ]" id="user_occupation" class="input" value="<?php echo esc_attr( $fields['occ'] ?? '' ); ?>" size="20" />
    3335</p>
    3436
    3537<p class="login-interests">
    3638    <label for="user_interests"><?php _e( 'Interests', 'wporg' ); ?></label>
    37     <input type="text" name="user_fields[interests]" id="user_interests" class="input" value="<?php echo esc_attr( $fields['interests'] ); ?>" size="20" />
     39    <input type="text" name="user_fields[interests]" id="user_interests" class="input" value="<?php echo esc_attr( $fields['interests'] ?? '' ); ?>" size="20" />
    3840</p>
    3941
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/pending-create.php

    r9139 r9146  
    11<?php
    22/**
    3  * The post-register profile-fields Template
     3 * The post-email-confirm Template
    44 *
    55 * @package wporg-login
    66 */
    77
    8     //      'register-confirm' => '/register/confirm/(?P<confirm_user>[^/]+)/(?P<confirm_key>[^/]+)',
     8$activation_user = WP_WPOrg_SSO::$matched_route_params['confirm_user'] ?? false;
     9$activation_key  = WP_WPOrg_SSO::$matched_route_params['confirm_key']  ?? false;
    910
    10 $confirm_user = isset( WP_WPOrg_SSO::$matched_route_params['confirm_user'] ) ? WP_WPOrg_SSO::$matched_route_params['confirm_user'] : false;
    11 $confirm_key  = isset( WP_WPOrg_SSO::$matched_route_params['confirm_key'] ) ? WP_WPOrg_SSO::$matched_route_params['confirm_key'] : false;
     11$pending_user = wporg_get_pending_user( $activation_user );
     12if ( ! $pending_user ) {
     13    // TODO: add a handler for "Link is expired". The pending user record has been purged.
     14    // See Line 33 below for the second case where this is needed.
     15}
    1216
    13 $can_access = true;
    14 if (
    15     $confirm_user && $confirm_key &&
    16     ( $user = get_user_by( 'login', $confirm_user ) ) &&
    17     $user->exists()
    18 ) {
    19     wp_set_current_user( $user->ID );
     17$can_access = false;
     18if ( $pending_user && $pending_user['user_activation_key'] && ! $pending_user['created'] ) {
     19    $expiration_duration = WEEK_IN_SECONDS; // Time that the user has to confirm the account.
    2020
    21     $user_activation_key = $user->user_activation_key;
    22     if ( ! $user_activation_key ) {
    23         // The activation key may not be in the cached user object, so we'll fetch it manually.
    24         $user_activation_key = $wpdb->get_var( $wpdb->prepare( "SELECT user_activation_key FROM {$wpdb->users} WHERE ID = %d", $user->ID ) );
     21    list( $user_request_time, $hashed_activation_key ) = explode( ':', $pending_user['user_activation_key'], 2 );
     22    $expiration_time                                   = $user_request_time + $expiration_duration;
     23
     24    $hash_is_correct = wp_check_password( $activation_key, $hashed_activation_key );
     25
     26    if ( $hash_is_correct && time() < $expiration_time ) {
     27        $can_access = true;
     28    } elseif ( $hash_is_correct ) {
     29        // TODO: Add a handler for "Link is expired".
     30        // For now, ignore the expiry date on the email links.
     31        // This URL is invalidated once the user is created anyway.
     32        $can_access = true;
    2533    }
    26 
    27     list( $reset_time, $hashed_activation_key ) = explode( ':', $user_activation_key, 2 );
    28 
    29     if ( empty( $wp_hasher ) ) {
    30         require_once ABSPATH . WPINC . '/class-phpass.php';
    31         $wp_hasher = new PasswordHash( 8, true );
    32     }
    33     $can_access = $wp_hasher->CheckPassword( $confirm_key, $hashed_activation_key );
    34 
    35     // Keys are only valid for 7 days (or until used)
    36     $can_access = $can_access && ( $reset_time + ( 7*DAY_IN_SECONDS ) > time() );
     34} elseif ( $pending_user && $pending_user['created'] ) {
     35    wp_safe_redirect( 'https://wordpress.org/support/' );
     36    die();
    3737}
    3838
    3939if ( ! $can_access ) {
    40     wp_set_current_user( 0 );
    4140    wp_safe_redirect( "/" );
    4241    die();
    43 } elseif ( !empty( $_POST['user_pass'] ) ) {
     42}
     43
     44if ( isset( $_POST['user_pass'] ) ) {
    4445    $user_pass = wp_unslash( $_POST['user_pass'] );
     46
     47    if ( $pending_user && ! $pending_user['created'] ) {
     48        $user = wporg_login_create_user_from_pending( $pending_user, $user_pass );
     49        if ( $user ) {
     50            wp_set_current_user( $user->ID );
     51            wp_set_auth_cookie( $user->ID, true );
     52        }
     53    }
    4554
    4655    wporg_login_save_profile_fields();
    4756
    48     add_filter( 'send_password_change_email', '__return_false' );
    49     if ( wp_update_user( wp_slash( array(
    50         'ID' => $user->ID,
    51         'user_pass' => $user_pass,
    52     ) ) ) ) {
    53         $wpdb->update( $wpdb->users, array( 'user_activation_key' => '' ), array( 'ID' => $user->ID ) );
    54         wp_set_auth_cookie( $user->ID, true );
    55         wp_safe_redirect( 'https://wordpress.org/support/' );
    56         die();
    57     }
     57    wp_safe_redirect( 'https://wordpress.org/support/' );
     58    die();
    5859}
    5960
     
    8687<!--    <p class="description indicator-hint"><?php _e( 'Hint: The password should be at least twelve characters long. To make it stronger, use upper and lower case letters, numbers, and symbols like ! " ? $ % ^ &amp; ).', 'wporg' ); ?></p> -->
    8788
    88     <?php include __DIR__ . '/partials/register-profilefields.php'; ?>
     89    <?php
     90        $fields = &$pending_user['meta'];
     91        include __DIR__ . '/partials/register-profilefields.php';
     92    ?>
    8993
    9094    <p class="login-submit">
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/pending-profile.php

    r9139 r9146  
    11<?php
    22/**
    3  * The post-register profile-fields Template
     3 * The post-pending-email-confirm profile-fields Template
    44 *
    55 * @package wporg-login
    66 */
    77
    8 $profile_user = isset( WP_WPOrg_SSO::$matched_route_params['profile_user'] ) ? WP_WPOrg_SSO::$matched_route_params['profile_user'] : false;
    9 $profile_nonce  = isset( WP_WPOrg_SSO::$matched_route_params['profile_nonce'] ) ? WP_WPOrg_SSO::$matched_route_params['profile_nonce'] : false;
     8$profile_user = WP_WPOrg_SSO::$matched_route_params['profile_user'] ?? false;
     9$profile_key  = WP_WPOrg_SSO::$matched_route_params['profile_key']  ?? false;
     10
     11$pending_user = wporg_get_pending_user( $profile_user );
    1012
    1113$can_access = false;
    12 if (
    13     $profile_user && $profile_nonce &&
    14     ( $user = get_user_by( 'login', $profile_user ) ) &&
    15     $user->exists()
    16 ) {
    17     wp_set_current_user( $user->ID );
    18     $can_access = wp_verify_nonce( $profile_nonce, 'login-register-profile-edit' );
     14if ( $pending_user && $pending_user['user_profile_key'] ) {
     15    $expiration_duration = DAY_IN_SECONDS; // The profile-edit screen is short lived.
     16
     17    list( $user_request_time, $hashed_profile_key ) = explode( ':', $pending_user['user_profile_key'], 2 );
     18    $expiration_time                                = $user_request_time + $expiration_duration;
     19
     20    $hash_is_correct = wp_check_password( $profile_key, $hashed_profile_key );
     21
     22    if ( $hash_is_correct && time() < $expiration_time ) {
     23        $can_access = true;
     24    }
    1925}
    2026
    21 if ( ! $can_access ) {
    22     wp_set_current_user( 0 );
     27if ( $can_access && $pending_user['created']  ) {
     28    wp_safe_redirect( 'https://wordpress.org/support/' );
     29    die();
     30} elseif ( ! $can_access ) {
    2331    wp_safe_redirect( '/' );
    2432    die();
    2533}
    2634
    27 wporg_login_save_profile_fields();
    28 
     35if ( wporg_login_save_profile_fields( $pending_user ) ) {
     36    // re-fetch the user, it's probably changed.
     37    $pending_user = wporg_get_pending_user( $profile_user );
     38}
    2939wp_enqueue_script( 'wporg-registration' );
    3040
     
    4757<form name="registerform" id="registerform" action="" method="post">
    4858
    49     <?php include __DIR__ . '/partials/register-profilefields.php'; ?>
     59    <?php
     60        $fields = &$pending_user['meta'];
     61        include __DIR__ . '/partials/register-profilefields.php';
     62    ?>
    5063
    5164    <p class="login-submit">
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/register.php

    r6681 r9146  
    2828            $error_recapcha_status = true;
    2929        } else {
    30             wporg_login_create_user( $user_login, $user_email, $user_mailinglist );
     30            wporg_login_create_pending_user( $user_login, $user_email, $user_mailinglist );
    3131            die();
    3232        }
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-login/stylesheets/login.css

    r6677 r9146  
    2727body.route-register,
    2828body.route-register-profile,
    29 body.route-register-confirm {
     29body.route-register-confirm,
     30body.route-pending-profile,
     31body.route-pending-create {
    3032    display: block;
    3133    padding-top: 72px;
     
    333335body.route-register input.input,
    334336body.route-register-profile input.input,
    335 body.route-register-confirm input.input {
     337body.route-register-confirm input.input,
     338body.route-pending-profile input.input,
     339body.route-pending-create input.input {
    336340    margin-bottom: 0;
    337341}
     
    339343body.route-register #login form p,
    340344body.route-register-profile #login form p,
    341 body.route-register-confirm #login form p {
     345body.route-register-confirm #login form p,
     346body.route-pending-profile #login form p,
     347body.route-pending-create #login form p {
    342348    margin-bottom: 16px;
    343349}
     
    370376body.route-register #login .message,
    371377body.route-register-profile #login .message,
    372 body.route-register-confirm #login .message {
     378body.route-register-confirm #login .message,
     379body.route-pending-profile #login .message,
     380body.route-pending-create #login .message {
    373381    margin-left: -24px;
    374382    padding-left: 24px;
     
    379387body.route-register #login .message p,
    380388body.route-register-profile #login .message p,
    381 body.route-register-confirm #login .message p {
     389body.route-register-confirm #login .message p,
     390body.route-pending-profile #login .message p,
     391body.route-pending-create #login .message p {
    382392    margin: 0;
    383393}
     
    385395body.route-register #login .message.with-avatar p,
    386396body.route-register-profile #login .message.with-avatar p,
    387 body.route-register-confirm #login .message.with-avatar p {
     397body.route-register-confirm #login .message.with-avatar p,
     398body.route-pending-profile #login .message.with-avatar p,
     399body.route-pending-create #login .message.with-avatar p {
    388400    display: -webkit-box;
    389401    display: -ms-flexbox;
     
    396408body.route-register #login .message.error,
    397409body.route-register-profile #login .message.error,
    398 body.route-register-confirm #login .message.error {
     410body.route-register-confirm #login .message.error,
     411body.route-pending-profile #login .message.error,
     412body.route-pending-create #login .message.error {
    399413    margin-bottom: 30px !important;
    400414    color: #23282d;
     
    411425body.rtl.route-register #login .message.error,
    412426body.rtl.route-register-profile #login .message.error,
    413 body.rtl.route-register-confirm #login .message.error {
     427body.rtl.route-register-confirm #login .message.error,
     428body.rtl.route-pending-profile #login .message.error,
     429body.rtl.route-pending-create #login .message.error {
    414430    border-right-color: #dc3232;
    415431}
     
    427443}
    428444
    429 body.route-register-profile #login .message.info {
     445body.route-register-profile #login .message.info,
     446body.route-pending-profile #login .message.info {
    430447    margin-top: -24px;
    431448    width: 350px;
     
    433450
    434451body.route-register-profile #login .message.info,
    435 body.route-register-profile p.intro {
     452body.route-register-profile p.intro,
     453body.route-pending-profile #login .message.info,
     454body.route-pending-profile p.intro {
    436455    margin-bottom: 1em !important;
    437456}
Note: See TracChangeset for help on using the changeset viewer.