Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : June 25, 2026

CVE-2026-7761: Ultimate Member <= 2.11.4 Authenticated (Contributor+) Account Takeover via Password Reset Link Disclosure PoC, Patch Analysis & Rule

CVE ID CVE-2026-7761
Severity High (CVSS 8.8)
CWE 862
Vulnerable Version 2.11.4
Patched Version 2.12.0
Disclosed June 22, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-7761: This is a critical account takeover vulnerability in the Ultimate Member plugin for WordPress (versions <= 2.11.4). The vulnerability allows an authenticated attacker with Contributor-level access to leak active password reset URLs for all users, including administrators, leading to complete account compromise. The attack exploits three chained logic flaws within the member directory, meta key parsing, and field validation functions.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/ultimate-member/includes/admin/class-site-health.php
+++ b/ultimate-member/includes/admin/class-site-health.php
@@ -1595,10 +1595,6 @@
 				'label' => __( 'Allowed Choice Callbacks', 'ultimate-member' ),
 				'value' => UM()->options()->get( 'allowed_choice_callbacks' ),
 			),
-			'rest_api_version'              => array(
-				'label' => __( 'REST API version', 'ultimate-member' ),
-				'value' => UM()->options()->get( 'rest_api_version' ),
-			),
 			'allow_url_redirect_confirm'    => array(
 				'label' => __( 'Allow external link redirect confirm (enable JS.confirm for external links)', 'ultimate-member' ),
 				'value' => UM()->options()->get( 'allow_url_redirect_confirm' ) ? $labels['yes'] : $labels['no'],
--- a/ultimate-member/includes/admin/core/class-admin-settings.php
+++ b/ultimate-member/includes/admin/core/class-admin-settings.php
@@ -1020,9 +1020,6 @@
 					'enable_as_email_sending'              => array(
 						'sanitize' => 'bool',
 					),
-					'rest_api_version'                     => array(
-						'sanitize' => 'text',
-					),
 					'disable_restriction_pre_queries'      => array(
 						'sanitize' => 'bool',
 					),
@@ -2229,16 +2226,6 @@
 												'label' => __( 'Allowed Choice Callbacks (Enter one PHP function per line)', 'ultimate-member' ),
 												'description' => __( 'This option lets you specify the choice callback functions to prevent anyone from using 3rd-party functions that may put your site at risk.', 'ultimate-member' ),
 											),
-											array(
-												'id'      => 'rest_api_version',
-												'type'    => 'select',
-												'label'   => __( 'REST API Version', 'ultimate-member' ),
-												'description' => __( 'This controls the REST API version, we recommend to use the last version.', 'ultimate-member' ),
-												'options' => array(
-													'1.0' => __( '1.0 version', 'ultimate-member' ),
-													'2.0' => __( '2.0 version', 'ultimate-member' ),
-												),
-											),
 										),
 									),
 									'redirect'   => array(
--- a/ultimate-member/includes/class-config.php
+++ b/ultimate-member/includes/class-config.php
@@ -731,7 +731,6 @@
 				'cover_photo_max_size'                  => 999999999,
 				'custom_roles_increment'                => 1,
 				'um_profile_object_cache_stop'          => false,
-				'rest_api_version'                      => '2.0',
 				'member_directory_own_table'            => false,
 				'profile_show_bio'                      => false,
 				'profile_show_html_bio'                 => false,
--- a/ultimate-member/includes/class-init.php
+++ b/ultimate-member/includes/class-init.php
@@ -427,8 +427,6 @@
 				if ( ! get_option( 'show_avatars' ) ) {
 					update_option( 'show_avatars', 1 );
 				}
-			} else {
-				UM()->options()->update( 'rest_api_version', '1.0' );
 			}

 			if ( $version != UM_VERSION ) {
@@ -442,7 +440,6 @@
 			$this->cron()->schedule_events();
 		}

-
 		/**
 		 *
 		 */
@@ -450,7 +447,6 @@
 			do_action( 'um_core_loaded' );
 		}

-
 		/**
 		 * Include required core files used in admin and on the frontend.
 		 *
@@ -523,14 +519,8 @@
 			if ( is_multisite() ) {
 				$this->multisite();
 			}
-
-			// Call only when REST_API request
-			if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
-				$this->rest_api();
-			}
 		}

-
 		/**
 		 * @since 2.1.0
 		 *
@@ -938,27 +928,6 @@
 		/**
 		 * @since 2.0
 		 *
-		 * @return umcorerestAPI_v1|umcorerestAPI_v2
-		 */
-		public function rest_api() {
-			$api_version = $this->options()->get( 'rest_api_version' );
-
-			if ( empty( $this->classes['rest_api'] ) ) {
-				if ( '1.0' === $api_version ) {
-					$this->classes['rest_api'] = new umcorerestAPI_v1();
-				} elseif ( '2.0' === $api_version ) {
-					$this->classes['rest_api'] = new umcorerestAPI_v2();
-				} else {
-					$this->classes['rest_api'] = new umcorerestAPI_v1();
-				}
-			}
-
-			return $this->classes['rest_api'];
-		}
-
-		/**
-		 * @since 2.0
-		 *
 		 * @return umcoreRewrite
 		 */
 		function rewrite() {
@@ -969,7 +938,6 @@
 			return $this->classes['rewrite'];
 		}

-
 		/**
 		 * @since 2.0
 		 *
--- a/ultimate-member/includes/core/class-builtin.php
+++ b/ultimate-member/includes/core/class-builtin.php
@@ -1540,7 +1540,7 @@
 		 *
 		 * @return array
 		 */
