is_resolved(); } /** * If the return is true or Response, we add it to resolve list. WP_Error if any error. * * @return bool|WP_Error|Response */ public function process() { $username = HTTP::post( 'username' ); $is_valid = $this->validate( $username ); if ( is_wp_error( $is_valid ) ) { return $is_valid; } return $this->update_username( $username ); } /** * This is for un-do stuff that has be done in @process. * * @return bool */ public function revert(): bool { return true; } /** * Shield up. * * @return bool */ public function shield_up(): bool { return true; } /** * Check whether the issue is resolved or not. * * @return bool */ private function is_resolved() { return ! $this->get_user_with_admin_username(); } /** * Get user with admin username. * * @return WP_User|false on failure */ private function get_user_with_admin_username() { return get_user_by( 'login', 'admin' ); } /** * Validate username. * * @param string $username to validate. * * @return bool|WP_Error on failure */ private function validate( $username ) { if ( ! is_string( $username ) || '' === $username ) { return new WP_Error( 'defender_invalid_username', wp_strip_all_tags( __( 'The username can\'t be empty!', 'defender-security' ) ) ); } if ( 'admin' === strtolower( $username ) ) { return new WP_Error( 'defender_invalid_username', wp_strip_all_tags( __( 'You can\'t use admin as a username again!', 'defender-security' ) ) ); } if ( ! validate_username( $username ) ) { return new WP_Error( 'defender_invalid_username', wp_strip_all_tags( __( 'The username is invalid!', 'defender-security' ) ) ); } if ( username_exists( $username ) ) { return new WP_Error( 'defender_invalid_username', wp_strip_all_tags( __( 'The username already exists!', 'defender-security' ) ) ); } return true; } /** * Updates the 'admin' username to a new username. * Performs the update in the database and handles multisite admin updates if applicable. * * @param string $username The new username. * * @return bool|WP_Error|Response True on success, WP_Error on database error, Response on logout requirement. */ private function update_username( $username ) { global $wpdb; $user = $this->get_user_with_admin_username(); $ret = $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery $wpdb->users, array( 'user_login' => trim( $username ) ), array( 'ID' => $user->ID ) ); if ( ! $ret ) { return new WP_Error( 'update_error', $wpdb->last_error ); } if ( is_multisite() ) { $site_admins = get_site_option( 'site_admins' ); if ( is_array( $site_admins ) ) { $pos = array_search( 'admin', array_map( 'strtolower', $site_admins ), true ); if ( false !== $pos ) { $site_admins[ $pos ] = $username; update_site_option( 'site_admins', $site_admins ); } } } clean_user_cache( $user ); // Log the user out only if it's the user with 'admin' username. if ( get_current_user_id() !== $user->ID ) { return true; } if ( defined( 'WP_DEFENDER_TESTING' ) && true === constant( 'WP_DEFENDER_TESTING' ) ) { // Testing. return true; } $interval = 5; $redirect = $this->get_login_url(); return new Response( true, array( 'message' => sprintf( /* translators: 1. Redirect link. 2. Line break. 3. Interval. */ esc_html__( 'Your admin name has changed. You will need to %1$s.%2$s This will auto reload after %3$s seconds.', 'defender-security' ), '' . esc_html__( 're-login', 'defender-security' ) . '', '
', '' . $interval . '' ), 'redirect' => $redirect, 'interval' => $interval, ) ); } /** * Get the login url. * * @return string */ private function get_login_url(): string { return wp_login_url( network_admin_url( 'admin.php?page=wdf-hardener' ) ); } /** * Retrieve the tweak's label. * * @return string */ public function get_label(): string { return esc_html__( 'Change admin account', 'defender-security' ); } /** * Get the error reason. * * @return string */ public function get_error_reason(): string { return wp_kses( __( 'Your account uses the default “admin” username, and may attract login attacks.', 'defender-security' ), array( 'strong' => array(), ) ); } /** * Return a summary data of this tweak. * * @return array */ public function to_array(): array { $admin_user = $this->get_user_with_admin_username(); $current_user = wp_get_current_user(); $username = $admin_user ? $admin_user->user_login : $current_user->user_login; $error_reason = wp_kses( sprintf( /* translators: %s: Username. */ __( 'Your account uses the default "%s" username, and may attract login attacks.', 'defender-security' ), esc_html( $username ) ), array( 'strong' => array(), ) ); return array( 'slug' => $this->slug, 'title' => $this->get_label(), 'errorReason' => $error_reason, 'successReason' => wp_strip_all_tags( __( 'Username is up to date.', 'defender-security' ) ), 'misc' => array( 'show_revert_button' => false, 'show_action_button' => true, 'admin_username' => $username, ), 'bulk_description' => wp_strip_all_tags( __( 'Brute force attacks often rely on common usernames and guessed passwords. Create a new admin username to make your site harder to target and help protect your login area.', 'defender-security' ) ), 'bulk_title' => wp_strip_all_tags( __( 'Admin User', 'defender-security' ) ), ); } }