'security failed!'] ); } if ( is_user_logged_in() ) { return wp_send_json_error( ['msg' => 'You are already logged in.'] ); } $user_login = !empty($_POST['user']) ? sanitize_user( wp_unslash( $_POST['user'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash $user_pass = !empty($_POST['pwd']) ? wp_unslash( $_POST['pwd'] ) : ''; $remember = !empty($_POST['remember']); $creds = [ 'user_login' => $user_login, 'user_password' => $user_pass, 'remember' => $remember, ]; $user = wp_signon( $creds, is_ssl() ); if ( is_wp_error( $user ) ) { return wp_send_json_error( ['msg' => 'Invalid username or password.'] ); } wp_set_current_user( $user->ID ); return wp_send_json_success(); } /** * Handle registration form submission */ public function easyel_handle_register() { $posted_nonce = ''; if ( ! empty( $_POST['eel_register_nonce'] ) ) { $posted_nonce = sanitize_text_field( wp_unslash( $_POST['eel_register_nonce'] ) ); } elseif ( ! empty( $_POST['nonce'] ) ) { $posted_nonce = sanitize_text_field( wp_unslash( $_POST['nonce'] ) ); } if ( ! $posted_nonce || ! wp_verify_nonce( $posted_nonce, 'easy_elements_nonce' ) ) { return wp_send_json_error( ['msg' => 'Security failed!'] ); } if ( is_user_logged_in() ) { return wp_send_json_error( ['msg' => 'You are already logged in.'] ); } if ( ! get_option( 'users_can_register' ) ) { return wp_send_json_error( ['msg' => 'User registration is currently disabled.'] ); } /** * Fires before the registration request is processed. */ do_action( 'easyel/login-register/before-register' ); $custom_meta = !empty($_POST['custom_meta']) ? map_deep( wp_unslash( $_POST['custom_meta'] ), 'sanitize_text_field' ) : []; $easyel_consent = !empty($_POST['easyel_consent']) ? 'yes' : 'no'; $default_role = get_option( 'default_role', 'subscriber' ); $user_data = [ 'user_login' => ! empty( $_POST['user_login'] ) ? sanitize_user( wp_unslash( $_POST['user_login'] ), true ) : '', 'user_email' => !empty($_POST['user_email']) ? sanitize_email( wp_unslash($_POST['user_email']) ) : '', // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash 'user_pass' => !empty($_POST['user_pass']) ? wp_unslash($_POST['user_pass']) : '', 'role' => $default_role, 'first_name' => !empty($_POST['first_name']) ? sanitize_text_field( wp_unslash($_POST['first_name']) ) : '', 'last_name' => !empty($_POST['last_name']) ? sanitize_text_field( wp_unslash($_POST['last_name']) ) : '', 'display_name' => !empty($_POST['display_name']) ? sanitize_text_field( wp_unslash($_POST['display_name']) ) : '', 'user_nicename' => !empty($_POST['user_nicename']) ? sanitize_text_field( wp_unslash($_POST['user_nicename']) ) : '', 'nickname' => !empty($_POST['nickname']) ? sanitize_text_field( wp_unslash($_POST['nickname']) ) : '', 'user_url' => !empty($_POST['user_url']) ? esc_url_raw( wp_unslash($_POST['user_url']) ) : '', 'description' => !empty($_POST['description']) ? sanitize_textarea_field( wp_unslash($_POST['description']) ) : '', ]; $auto_login_raw = isset( $_POST['auto_login'] ) ? sanitize_text_field( wp_unslash( $_POST['auto_login'] ) ) : 'no'; if ( ! in_array( $auto_login_raw, [ 'yes', 'no' ], true ) ) { return wp_send_json_error( ['msg' => 'Registration failed: invalid request.'] ); } $auto_login = $auto_login_raw; $send_new_user_email = ( isset( $_POST['send_new_user_email'] ) && 'yes' === $_POST['send_new_user_email'] ) ? 'yes' : 'no'; $notify_admin_email = ( isset( $_POST['notify_admin_email'] ) && 'yes' === $_POST['notify_admin_email'] ) ? 'yes' : 'no'; if ( empty( $user_data['user_login'] ) ) { return wp_send_json_error( ['msg' => 'Username is required.'] ); } if ( ! validate_username( $user_data['user_login'] ) ) { return wp_send_json_error( ['msg' => 'Invalid username.'] ); } if ( username_exists( $user_data['user_login'] ) ) { return wp_send_json_error( ['msg' => 'Username already exists.'] ); } if ( empty( $user_data['user_email'] ) || ! is_email( $user_data['user_email'] ) ) { return wp_send_json_error( ['msg' => 'Invalid email address.'] ); } if ( email_exists( $user_data['user_email'] ) ) { return wp_send_json_error( ['msg' => 'Email already exists.'] ); } if ( empty( $user_data['user_pass'] ) ) { return wp_send_json_error( ['msg' => 'Password is required.'] ); } if ( strlen( $user_data['user_pass'] ) < 8 ) { return wp_send_json_error( ['msg' => 'Password must be at least 8 characters.'] ); } if ( isset( $_POST['confirm_password'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash $confirm_password = wp_unslash( $_POST['confirm_password'] ); if ( ! hash_equals( $user_data['user_pass'], (string) $confirm_password ) ) { return wp_send_json_error( ['msg' => 'Confirm password does not match.'] ); } } if ( isset( $_POST['eel_math_captcha_hash'] ) ) { $captcha_answer = isset( $_POST['eel_math_captcha'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['eel_math_captcha'] ) ) ) : ''; $captcha_hash = sanitize_text_field( wp_unslash( $_POST['eel_math_captcha_hash'] ) ); if ( '' === $captcha_answer || ! hash_equals( wp_hash( $captcha_answer ), $captcha_hash ) ) { $captcha_error = ! empty( $_POST['math_captcha_error_msg'] ) ? sanitize_text_field( wp_unslash( $_POST['math_captcha_error_msg'] ) ) : 'Incorrect answer to the math question.'; return wp_send_json_error( ['msg' => $captcha_error] ); } } /** * Filter the user data array right before it is inserted, so * integrations can add/override fields */ $user_data = apply_filters( 'easyel/login-register/new-user-data', $user_data ); $user_data['role'] = $default_role; /** * Fires immediately before the new user is created. */ do_action( 'easyel/login-register/before-insert-user', $user_data ); $user_id = wp_insert_user( $user_data ); if ( is_wp_error( $user_id ) ) { return wp_send_json_error( ['msg' => $user_id->get_error_message()] ); } if ( is_array( $custom_meta ) ) { foreach ( $custom_meta as $key => $value ) { if ( $this->easyel_is_meta_key_allowed( $key ) ) { update_user_meta( $user_id, $key, $value ); } } } update_user_meta( $user_id, 'easyel_consent', $easyel_consent ); /** * Fires after the new user and all of its meta have been stored */ do_action( 'easyel/login-register/after-insert-user', $user_id, $user_data ); /** * Fire WordPress core's `register_new_user` action so third-party and * security plugins that hook the standard registration flow also run * for this form. * * The core default notifier (`wp_send_new_user_notifications`) is * detached first so it does not send a duplicate email — this handler * sends its own notification below using the scope chosen in the widget. */ remove_action( 'register_new_user', 'wp_send_new_user_notifications' ); // This is a WordPress core hook, fired intentionally with its core name so listeners run; it cannot be prefixed. // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound do_action( 'register_new_user', $user_id ); $notify_scope = []; if ( 'yes' === $send_new_user_email ) { $notify_scope[] = 'user'; } if ( 'yes' === $notify_admin_email ) { $notify_scope[] = 'admin'; } if ( ! empty( $notify_scope ) ) { $scope = ( count( $notify_scope ) === 2 ) ? 'both' : $notify_scope[0]; wp_new_user_notification( $user_id, null, $scope ); } $msg = 'User created successfully'; if ( $auto_login === 'yes' ) { wp_set_current_user( $user_id ); wp_set_auth_cookie( $user_id, true, is_ssl() ); } return wp_send_json_success( ['msg' => $msg] ); } /** * Decide whether a user meta key is safe to write from the public * registration request. * * Blocks WordPress protected meta (keys beginning with "_"), capability / * user-level / role / session meta, and anything that could be used to * escalate privileges. Everything else (plain custom profile fields) is * allowed. * * @param mixed $key The meta key coming from $_POST['custom_meta']. * @return bool */ private function easyel_is_meta_key_allowed( $key ) { if ( ! is_string( $key ) || $key === '' ) { return false; } // Reject WordPress protected meta (e.g. anything starting with "_"). if ( function_exists( 'is_protected_meta' ) && is_protected_meta( $key, 'user' ) ) { return false; } $blocked_keys = [ 'wp_capabilities', 'wp_user_level', 'session_tokens', 'role', 'roles', 'default_password_nag', 'user_status', ]; if ( in_array( strtolower( $key ), $blocked_keys, true ) ) { return false; } if ( preg_match( '/(^|_)(capabilities|user_level)$/i', $key ) ) { return false; } if ( ! preg_match( '/^[A-Za-z0-9_]+$/', $key ) ) { return false; } return true; } } new Easyel_Login_Register();