-		function all_user_fields( $exclude_types = null, $show_all = false ) {
+		public function all_user_fields( $exclude_types = null, $show_all = false ) {

 			$fields_without_metakey = $this->get_fields_without_metakey();
 			$fields_without_metakey = apply_filters( 'um_all_user_fields_without_metakey', $fields_without_metakey );
--- a/ultimate-member/includes/core/class-fields.php
+++ b/ultimate-member/includes/core/class-fields.php
@@ -834,7 +834,6 @@
 			return $classes;
 		}

-
 		/**
 		 * Gets field value
 		 *
@@ -844,26 +843,26 @@
 		 *
 		 * @return mixed
 		 */
-		function field_value( $key, $default = false, $data = null ) {
-			// preview in backend
+		public function field_value( $key, $default = false, $data = null ) {
+			// Preview in backend
 			if ( isset( UM()->user()->preview ) && UM()->user()->preview ) {
-				if ( $this->set_mode == 'login' || $this->set_mode == 'register' ) {
+				if ( 'login' === $this->set_mode || 'register' === $this->set_mode ) {
 					return '';
-				} else {
-					$val = um_user( $key );
-					if ( ! empty( $val ) ) {
-						return $val;
-					} else {
-						return '';
-					}
 				}
+
+				$val = um_user( $key );
+				if ( ! empty( $val ) ) {
+					return $val;
+				}
+
+				return '';
 			}

-			if ( isset( $_SESSION ) && isset( $_SESSION['um_social_profile'][ $key ] ) && isset( $this->set_mode ) && $this->set_mode == 'register' ) {
+			if ( isset( $_SESSION ) && isset( $_SESSION['um_social_profile'][ $key ] ) && isset( $this->set_mode ) && 'register' === $this->set_mode ) {
 				return $_SESSION['um_social_profile'][ $key ];
 			}

-			$type = ( isset( $data['type'] ) ) ? $data['type'] : '';
+			$type = isset( $data['type'] ) ? $data['type'] : '';

 			// normal state
 			if ( isset( UM()->form()->post_form[ $key ] ) ) {
@@ -4384,7 +4383,7 @@


 		/**
-		 * Gets a field in `view mode`
+		 * Gets a field in `view mode`. Works in the User Profile form > View mode only.
 		 *
 		 * @param string $key
 		 * @param array $data
@@ -4436,7 +4435,8 @@

 			$default = array_key_exists( 'default', $data ) ? $data['default'] : false;

-			// Hide if empty.
+			// Hide if the value of the field with metakey is empty.
+			$_field_value           = null;
 			$fields_without_metakey = UM()->builtin()->get_fields_without_metakey();
 			if ( ! in_array( $type, $fields_without_metakey, true ) ) {
 				$_field_value = $this->field_value( $key, $default, $data );
@@ -4467,8 +4467,6 @@
 			switch ( $type ) {
 				/* Default */
 				default:
-					$_field_value = $this->field_value( $key, $default, $data );
-
 					if ( ( isset( $_field_value ) && '' !== $_field_value ) || in_array( $type, $fields_without_metakey, true ) ) {
 						$output .= '<div ' . $this->get_atts( $key, $classes, $conditional, $data ) . '>';

@@ -4508,16 +4506,30 @@

 							if ( $show_bio ) {
 								if ( true === $bio_html && ! empty( $data['html'] ) ) {
-									$res = wp_kses_post( make_clickable( wpautop( $res ) ) );
+									$res = wp_kses( make_clickable( $res ), 'user_description' );
 								} else {
-									$res = esc_html( $res );
+									$res = wp_kses(
+										make_clickable( $res ),
+										array(
+											'a' => array(
+												'href' => array(),
+												'rel'  => array(),
+											),
+										)
+									);
 								}
+							} elseif ( ! empty( $data['html'] ) ) {
+								$res = wp_kses( make_clickable( $res ), 'user_description' );
 							} else {
-								if ( ! empty( $data['html'] ) ) {
-									$res = wp_kses_post( make_clickable( wpautop( $res ) ) );
-								} else {
-									$res = esc_html( $res );
-								}
+								$res = wp_kses(
+									make_clickable( $res ),
+									array(
+										'a' => array(
+											'href' => array(),
+											'rel'  => array(),
+										),
+									)
+								);
 							}

 							$res = nl2br( $res );
--- a/ultimate-member/includes/core/class-form.php
+++ b/ultimate-member/includes/core/class-form.php
@@ -841,9 +841,10 @@
 											$form[ $k ] = '' !== $form[ $k ] ? (int) $form[ $k ] : '';
 											break;
 										case 'textarea':
-											if ( ! empty( $field['html'] ) || ( UM()->profile()->get_show_bio_key( $form ) === $k && UM()->options()->get( 'profile_show_html_bio' ) ) ) {
+											$description_key = UM()->profile()->get_show_bio_key( $form );
+											if ( ! empty( $field['html'] ) || ( $description_key === $k && UM()->options()->get( 'profile_show_html_bio' ) ) ) {
 												$allowed_html = UM()->get_allowed_html( 'templates' );
-												if ( UM()->profile()->get_show_bio_key( $form ) === $k ) {
+												if ( $description_key === $k ) {
 													$allowed_html = 'user_description';
 												}

@@ -851,6 +852,7 @@
 												$form[ $k ] = self::maybe_apply_tidy( $form[ $k ], $field );
 												$form[ $k ] = wp_kses( strip_shortcodes( $form[ $k ] ), $allowed_html );
 											} else {
+												// When save textarea value without HTML supported property, strip shortcodes, sanitize like a standard textarea.
 												$form[ $k ] = sanitize_textarea_field( strip_shortcodes( $form[ $k ] ) );
 											}
 											break;
@@ -961,8 +963,10 @@
 				}

 				$description_key = UM()->profile()->get_show_bio_key( $this->form_data );
+				// Case when user_description is added to the User Profile header, and it's editable and not empty.
 				if ( $show_bio && ! empty( $form[ $description_key ] ) ) {
 					$field_exists = false;
+					// Check the case when user_description is also added to the User Profile form, and it's editable and not empty.
 					if ( ! empty( $this->form_data['custom_fields'] ) ) {
 						$custom_fields = maybe_unserialize( $this->form_data['custom_fields'] );
 						if ( array_key_exists( $description_key, $custom_fields ) ) {
@@ -972,6 +976,7 @@
 								$form[ $description_key ] = self::maybe_apply_tidy( $form[ $description_key ], $custom_fields[ $description_key ] );
 								$form[ $description_key ] = wp_kses( strip_shortcodes( $form[ $description_key ] ), 'user_description' );
 							} else {
+								// When save user_description value without HTML supported property, strip shortcodes, sanitize like a standard textarea.
 								$form[ $description_key ] = sanitize_textarea_field( strip_shortcodes( $form[ $description_key ] ) );
 							}
 						}
@@ -983,6 +988,7 @@
 							$form[ $description_key ] = self::maybe_apply_tidy( $form[ $description_key ], array() );
 							$form[ $description_key ] = wp_kses( strip_shortcodes( $form[ $description_key ] ), 'user_description' );
 						} else {
+							// When save user_description value without HTML supported property, strip shortcodes, sanitize like a standard textarea.
 							$form[ $description_key ] = sanitize_textarea_field( strip_shortcodes( $form[ $description_key ] ) );
 						}
 					}
--- a/ultimate-member/includes/core/class-member-directory-meta.php
+++ b/ultimate-member/includes/core/class-member-directory-meta.php
@@ -671,7 +671,7 @@
 				$cover_photo_where = " AND umm_general.um_value LIKE '%s:11:"cover_photo";b:1;%'";
 			}

-			if ( ! UM()->roles()->um_user_can( 'can_edit_everyone' ) ) {
+			if ( ! $this->can_edit_users() ) {
 				if ( ! $this->general_meta_joined ) {
 					$this->joins[] = "LEFT JOIN {$wpdb->prefix}um_metadata umm_general ON umm_general.user_id = u.ID";

--- a/ultimate-member/includes/core/class-member-directory.php
+++ b/ultimate-member/includes/core/class-member-directory.php
@@ -262,9 +262,8 @@
 			return $default;
 		}

-
 		/**
-		 * Getting member directory post ID via hash
+		 * Getting member directory post ID via hash.
 		 * Hash is unique attr, which we use visible at frontend
 		 *
 		 * @param string $hash
@@ -277,9 +276,12 @@
 			$directory_id = $wpdb->get_var(
 				$wpdb->prepare(
 					"SELECT post_id
-					FROM {$wpdb->postmeta}
-					WHERE meta_key = '_um_directory_token' AND
-						  meta_value = %s
+					FROM {$wpdb->postmeta} pm
+					LEFT JOIN {$wpdb->posts} p ON pm.post_id = p.ID
+					WHERE p.post_type = 'um_directory' AND
+						  p.post_status = 'publish' AND
+						  pm.meta_key = '_um_directory_token' AND
+						  pm.meta_value = %s
 					LIMIT 1",
 					$hash
 				)
@@ -290,7 +292,9 @@
 					$wpdb->prepare(
 						"SELECT ID
 						FROM {$wpdb->posts}
-						WHERE SUBSTRING( MD5( ID ), 11, 5 ) = %s",
+						WHERE SUBSTRING( MD5( ID ), 11, 5 ) = %s AND
+							  post_type='um_directory' AND
+							  post_status = 'publish'",
 						$hash
 					)
 				);
@@ -1183,43 +1187,46 @@
 		}

 		/**
-		 * @param $filter
+		 * Get the placeholders array for the slider-type filter.
+		 * Format `array( 'singular-placeholder', 'plural-placeholder' )`.
 		 *
-		 * @return mixed
+		 * @param string $filter
+		 * @param array  $attrs
+		 *
+		 * @return array
 		 */
-		function slider_range_placeholder( $filter, $attrs ) {
+		public function slider_range_placeholder( $filter, $attrs ) {
 			switch ( $filter ) {
-				default: {
-					$label = ! empty( $attrs['label'] ) ? $attrs['label'] : $filter;
-					$label = ucwords( str_replace( array( 'um_', '_' ), array( '', ' ' ), $label ) );
+				default:
+					$label        = ! empty( $attrs['label'] ) ? $attrs['label'] : $filter;
+					$label        = ucwords( str_replace( array( 'um_', '_' ), array( '', ' ' ), $label ) );
 					$placeholders = apply_filters( 'um_member_directory_filter_slider_range_placeholder', false, $filter );

 					if ( ! $placeholders ) {
 						switch ( $attrs['type'] ) {
 							default:
 								$placeholders = array(
-									"<strong>$label:</strong> {value}",
-									"<strong>$label:</strong> {min_range} - {max_range}",
+									"$label: {value}",
+									"$label: {min_range} - {max_range}",
 								);
 								break;
 							case 'rating':
 								$placeholders = array(
-									"<strong>$label:</strong> {value}" . __( ' stars', 'ultimate-member' ),
-									"<strong>$label:</strong> {min_range} - {max_range}" . __( ' stars', 'ultimate-member' )
+									"$label: {value}" . __( ' stars', 'ultimate-member' ),
+									"$label: {min_range} - {max_range}" . __( ' stars', 'ultimate-member' ),
 								);
 								break;
 						}
 					}
-
 					break;
-				}
-				case 'birth_date': {
+
+				case 'birth_date':
 					$placeholders = array(
-						__( '<strong>Age:</strong> {value} years old', 'ultimate-member' ),
-						__( '<strong>Age:</strong> {min_range} - {max_range} years old', 'ultimate-member' )
+						__( 'Age: {value} years old', 'ultimate-member' ),
+						__( 'Age: {min_range} - {max_range} years old', 'ultimate-member' ),
 					);
 					break;
-				}
+
 			}

 			return $placeholders;
@@ -1344,12 +1351,30 @@
 			do_action( 'um_member_directory_restrictions_handle_extend' );
 		}

+		/**
+		 * Determine if the current user can edit other users
+		 *
+		 * @return bool Returns true if the current user can edit users, false otherwise
+		 */
+		protected function can_edit_users() {
+			if ( is_user_logged_in() ) {
+				$rolename = UM()->roles()->get_priority_user_role( get_current_user_id() );
+				$role     = get_role( $rolename );
+
+				// Don't specify only approved users  when the current user has 'edit_users' capability.
+				if ( current_user_can( 'edit_users' ) || ( ! is_null( $role ) && $role->has_cap( 'edit_users' ) ) ) {
+					return true;
+				}
+			}
+
+			return false;
+		}

 		/**
 		 *
 		 */
-		function hide_not_approved() {
-			if ( UM()->roles()->um_user_can( 'can_edit_everyone' )  ) {
+		public function hide_not_approved() {
+			if ( $this->can_edit_users() ) {
 				return;
 			}

@@ -1360,7 +1385,6 @@
 			) ) );
 		}

-
 		/**
 		 *
 		 */
@@ -1393,7 +1417,7 @@
 				return;
 			}

-			if ( UM()->roles()->um_user_can( 'can_edit_everyone' ) ) {
+			if ( $this->can_edit_users() ) {
 				return;
 			}

@@ -2671,6 +2695,8 @@
 		 * @return array
 		 */
 		public function build_user_card_data( $user_id, $directory_data ) {
+			$user_fields = UM()->builtin()->all_user_fields();
+
 			um_fetch_user( $user_id );

 			$dropdown_actions = $this->build_user_actions_list( $user_id );
@@ -2690,9 +2716,9 @@

 			$data_array = array(
 				'card_anchor'          => esc_html( $this->get_user_hash( $user_id ) ),
-				'role'                 => is_user_logged_in() ? esc_html( um_user( 'role' ) ) : 'undefined', // make the role hidden for the nopriv requests.
-				'account_status'       => is_user_logged_in() ? esc_html( UM()->common()->users()->get_status( $user_id ) ) : 'undefined', // make the status hidden for the nopriv requests.
-				'account_status_name'  => is_user_logged_in() ? esc_html( UM()->common()->users()->get_status( $user_id, 'formatted' ) ) : __( 'Undefined', 'ultimate-member' ), // make the status hidden for the nopriv requests.
+				'role'                 => 'undefined', // make the role hidden here.
+				'account_status'       => 'undefined', // make the status hidden here.
+				'account_status_name'  => esc_html__( 'Undefined', 'ultimate-member' ), // make the status hidden here.
 				'cover_photo'          => wp_kses( um_user( 'cover_photo', $this->cover_size ), UM()->get_allowed_html( 'templates' ) ),
 				'display_name'         => esc_html( um_user( 'display_name' ) ),
 				'profile_url'          => esc_url( um_user_profile_url() ),
@@ -2705,45 +2731,53 @@
 				'hook_after_user_name' => wp_kses( preg_replace( '/^s+/im', '', $hook_after_user_name ), UM()->get_allowed_html( 'templates' ) ),
 			);

-			if ( ! empty( $directory_data['show_tagline'] ) ) {
-
-				if ( ! empty( $directory_data['tagline_fields'] ) ) {
-					$directory_data['tagline_fields'] = maybe_unserialize( $directory_data['tagline_fields'] );
+			// Make the role and status visible for the user who can edit these users in the request.
+			if ( is_user_logged_in() && UM()->common()->users()->can_current_user_edit_user( $user_id ) ) {
+				$data_array['role']                = esc_html( um_user( 'role' ) );
+				$data_array['account_status']      = esc_html( UM()->common()->users()->get_status( $user_id ) );
+				$data_array['account_status_name'] = esc_html( UM()->common()->users()->get_status( $user_id, 'formatted' ) );
+			}

-					if ( is_array( $directory_data['tagline_fields'] ) ) {
-						foreach ( $directory_data['tagline_fields'] as $key ) {
-							if ( ! $key ) {
-								continue;
-							}
+			$description_key = UM()->profile()->get_show_bio_key( UM()->fields()->global_args );

-							if ( '_um_last_login' === $key ) {
-								$show_last_login = get_user_meta( $user_id, 'um_show_last_login', true );
-								if ( ! empty( $show_last_login ) && 'no' === $show_last_login[0] ) {
-									continue;
-								}
-							}
+			if ( ! empty( $directory_data['show_tagline'] ) && ! empty( $directory_data['tagline_fields'] ) ) {
+				$directory_data['tagline_fields'] = maybe_unserialize( $directory_data['tagline_fields'] );

-							$value = um_filtered_value( $key );
+				if ( is_array( $directory_data['tagline_fields'] ) ) {
+					foreach ( $directory_data['tagline_fields'] as $key ) {
+						if ( ! $key || ! array_key_exists( $key, $user_fields ) ) {
+							continue;
+						}

-							if ( ! $value ) {
+						if ( '_um_last_login' === $key ) {
+							$show_last_login = get_user_meta( $user_id, 'um_show_last_login', true );
+							if ( ! empty( $show_last_login ) && 'no' === $show_last_login[0] ) {
 								continue;
 							}
+						}
+
+						$value = um_filtered_value( $key );
+						if ( ! $value ) {
+							continue;
+						}

-							$data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
+						if ( $description_key === $key ) {
+							$value = nl2br( wp_kses( make_clickable( $value ), 'user_description' ) );
 						}
+
+						$data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
 					}
 				}
 			}

 			if ( ! empty( $directory_data['show_userinfo'] ) ) {
-
 				if ( ! empty( $directory_data['reveal_fields'] ) ) {

 					$directory_data['reveal_fields'] = maybe_unserialize( $directory_data['reveal_fields'] );

 					if ( is_array( $directory_data['reveal_fields'] ) ) {
 						foreach ( $directory_data['reveal_fields'] as $key ) {
-							if ( ! $key ) {
+							if ( ! $key || ! array_key_exists( $key, $user_fields ) ) {
 								continue;
 							}

@@ -2759,16 +2793,23 @@
 								continue;
 							}

+							if ( $description_key === $key ) {
+								$value = nl2br( wp_kses( make_clickable( $value ), 'user_description' ) );
+							}
+
 							$label = UM()->fields()->get_label( $key );
-							if ( $key == 'role_select' || $key == 'role_radio' ) {
-								$label = strtr( $label, array(
-									' (Dropdown)'   => '',
-									' (Radio)'      => ''
-								) );
+							if ( 'role_select' === $key || 'role_radio' === $key ) {
+								$label = strtr(
+									$label,
+									array(
+										' (Dropdown)' => '',
+										' (Radio)'    => '',
+									)
+								);
 							}

-							$data_array[ "label_{$key}" ] = esc_html__( $label, 'ultimate-member' );
-							$data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
+							$data_array[ "label_{$key}" ] = esc_html( $label );
+							$data_array[ $key ]           = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
 						}
 					}
 				}
--- a/ultimate-member/includes/core/class-profile.php
+++ b/ultimate-member/includes/core/class-profile.php
@@ -40,23 +40,20 @@
 		/**
 		 * Profile constructor.
 		 */
-		function __construct() {
+		public function __construct() {
 			add_action( 'template_redirect', array( &$this, 'active_tab' ), 10002 );
 			add_action( 'template_redirect', array( &$this, 'active_subnav' ), 10002 );
 		}

-
 		/**
 		 * @param array $args
 		 *
 		 * @return string
 		 */
-		function get_show_bio_key( $args ) {
-			$key = apply_filters( 'um_profile_bio_key', 'description', $args );
-			return $key;
+		public function get_show_bio_key( $args ) {
+			return apply_filters( 'um_profile_bio_key', 'description', $args );
 		}

-
 		/**
 		 * Delete profile avatar AJAX handler
 		 */
@@ -448,22 +445,25 @@
 						if ( $description_key === $key ) {
 							$global_setting = UM()->options()->get( 'profile_show_html_bio' );
 							$bio_html       = ! empty( $global_setting );
-
-							if ( ! empty( $args['custom_fields'][ $description_key ] ) ) {
-								if ( empty( $args['custom_fields'][ $description_key ]['html'] ) ) {
-									$bio_html = false;
-								}
+							if ( ! empty( $args['custom_fields'][ $description_key ] ) && empty( $args['custom_fields'][ $description_key ]['html'] ) ) {
+								$bio_html = false;
 							}

 							if ( $bio_html ) {
-								$data['html'] = true;
-								$value = um_filtered_value( $key, $data );
-								$res = wp_kses_post( make_clickable( wpautop( $value ) ) );
+								$value = wp_kses( make_clickable( $value ), 'user_description' );
 							} else {
-								$res = esc_html( $value );
+								$value = wp_kses(
+									make_clickable( $value ),
+									array(
+										'a' => array(
+											'href' => array(),
+											'rel'  => array(),
+										),
+									)
+								);
 							}

-							$value = nl2br( $res );
+							$value = nl2br( $value );
 						}

 						if ( ! $value && ( ! array_key_exists( 'type', $data ) || ! in_array( $data['type'], $fields_without_metakey, true ) ) ) {
--- a/ultimate-member/includes/core/class-query.php
+++ b/ultimate-member/includes/core/class-query.php
@@ -426,29 +426,38 @@
 		 * @return array
 		 */
 		public function post_data( $post_id ) {
-			$array['form_id'] = $post_id;
-			$mode             = $this->get_attr( 'mode', $post_id );
-			$meta             = get_post_custom( $post_id );
+			$mode = $this->get_attr( 'mode', $post_id );
+
+			$array = array(
+				'form_id' => $post_id,
+				'mode'    => $mode,
+			);
+
+			$meta = get_post_custom( $post_id );
 			foreach ( $meta as $k => $v ) {
-				if ( strstr( $k, '_um_' . $mode . '_' ) ) {
+				if ( '_um_mode' === $k ) {
+					continue;
+				}
+
+				if ( 0 === strpos( $k, '_um_' . $mode . '_' ) ) {
 					$k           = str_replace( '_um_' . $mode . '_', '', $k );
 					$array[ $k ] = $v[0];
-				} elseif ( '_um_mode' === $k ) {
-					$k           = str_replace( '_um_', '', $k );
-					$array[ $k ] = $v[0];
-				} elseif ( strstr( $k, '_um_' ) ) {
+				} elseif ( 0 === strpos( $k, '_um_' ) ) {
 					$k           = str_replace( '_um_', '', $k );
 					$array[ $k ] = $v[0];
 				}
 			}

-			foreach ( $array as $k => $v ) {
-				if ( strstr( $k, 'login_' ) || strstr( $k, 'register_' ) || strstr( $k, 'profile_' ) ) {
-					if ( 'directory' !== $mode ) {
+			// Remove another form mode meta if exists. E.g. login meta for the profile-mode form.
+			if ( 'directory' !== $mode ) {
+				// There isn't such meta in the member directory mode, so skip this.
+				foreach ( $array as $k => $v ) {
+					if ( 0 === strpos( $k, 'login_' ) || 0 === strpos( $k, 'register_' ) || 0 === strpos( $k, 'profile_' ) ) {
 						unset( $array[ $k ] );
 					}
 				}
 			}
+
 			return $array;
 		}

--- a/ultimate-member/includes/core/class-user.php
+++ b/ultimate-member/includes/core/class-user.php
@@ -110,6 +110,8 @@
 				'user_activation_key',
 				'level_',
 				$wpdb->get_blog_prefix() . 'user_level',
+				'um_user_public_key', // UM REST API public. Legacy, not used for now!
+				'um_user_secret_key', // UM REST API secret. Legacy, not used for now!
 			);

 			// a list of keys that should never be in wp_usermeta
@@ -1180,13 +1182,11 @@
 			return '';
 		}

-
 		/**
 		 * @param $user_id
 		 * @param $profile
 		 */
-		function setup_cache( $user_id, $profile ) {
-
+		public function setup_cache( $user_id, $profile ) {
 			$disallow_cache = UM()->options()->get( 'um_profile_object_cache_stop' );
 			if ( $disallow_cache ) {
 				return;
@@ -1195,11 +1195,10 @@
 			update_option( "um_cache_userdata_{$user_id}", $profile, false );
 		}

-
 		/**
 		 * @param $user_id
 		 */
-		function remove_cache( $user_id ) {
+		public function remove_cache( $user_id ) {
 			delete_option( "um_cache_userdata_{$user_id}" );
 		}

@@ -1319,13 +1318,10 @@

 					// Setup cache
 					$this->setup_cache( $this->id, $this->profile );
-
 				}
 			}
-
 		}

-
 		/**
 		 * Reset user data
 		 *
--- a/ultimate-member/includes/core/rest/class-api-v1.php
+++ b/ultimate-member/includes/core/rest/class-api-v1.php
@@ -1,445 +0,0 @@
-<?php
-namespace umcorerest;
-
-if ( ! defined( 'ABSPATH' ) ) {
-	exit;
-}
-
-if ( ! class_exists( 'umcorerestAPI_v1' ) ) {
-
-
-	/**
-	 * Class REST_API
-	 * @package umcore
-	 */
-	class API_v1 extends API {
-
-		/**
-		 *
-		 */
-		const VERSION = '1.0';
-
-		/**
-		 * REST_API constructor.
-		 */
-		public function __construct() {
-			parent::__construct();
-
-			add_filter( 'query_vars', array( $this, 'query_vars' ) );
-		}
-
-		/**
-		 * Registers query vars for API access
-		 *
-		 * @param $vars
-		 *
-		 * @return array
-		 */
-		public function query_vars( $vars ) {
-			$vars[] = 'key';
-			$vars[] = 'token';
-			$vars[] = 'format';
-			$vars[] = 'query';
-			$vars[] = 'type';
-			$vars[] = 'data';
-			$vars[] = 'fields';
-			$vars[] = 'value';
-			$vars[] = 'number';
-			$vars[] = 'id';
-			$vars[] = 'email';
-			$vars[] = 'orderby';
-			$vars[] = 'order';
-			$vars[] = 'include';
-			$vars[] = 'exclude';
-
-			$this->vars = $vars;
-
-			return $vars;
-		}
-
-		/**
-		 * Validate the API request
-		 */
-		protected function validate_request() {
-			global $wp_query;
-
-			$this->override = false;
-
-			// Make sure we have both user and api key
-			if ( ! empty( $wp_query->query_vars['um-api'] ) ) {
-
-				if ( empty( $wp_query->query_vars['token'] ) || empty( $wp_query->query_vars['key'] ) ) {
-					$this->missing_auth();
-				}
-
-				// Retrieve the user by public API key and ensure they exist
-				if ( ! ( $user = $this->get_user( $wp_query->query_vars['key'] ) ) ) {
-					$this->invalid_key();
-				} else {
-					$token  = urldecode( $wp_query->query_vars['token'] );
-					$secret = get_user_meta( $user, 'um_user_secret_key', true );
-					$public = urldecode( $wp_query->query_vars['key'] );
-
-					if ( hash_equals( md5( $secret . $public ), $token ) ) {
-						$this->is_valid_request = true;
-					} else {
-						$this->invalid_auth();
-					}
-				}
-			}
-		}
-
-		/**
-		 * Retrieve the user ID based on the public key provided
-		 *
-		 * @param string $key
-		 *
-		 * @return bool|mixed|null|string
-		 */
-		public function get_user( $key = '' ) {
-			global $wpdb, $wp_query;
-
-			if ( empty( $key ) ) {
-				$key = urldecode( $wp_query->query_vars['key'] );
-			}
-
-			if ( empty( $key ) ) {
-				return false;
-			}
-
-			$user = get_transient( md5( 'um_api_user_' . $key ) );
-
-			if ( false === $user ) {
-				$user = $wpdb->get_var(
-					$wpdb->prepare(
-						"SELECT user_id
-						FROM $wpdb->usermeta
-						WHERE meta_key = 'um_user_public_key' AND
-							  meta_value = %s
-						LIMIT 1",
-						$key
-					)
-				);
-				set_transient( md5( 'um_api_user_' . $key ) , $user, DAY_IN_SECONDS );
-			}
-
-			if ( $user != null ) {
-				$this->user_id = $user;
-				return $user;
-			}
-
-			return false;
-		}
-
-		/**
-		 * Process Get users API Request.
-		 *
-		 * @param array $args
-		 *
-		 * @return array
-		 */
-		public function get_users( $args ) {
-			$response = array();
-
-			$number  = array_key_exists( 'number', $args ) && is_numeric( $args['number'] ) ? absint( $args['number'] ) : 10;
-			$orderby = array_key_exists( 'orderby', $args ) ? sanitize_key( $args['orderby'] ) : 'user_registered';
-			$order   = array_key_exists( 'order', $args ) ? sanitize_key( $args['order'] ) : 'desc';
-
-			$loop_a = array(
-				'number'  => $number,
-				'orderby' => $orderby,
-				'order'   => $order,
-			);
-
-			if ( array_key_exists( 'include', $args ) ) {
-				$include           = explode( ',', sanitize_text_field( $args['include'] ) );
-				$loop_a['include'] = $include;
-			}
-
-			if ( array_key_exists( 'exclude', $args ) ) {
-				$exclude           = explode( ',', sanitize_text_field( $args['exclude'] ) );
-				$loop_a['exclude'] = $exclude;
-			}
-
-			$loop = get_users( $loop_a );
-
-			foreach ( $loop as $user ) {
-				unset( $user->data->user_status, $user->data->user_activation_key, $user->data->user_pass );
-
-				um_fetch_user( $user->ID );
-
-				foreach ( $user as $key => $val ) {
-					if ( 'data' !== $key ) {
-						continue;
-					}
-
-					$val->roles                = $user->roles;
-					$val->first_name           = um_user( 'first_name' );
-					$val->last_name            = um_user( 'last_name' );
-					$val->account_status       = UM()->common()->users()->get_status( $user->ID );
-					$val->profile_pic_original = um_get_user_avatar_url( '', 'original' );
-					$val->profile_pic_normal   = um_get_user_avatar_url( '', 200 );
-					$val->profile_pic_small    = um_get_user_avatar_url( '', 40 );
-					$val->cover_photo          = $this->getsrc( um_user( 'cover_photo', 1000 ) );
-
-					/**
-					 * Filters the output data for Rest API userdata call.
-					 *
-					 * @param {mixed} $val      User data value.
-					 * @param {int}   $user_id  User ID.
-					 *
-					 * @return {mixed} User data value.
-					 *
-					 * @since 2.0
-					 * @hook um_rest_userdata
-					 *
-					 * @example <caption>Force change the output data for Rest API userdata call.</caption>
-					 * function my_custom_um_rest_userdata( $value, $user_id  ) {
-					 *     // your code here
-					 *     return $response;
-					 * }
-					 * add_filter( 'um_rest_userdata', 'my_custom_um_rest_userdata', 10, 2 );
-					 */
-					$response[ $user->ID ] = apply_filters( 'um_rest_userdata', $val, $user->ID );
-				}
-			}
-
-			return $response;
-		}
-
-		/**
-		 * Update user API query
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function update_user( $args ) {
-			$response = array();
-			$error    = array();
-
-			if ( empty( $args['id'] ) ) {
-				$error['error'] = __( 'You must provide a user ID', 'ultimate-member' );
-				return $error;
-			}
-
-			if ( empty( $args['data'] ) ) {
-				$error['error'] = __( 'You need to provide data to update', 'ultimate-member' );
-				return $error;
-			}
-
-			if ( ! array_key_exists( 'value', $args ) ) {
-				$error['error'] = __( 'You need to provide value to update', 'ultimate-member' );
-				return $error;
-			}
-
-			$id    = absint( $args['id'] );
-			$data  = sanitize_text_field( $args['data'] );
-			$value = sanitize_text_field( $args['value'] );
-
-			um_fetch_user( $id );
-
-			switch ( $data ) {
-				case 'status':
-					// Force update of the user status without email notifications.
-					UM()->common()->users()->set_status( $id, $value );
-					$response['success'] = __( 'User status has been changed.', 'ultimate-member' );
-					break;
-				case 'role':
-					$wp_user_object = new WP_User( $id );
-					$old_roles      = $wp_user_object->roles;
-					$wp_user_object->set_role( $value );
-
-					/** This action is documented in includes/core/class-user.php */
-					do_action( 'um_after_member_role_upgrade', array( $value ), $old_roles, $id );
-
-					$response['success'] = __( 'User role has been changed.', 'ultimate-member' );
-					break;
-				default:
-					update_user_meta( $id, $data, $value );
-					$response['success'] = __( 'User meta has been changed.', 'ultimate-member' );
-					break;
-			}
-
-			return $response;
-		}
-
-		/**
-		 * Process delete user via API
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function delete_user( $args ) {
-			$response = array();
-			$error    = array();
-
-			if ( empty( $args['id'] ) ) {
-				$error['error'] = __( 'You must provide a user ID', 'ultimate-member' );
-				return $error;
-			}
-
-			$id = absint( $args['id'] );
-
-			$user = get_userdata( $id );
-			if ( ! $user ) {
-				$error['error'] = __( 'Invalid user specified', 'ultimate-member' );
-				return $error;
-			}
-
-			um_fetch_user( $id );
-			UM()->user()->delete();
-
-			$response['success'] = __( 'User has been successfully deleted.', 'ultimate-member' );
-
-			return $response;
-		}
-
-		/**
-		 * Process Get user API Request
-		 *
-		 * @param $args
-		 *
-		 * @return array|mixed
-		 */
-		public function get_auser( $args ) {
-			$response = array();
-			$error    = array();
-
-			if ( empty( $args['id'] ) ) {
-				$error['error'] = __( 'You must provide a user ID', 'ultimate-member' );
-				return $error;
-			}
-
-			$id   = absint( $args['id'] );
-			$user = get_userdata( $id );
-			if ( ! $user ) {
-				$error['error'] = __( 'Invalid user specified', 'ultimate-member' );
-				return $error;
-			}
-
-			unset( $user->data->user_status, $user->data->user_activation_key, $user->data->user_pass );
-
-			um_fetch_user( $user->ID );
-
-			if ( array_key_exists( 'fields', $args ) ) {
-				$fields               = explode( ',', sanitize_text_field( $args['fields'] ) );
-				$response['ID']       = $user->ID;
-				$response['username'] = $user->user_login;
-				foreach ( $fields as $field ) {
-
-					switch ( $field ) {
-						default:
-							$profile_data       = um_profile( $field );
-							$response[ $field ] = $profile_data ? $profile_data : '';
-
-							/**
-							 * Filters the output data for Rest API user authentication call.
-							 *
-							 * @param {array}  $response REST API response.
-							 * @param {string} $field    Field Options.
-							 * @param {int}    $user_id  User ID.
-							 *
-							 * @return {array} REST API response.
-							 *
-							 * @since 2.0
-							 * @hook um_rest_get_auser
-							 *
-							 * @example <caption>Force change the output data for Rest API user authentication call.</caption>
-							 * function my_custom_um_rest_get_auser( $response, $field, $user_id  ) {
-							 *     // your code here
-							 *     return $response;
-							 * }
-							 * add_filter( 'um_rest_get_auser', 'my_custom_um_rest_get_auser', 10, 3 );
-							 */
-							$response = apply_filters( 'um_rest_get_auser', $response, $field, $user->ID );
-							break;
-						case 'cover_photo':
-							$response['cover_photo'] = $this->getsrc( um_user( 'cover_photo', 1000 ) );
-							break;
-						case 'profile_pic':
-							$response['profile_pic_original'] = um_get_user_avatar_url( '', 'original' );
-							$response['profile_pic_normal']   = um_get_user_avatar_url( '', 200 );
-							$response['profile_pic_small']    = um_get_user_avatar_url( '', 40 );
-							break;
-						case 'status':
-							$response['status'] = UM()->common()->users()->get_status( $user->ID );
-							break;
-						case 'role':
-							//get priority role here
-							$response['role'] = um_user( 'role' );
-							break;
-						case 'email':
-						case 'user_email':
-							$response['email'] = um_user( 'user_email' );
-							break;
-					}
-				}
-			} else {
-				foreach ( $user as $key => $val ) {
-					if ( 'data' !== $key ) {
-						continue;
-					}
-
-					$val->roles                = $user->roles;
-					$val->first_name           = um_user( 'first_name' );
-					$val->last_name            = um_user( 'last_name' );
-					$val->account_status       = UM()->common()->users()->get_status( $user->ID );
-					$val->profile_pic_original = um_get_user_avatar_url( '', 'original' );
-					$val->profile_pic_normal   = um_get_user_avatar_url( '', 200 );
-					$val->profile_pic_small    = um_get_user_avatar_url( '', 40 );
-					$val->cover_photo          = $this->getsrc( um_user( 'cover_photo', 1000 ) );
-
-					/** This filter is documented in includes/core/rest/class-api-v1.php */
-					$response = apply_filters( 'um_rest_userdata', $val, $user->ID );
-				}
-			}
-
-			return $response;
-		}
-
-		/**
-		 * Get source
-		 *
-		 * @param $image
-		 *
-		 * @return string
-		 */
-		public function getsrc( $image ) {
-			if ( preg_match( '/<img.+?src(?: )*=(?: )*['"](.*?)['"]/si', $image, $arr_result ) ) {
-				return $arr_result[1];
-			}
-			return '';
-		}
-
-		/**
-		 * Retrieve the output format
-		 */
-		public function get_output_format() {
-			global $wp_query;
-
-			$format = isset( $wp_query->query_vars['format'] ) ? $wp_query->query_vars['format'] : 'json';
-
-			/**
-			 * Filters the REST API output format. JSON by default.
-			 *
-			 * @param {string} $format REST API output format.
-			 *
-			 * @return {string} REST API output format.
-			 *
-			 * @since 1.3.x
-			 * @hook um_api_output_format
-			 *
-			 * @example <caption>Changing the REST API output format.</caption>
-			 * function my_custom_um_api_output_format( $format ) {
-			 *     // your code here
-			 *     $format = 'xml';
-			 *     return $format;
-			 * }
-			 * add_filter( 'um_api_output_format', 'my_custom_um_api_output_format' );
-			 */
-			return apply_filters( 'um_api_output_format', $format );
-		}
-	}
-}
--- a/ultimate-member/includes/core/rest/class-api-v2.php
+++ b/ultimate-member/includes/core/rest/class-api-v2.php
@@ -1,392 +0,0 @@
-<?php
-namespace umcorerest;
-
-if ( ! defined( 'ABSPATH' ) ) {
-	exit;
-}
-
-if ( ! class_exists( 'umcorerestAPI_v2' ) ) {
-
-	/**
-	 * Class API_v2
-	 * @package umcorerest
-	 */
-	class API_v2 extends API {
-
-		/**
-		 *
-		 */
-		const VERSION = '2.0';
-
-		/**
-		 * REST_API constructor.
-		 */
-		public function __construct() {
-			parent::__construct();
-
-			add_filter( 'query_vars', array( $this, 'query_vars' ) );
-		}
-
-		/**
-		 * Registers query vars for API access
-		 *
-		 * @param $vars
-		 *
-		 * @return array
-		 */
-		public function query_vars( $vars ) {
-			$vars[] = 'um_key';
-			$vars[] = 'um_token';
-			$vars[] = 'um_format';
-			$vars[] = 'um_query';
-			$vars[] = 'um_type';
-			$vars[] = 'um_data';
-			$vars[] = 'um_fields';
-			$vars[] = 'um_value';
-			$vars[] = 'um_number';
-			$vars[] = 'um_id';
-			$vars[] = 'um_email';
-			$vars[] = 'um_orderby';
-			$vars[] = 'um_order';
-			$vars[] = 'um_include';
-			$vars[] = 'um_exclude';
-
-			$this->vars = $vars;
-
-			return $vars;
-		}
-
-		/**
-		 * Validate the API request
-		 */
-		protected function validate_request() {
-			global $wp_query;
-
-			$this->override = false;
-
-			// Make sure we have both user and api key
-			if ( ! empty( $wp_query->query_vars['um-api'] ) ) {
-
-				if ( empty( $wp_query->query_vars['um_token'] ) || empty( $wp_query->query_vars['um_key'] ) ) {
-					$this->missing_auth();
-				}
-
-				// Retrieve the user by public API key and ensure they exist
-				if ( ! ( $user = $this->get_user( $wp_query->query_vars['um_key'] ) ) ) {
-					$this->invalid_key();
-				} else {
-					$token  = urldecode( $wp_query->query_vars['um_token'] );
-					$secret = get_user_meta( $user, 'um_user_secret_key', true );
-					$public = urldecode( $wp_query->query_vars['um_key'] );
-
-					if ( hash_equals( md5( $secret . $public ), $token ) ) {
-						$this->is_valid_request = true;
-					} else {
-						$this->invalid_auth();
-					}
-				}
-			}
-		}
-
-		/**
-		 * Retrieve the user ID based on the public key provided
-		 *
-		 * @param string $key
-		 *
-		 * @return bool|mixed|null|string
-		 */
-		public function get_user( $key = '' ) {
-			global $wpdb, $wp_query;
-
-			if ( empty( $key ) ) {
-				$key = urldecode( $wp_query->query_vars['um_key'] );
-			}
-
-			if ( empty( $key ) ) {
-				return false;
-			}
-
-			$user = get_transient( md5( 'um_api_user_' . $key ) );
-
-			if ( false === $user ) {
-				$user = $wpdb->get_var(
-					$wpdb->prepare(
-						"SELECT user_id
-						FROM $wpdb->usermeta
-						WHERE meta_key = 'um_user_public_key' AND
-							  meta_value = %s
-						LIMIT 1",
-						$key
-					)
-				);
-				set_transient( md5( 'um_api_user_' . $key ) , $user, DAY_IN_SECONDS );
-			}
-
-			if ( $user != NULL ) {
-				$this->user_id = $user;
-				return $user;
-			}
-
-			return false;
-		}
-
-		/**
-		 * Process Get users API Request
-		 *
-		 * @param array $args
-		 *
-		 * @return array
-		 */
-		public function get_users( $args ) {
-			$response = array();
-
-			$number  = array_key_exists( 'um_number', $args ) && is_numeric( $args['um_number'] ) ? absint( $args['um_number'] ) : 10;
-			$orderby = array_key_exists( 'um_orderby', $args ) ? sanitize_key( $args['um_orderby'] ) : 'user_registered';
-			$order   = array_key_exists( 'um_order', $args ) ? sanitize_key( $args['um_order'] ) : 'desc';
-
-			$loop_a = array(
-				'number'  => $number,
-				'orderby' => $orderby,
-				'order'   => $order,
-			);
-
-			if ( array_key_exists( 'um_include', $args ) ) {
-				$include           = explode( ',', sanitize_text_field( $args['um_include'] ) );
-				$loop_a['include'] = $include;
-			}
-
-			if ( array_key_exists( 'um_exclude', $args ) ) {
-				$exclude           = explode( ',', sanitize_text_field( $args['um_exclude'] ) );
-				$loop_a['exclude'] = $exclude;
-			}
-
-			$loop = get_users( $loop_a );
-
-			foreach ( $loop as $user ) {
-				unset( $user->data->user_status, $user->data->user_activation_key, $user->data->user_pass );
-
-				um_fetch_user( $user->ID );
-
-				foreach ( $user as $key => $val ) {
-					if ( 'data' !== $key ) {
-						continue;
-					}
-
-					$val->roles                = $user->roles;
-					$val->first_name           = um_user( 'first_name' );
-					$val->last_name            = um_user( 'last_name' );
-					$val->account_status       = UM()->common()->users()->get_status( $user->ID );
-					$val->profile_pic_original = um_get_user_avatar_url( '', 'original' );
-					$val->profile_pic_normal   = um_get_user_avatar_url( '', 200 );
-					$val->profile_pic_small    = um_get_user_avatar_url( '', 40 );
-					$val->cover_photo          = $this->getsrc( um_user( 'cover_photo', 1000 ) );
-
-					/** This filter is documented in includes/core/rest/class-api-v1.php */
-					$response[ $user->ID ] = apply_filters( 'um_rest_userdata', $val, $user->ID );
-				}
-			}
-
-			return $response;
-		}
-
-		/**
-		 * Update user API query
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function update_user( $args ) {
-			$response = array();
-			$error    = array();
-
-			if ( empty( $args['um_id'] ) ) {
-				$error['error'] = __( 'You must provide a user ID', 'ultimate-member' );
-				return $error;
-			}
-
-			if ( empty( $args['um_data'] ) ) {
-				$error['error'] = __( 'You need to provide data to update', 'ultimate-member' );
-				return $error;
-			}
-
-			if ( ! array_key_exists( 'um_value', $args ) ) {
-				$error['error'] = __( 'You need to provide value to update', 'ultimate-member' );
-				return $error;
-			}
-
-			$id    = absint( $args['um_id'] );
-			$data  = sanitize_text_field( $args['um_data'] );
-			$value = sanitize_text_field( $args['um_value'] );
-
-			um_fetch_user( $id );
-
-			switch ( $data ) {
-				case 'status':
-					// Force update of the user status without email notifications.
-					UM()->common()->users()->set_status( $id, $value );
-					$response['success'] = __( 'User status has been changed.', 'ultimate-member' );
-					break;
-				case 'role':
-					$wp_user_object = new WP_User( $id );
-					$old_roles      = $wp_user_object->roles;
-					$wp_user_object->set_role( $value );
-
-					/** This action is documented in includes/core/class-user.php */
-					do_action( 'um_after_member_role_upgrade', array( $value ), $old_roles, $id );
-
-					$response['success'] = __( 'User role has been changed.', 'ultimate-member' );
-					break;
-				default:
-					update_user_meta( $id, $data, $value );
-					$response['success'] = __( 'User meta has been changed.', 'ultimate-member' );
-					break;
-			}
-
-			return $response;
-		}
-
-		/**
-		 * Process delete user via API.
-		 *
-		 * @param array $args
-		 *
-		 * @return array
-		 */
-		public function delete_user( $args ) {
-			$response = array();
-			$error    = array();
-
-			if ( empty( $args['um_id'] ) ) {
-				$error['error'] = __( 'You must provide a user ID', 'ultimate-member' );
-				return $error;
-			}
-
-			$id = absint( $args['um_id'] );
-
-			$user = get_userdata( $id );
-			if ( ! $user ) {
-				$error['error'] = __( 'Invalid user specified', 'ultimate-member' );
-				return $error;
-			}
-
-			um_fetch_user( $id );
-			UM()->user()->delete();
-
-			$response['success'] = __( 'User has been successfully deleted.', 'ultimate-member' );
-
-			return $response;
-		}
-
-		/**
-		 * Process Get user API Request
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function get_auser( $args ) {
-			$response = array();
-			$error    = array();
-
-			if ( empty( $args['um_id'] ) ) {
-				$error['error'] = __( 'You must provide a user ID', 'ultimate-member' );
-				return $error;
-			}
-
-			$id   = absint( $args['um_id'] );
-			$user = get_userdata( $id );
-			if ( ! $user ) {
-				$error['error'] = __( 'Invalid user specified', 'ultimate-member' );
-				return $error;
-			}
-
-			unset( $user->data->user_status, $user->data->user_activation_key, $user->data->user_pass );
-
-			um_fetch_user( $user->ID );
-
-			if ( array_key_exists( 'um_fields', $args ) ) {
-				$fields               = explode( ',', sanitize_text_field( $args['um_fields'] ) );
-				$response['ID']       = $user->ID;
-				$response['username'] = $user->user_login;
-				foreach ( $fields as $field ) {
-
-					switch ( $field ) {
-						default:
-							$profile_data       = um_profile( $field );
-							$response[ $field ] = $profile_data ? $profile_data : '';
-
-							/** This filter is documented in includes/core/rest/class-api-v1.php */
-							$response = apply_filters( 'um_rest_get_auser', $response, $field, $user->ID );
-							break;
-						case 'cover_photo':
-							$response['cover_photo'] = $this->getsrc( um_user( 'cover_photo', 1000 ) );
-							break;
-						case 'profile_pic':
-							$response['profile_pic_original'] = um_get_user_avatar_url( '', 'original' );
-							$response['profile_pic_normal']   = um_get_user_avatar_url( '', 200 );
-							$response['profile_pic_small']    = um_get_user_avatar_url( '', 40 );
-							break;
-						case 'status':
-							$response['status'] = UM()->common()->users()->get_status( $user->ID );
-							break;
-						case 'role':
-							//get priority role here
-							$response['role'] = um_user( 'role' );
-							break;
-						case 'email':
-						case 'user_email':
-							$response['email'] = um_user( 'user_email' );
-							break;
-					}
-				}
-			} else {
-				foreach ( $user as $key => $val ) {
-					if ( 'data' !== $key ) {
-						continue;
-					}
-
-					$val->roles                = $user->roles;
-					$val->first_name           = um_user( 'first_name' );
-					$val->last_name            = um_user( 'last_name' );
-					$val->account_status       = UM()->common()->users()->get_status( $user->ID );
-					$val->profile_pic_original = um_get_user_avatar_url( '', 'original' );
-					$val->profile_pic_normal   = um_get_user_avatar_url( '', 200 );
-					$val->profile_pic_small    = um_get_user_avatar_url( '', 40 );
-					$val->cover_photo          = $this->getsrc( um_user( 'cover_photo', 1000 ) );
-
-					/** This filter is documented in includes/core/rest/class-api-v1.php */
-					$response = apply_filters( 'um_rest_userdata', $val, $user->ID );
-				}
-			}
-
-			return $response;
-		}
-
-		/**
-		 * Get source
-		 *
-		 * @param $image
-		 *
-		 * @return string
-		 */
-		public function getsrc( $image ) {
-			if ( preg_match( '/<img.+?src(?: )*=(?: )*['"](.*?)['"]/si', $image, $arr_result ) ) {
-				return $arr_result[1];
-			}
-			return '';
-		}
-
-		/**
-		 * Retrieve the output format
-		 */
-		public function get_output_format() {
-			global $wp_query;
-
-			$format = isset( $wp_query->query_vars['um_format'] ) ? $wp_query->query_vars['um_format'] : 'json';
-
-			/** This filter is documented in includes/core/rest/class-api-v1.php */
-			return apply_filters( 'um_api_output_format', $format );
-		}
-	}
-}
--- a/ultimate-member/includes/core/rest/class-api.php
+++ b/ultimate-member/includes/core/rest/class-api.php
@@ -1,615 +0,0 @@
-<?php
-namespace umcorerest;
-
-
-if ( ! defined( 'ABSPATH' ) ) exit;
-
-
-if ( ! class_exists( 'umcorerestAPI' ) ) {
-
-
-	/**
-	 * Class API
-	 *
-	 * @package umcorerest
-	 */
-	class API {
-
-
-		/**
-		 * @var bool|int|null
-		 */
-		protected $pretty_print = false;
-
-
-		/**
-		 * @var bool|mixed|void
-		 */
-		public 	$log_requests = true;
-
-
-		/**
-		 * @var bool
-		 */
-		protected $is_valid_request = false;
-
-
-		/**
-		 * @var int
-		 */
-		protected $user_id = 0;
-
-
-		/**
-		 * @var
-		 */
-		protected $stats;
-
-
-		/**
-		 * @var array
-		 */
-		protected $data = array();
-
-
-		/**
-		 * @var bool
-		 */
-		protected $override = true;
-
-
-		/**
-		 * @var array
-		 */
-		protected $vars = array();
-
-
-		/**
-		 * REST_API constructor.
-		 */
-		public function __construct() {
-
-			add_action( 'init', array( $this, 'add_endpoint' ) );
-			add_action( 'template_redirect', array( $this, 'process_query' ), -1 );
-
-			// Determine if JSON_PRETTY_PRINT is available
-			$this->pretty_print = defined( 'JSON_PRETTY_PRINT' ) ? JSON_PRETTY_PRINT : null;
-
-			/**
-			 * UM hook
-			 *
-			 * @type filter
-			 * @title um_api_log_requests
-			 * @description Allow API request logging to be turned off
-			 * @input_vars
-			 * [{"var":"$allow_log","type":"bool","desc":"Enable api logs"}]
-			 * @change_log
-			 * ["Since: 2.0"]
-			 * @usage
-			 * <?php add_filter( 'um_api_log_requests', 'function_name', 10, 1 ); ?>
-			 * @example
-			 * <?php
-			 * add_filter( 'um_api_log_requests', 'my_api_log_requests', 10, 1 );
-			 * function my_api_log_requests( $allow_log ) {
-			 *     // your code here
-			 *     return $allow_log;
-			 * }
-			 * ?>
-			 */
-			$this->log_requests = apply_filters( 'um_api_log_requests', $this->log_requests );
-		}
-
-
-		/**
-		 * Registers a new rewrite endpoint for accessing the API
-		 *
-		 * @param $rewrite_rules
-		 */
-		public function add_endpoint( $rewrite_rules ) {
-			add_rewrite_endpoint( 'um-api', EP_ALL );
-		}
-
-
-		/**
-		 * Listens for the API and then processes the API requests
-		 */
-		public function process_query() {
-			global $wp_query;
-
-			// Check for um-api var. Get out if not present
-			if ( ! isset( $wp_query->query_vars['um-api'] ) ) {
-				return;
-			}
-
-			// Check for a valid user and set errors if necessary
-			$this->validate_request();
-
-			// Only proceed if no errors have been noted
-			if ( ! $this->is_valid_request ) {
-				return;
-			}
-
-			if ( ! defined( 'UM_DOING_API' ) ) {
-				define( 'UM_DOING_API', true );
-			}
-
-			// Determine the kind of query
-			$args = array();
-			$query_mode = $this->get_query_mode();
-			foreach ( $this->vars as $k ) {
-				$args[ $k ] = isset( $wp_query->query_vars[ $k ] ) ? $wp_query->query_vars[ $k ] : null;
-			}
-
-			$data = array();
-
-			switch ( $query_mode ) {
-				case 'get.stats':
-					$data = $this->get_stats( $args );
-					break;
-
-				case 'get.users':
-					$data = $this->get_users( $args );
-					break;
-
-				case 'get.user':
-					$data = $this->get_auser( $args );
-					break;
-
-				case 'update.user':
-					$data = $this->update_user( $args );
-					break;
-
-				case 'delete.user':
-					$data = $this->delete_user( $args );
-					break;
-
-				default:
-					/**
-					 * UM hook
-					 *
-					 * @type filter
-					 * @title um_rest_query_mode
-					 * @description Change query attributes
-					 * @input_vars
-					 * [{"var":"$data","type":"array","desc":"Query Data"},
-					 * {"var":"$query_mode","type":"string","desc":"Query Mode"},
-					 * {"var":"$args","type":"array","desc":"Query Arguments"}]
-					 * @change_log
-					 * ["Since: 2.0"]
-					 * @usage
-					 * <?php add_filter( 'um_rest_query_mode', 'function_name', 10, 3 ); ?>
-					 * @example
-					 * <?php
-					 * add_filter( 'um_rest_query_mode', 'my_rest_query_mode', 10, 3 );
-					 * function um_rest_query_mode( $data, $query_mode, $args ) {
-					 *     // your code here
-					 *     return $data;
-					 * }
-					 * ?>
-					 */
-					$data = apply_filters( 'um_rest_query_mode', $data, $query_mode, $args );
-					break;
-			}
-
-			/**
-			 * UM hook
-			 *
-			 * @type filter
-			 * @title um_api_output_data
-			 * @description Change output data for Rest API call
-			 * @input_vars
-			 * [{"var":"$data","type":"array","desc":"Output Data"},
-			 * {"var":"$query_mode","type":"string","desc":"Query Mode"},
-			 * {"var":"$api_class","type":"REST_API","desc":"REST_API instance"}]
-			 * @change_log
-			 * ["Since: 2.0"]
-			 * @usage
-			 * <?php add_filter( 'um_api_output_data', 'function_name', 10, 3 ); ?>
-			 * @example
-			 * <?php
-			 * add_filter( 'um_api_output_data', 'my_api_output_data', 10, 3 );
-			 * function my_api_output_data( $data, $query_mode, $api_class ) {
-			 *     // your code here
-			 *     return $data;
-			 * }
-			 * ?>
-			 */
-			$this->data = apply_filters( 'um_api_output_data', $data, $query_mode, $this );
-
-			// Log this API request, if enabled. We log it here because we have access to errors.
-			$this->log_request( $this->data );
-
-			// Send out data to the output function
-			$this->output();
-		}
-
-
-		/**
-		 * Validate the API request
-		 */
-		protected function validate_request() {
-
-		}
-
-
-		/**
-		 * Retrieve the user ID based on the public key provided
-		 *
-		 * @param string $key
-		 *
-		 * @return bool
-		 */
-		public function get_user( $key = '' ) {
-			return false;
-		}
-
-
-		/**
-		 * Displays a missing authentication error if all the parameters aren't
-		 * provided
-		 */
-		protected function missing_auth() {
-			$error = array();
-			$error['error'] = __( 'You must specify both a token and API key!', 'ultimate-member' );
-
-			$this->data = $error;
-			$this->output( 401 );
-		}
-
-
-		/**
-		 * Displays an authentication failed error if the user failed to provide valid credentials
-		 */
-		protected function invalid_auth() {
-			$error = array();
-			$error['error'] = __( 'Your request could not be authenticated', 'ultimate-member' );
-
-			$this->data = $error;
-			$this->output( 401 );
-		}
-
-
-		/**
-		 * Displays an invalid API key error if the API key provided couldn't be validated
-		 */
-		protected function invalid_key() {
-			$error = array();
-			$error['error'] = __( 'Invalid API key', 'ultimate-member' );
-
-			$this->data = $error;
-			$this->output( 401 );
-		}
-
-
-		/**
-		 * Get some stats
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function get_stats( $args ) {
-			global $wpdb;
-
-			$response = array();
-
-			$count = absint( $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}users" ) );
-			$response['stats']['total_users'] = $count;
-
-			$pending = UM()->query()->get_pending_users_count();
-			$response['stats']['pending_users'] = absint( $pending );
-
-			/**
-			 * UM hook
-			 *
-			 * @type filter
-			 * @title um_rest_api_get_stats
-			 * @description Change output data for Rest API get stats call
-			 * @input_vars
-			 * [{"var":"$response","type":"array","desc":"Output Data"}]
-			 * @change_log
-			 * ["Since: 2.0"]
-			 * @usage
-			 * <?php add_filter( 'um_rest_api_get_stats', 'function_name', 10, 1 ); ?>
-			 * @example
-			 * <?php
-			 * add_filter( 'um_rest_api_get_stats', 'my_rest_api_get_stats', 10, 1 );
-			 * function my_rest_api_get_stats( $response ) {
-			 *     // your code here
-			 *     return $response;
-			 * }
-			 * ?>
-			 */
-			$response = apply_filters( 'um_rest_api_get_stats', $response );
-			return $response;
-		}
-
-
-		/**
-		 * Process Get users API Request
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function get_users( $args ) {
-			return array();
-		}
-
-
-		/**
-		 * Update user API query
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function update_user( $args ) {
-			return array();
-		}
-
-
-		/**
-		 * Process delete user via API
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function delete_user( $args ) {
-			return array();
-		}
-
-
-		/**
-		 * Process Get user API Request
-		 *
-		 * @param $args
-		 *
-		 * @return array
-		 */
-		public function get_auser( $args ) {
-			return array();
-		}
-
-
-		/**
-		 * Get source
-		 *
-		 * @param $image
-		 *
-		 * @return string
-		 */
-		protected function getsrc( $image ) {
-			if ( preg_match( '/<img.+?src(?: )*=(?: )*['"](.*?)['"]/si', $image, $arrResult ) ) {
-				return $arrResult[1];
-			}
-			return '';
-		}
-
-
-		/**
-		 * Determines the kind of query requested and also ensure it is a valid query
-		 *
-		 * @return null
-		 */
-		public function get_query_mode() {
-			global $wp_query;
-
-			/**
-			 * UM hook
-			 *
-			 * @type filter
-			 * @title um_api_valid_query_modes
-			 * @description Whitelist UM query options
-			 * @input_vars
-			 * [{"var":"$list","type":"array","desc":"Whitelist"}]
-			 * @change_log
-			 * ["Since: 2.0"]
-			 * @usage
-			 * <?php add_filter( 'um_api_valid_query_modes', 'function_name', 10, 1 ); ?>
-			 * @example
-			 * <?php
-			 * add_filter( 'um_api_valid_query_modes', 'my_api_valid_query_modes', 10, 1 );
-			 * function my_api_valid_query_modes( $list ) {
-			 *     // your code here
-			 *     return $list;
-			 * }
-			 * ?>
-			 */
-			$accepted = apply_filters( 'um_api_valid_query_modes', array(
-				'get.users',
-				'get.user',
-				'update.user',
-				'delete.user',
-				'get.following',
-				'get.followers',
-				'get.stats',
-			) );
-
-			$query = isset( $wp_query->query_vars['um-api'] ) ? $wp_query->query_vars['um-api'] : null;
-			$error = array();
-			// Make sure our query is valid
-			if ( 

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School