From 58bbd3cede6d8a83290994b7feed68a5c1ecc5ff Mon Sep 17 00:00:00 2001 From: Nikita Sinelnikov Date: Mon, 23 Aug 2021 17:21:30 +0300 Subject: [PATCH 1/4] - fixed notices if there aren't restricted post types; --- includes/core/class-access.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/includes/core/class-access.php b/includes/core/class-access.php index 5073d5bb..5a7c440d 100644 --- a/includes/core/class-access.php +++ b/includes/core/class-access.php @@ -166,9 +166,11 @@ if ( ! class_exists( 'um\core\Access' ) ) { } } else { $restricted_posts = UM()->options()->get( 'restricted_access_post_metabox' ); - $restricted_posts = array_keys( $restricted_posts ); - if ( ! empty( $post_types ) ) { - $restricted_posts = array_intersect( $post_types, $restricted_posts ); + if ( ! empty( $restricted_posts ) ) { + $restricted_posts = array_keys( $restricted_posts ); + if ( ! empty( $post_types ) ) { + $restricted_posts = array_intersect( $post_types, $restricted_posts ); + } } if ( ! empty( $restricted_posts ) ) { @@ -812,6 +814,9 @@ if ( ! class_exists( 'um\core\Access' ) ) { global $wp_taxonomies; $restricted_posts = UM()->options()->get( 'restricted_access_post_metabox' ); + if ( empty( $restricted_posts ) ) { + $restricted_posts = array(); + } $restricted_posts = array_keys( $restricted_posts ); $restricted_taxonomies = UM()->options()->get( 'restricted_access_taxonomy_metabox' ); From 9927dab3232f0d8d31c6a183970a2e9008228c4c Mon Sep 17 00:00:00 2001 From: Nikita Sinelnikov Date: Wed, 25 Aug 2021 01:07:09 +0300 Subject: [PATCH 2/4] - fixed um_edit_profile_url() function and added $user_id attribute; - added `disable_restriction_pre_queries` option for backward compatibility with business logic where 404 error isn't good way; - added `restricted_post_title_replace` option for ability to disable restricted post's title replace --- includes/admin/core/class-admin-metabox.php | 8 ++-- includes/admin/core/class-admin-settings.php | 40 ++++++++++++++----- .../templates/access/restrict_content.php | 4 +- includes/class-config.php | 2 + includes/core/class-access.php | 28 +++++++++++++ includes/um-short-functions.php | 6 ++- 6 files changed, 69 insertions(+), 19 deletions(-) diff --git a/includes/admin/core/class-admin-metabox.php b/includes/admin/core/class-admin-metabox.php index 0877da44..01b73dbb 100644 --- a/includes/admin/core/class-admin-metabox.php +++ b/includes/admin/core/class-admin-metabox.php @@ -416,8 +416,8 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) { array( 'id' => '_um_access_hide_from_queries', 'type' => 'checkbox', - 'label' => __( 'Would you like to display 404 error on the term\'s archive page and terms\' posts single pages when users haven\'t access?', 'ultimate-member' ), - 'description' => __( 'Recommended to be enabled. Restricted term\'s archive page and all terms\' posts will be hidden by exclusion from WP Query. The safest and most effective method that hides post and its comments from all requests, RSS feeds, etc. on your site', 'ultimate-member' ), + 'label' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Hide from queries', 'ultimate-member' ) : __( 'Would you like to display 404 error on the term\'s archive page and terms\' posts single pages when users haven\'t access?', 'ultimate-member' ), + 'description' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Exclude only from WP queries results', 'ultimate-member' ) : __( 'Recommended to be enabled. Restricted term\'s archive page and all terms\' posts will be hidden by exclusion from WP Query. The safest and most effective method that hides post and its comments from all requests, RSS feeds, etc. on your site', 'ultimate-member' ), 'value' => 1, 'conditional' => array( '_um_accessible', '!=', '0' ), ), @@ -568,8 +568,8 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) { array( 'id' => '_um_access_hide_from_queries', 'type' => 'checkbox', - 'label' => __( 'Would you like to display 404 error on the term\'s archive page and terms\' posts single pages when users haven\'t access?', 'ultimate-member' ), - 'description' => __( 'Recommended to be enabled. Restricted term\'s archive page and all terms\' posts will be hidden by exclusion from WP Query. The safest and most effective method that hides post and its comments from all requests, RSS feeds, etc. on your site', 'ultimate-member' ), + 'label' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Hide from queries', 'ultimate-member' ) : __( 'Would you like to display 404 error on the term\'s archive page and terms\' posts single pages when users haven\'t access?', 'ultimate-member' ), + 'description' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Exclude only from WP queries results', 'ultimate-member' ) : __( 'Recommended to be enabled. Restricted term\'s archive page and all terms\' posts will be hidden by exclusion from WP Query. The safest and most effective method that hides post and its comments from all requests, RSS feeds, etc. on your site', 'ultimate-member' ), 'value' => ! empty( $data['_um_access_hide_from_queries'] ) ? $data['_um_access_hide_from_queries'] : '', 'conditional' => array( '_um_accessible', '!=', '0' ), ), diff --git a/includes/admin/core/class-admin-settings.php b/includes/admin/core/class-admin-settings.php index 097bd22a..237fb878 100644 --- a/includes/admin/core/class-admin-settings.php +++ b/includes/admin/core/class-admin-settings.php @@ -503,10 +503,17 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { 'conditional' => array( 'accessible', '=', 2 ), ), array( - 'id' => 'restricted_access_post_title', - 'type' => 'text', - 'label' => __( 'Restricted Access Post Title', 'ultimate-member' ), - 'tooltip' => __( 'This is the post title shown to users that do not have permission to view the content', 'ultimate-member' ), + 'id' => 'restricted_post_title_replace', + 'type' => 'checkbox', + 'label' => __( 'Replace the restricted Post Title', 'ultimate-member' ), + 'tooltip' => __( 'Allow to replace the restricted post title to users that do not have permission to view the content', 'ultimate-member' ), + ), + array( + 'id' => 'restricted_access_post_title', + 'type' => 'text', + 'label' => __( 'Restricted Access Post Title', 'ultimate-member' ), + 'tooltip' => __( 'This is the post title shown to users that do not have permission to view the content', 'ultimate-member' ), + 'conditional' => array( 'restricted_post_title_replace', '=', 1 ), ), array( 'id' => 'restricted_access_message', @@ -519,25 +526,28 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { $settings_map = array_merge( $settings_map, array( - 'accessible' => array( + 'accessible' => array( 'sanitize' => 'int', ), - 'access_redirect' => array( + 'access_redirect' => array( 'sanitize' => 'url', ), - 'access_exclude_uris' => array( + 'access_exclude_uris' => array( 'sanitize' => 'url', ), - 'home_page_accessible' => array( + 'home_page_accessible' => array( 'sanitize' => 'bool', ), - 'category_page_accessible' => array( + 'category_page_accessible' => array( 'sanitize' => 'bool', ), - 'restricted_access_post_title' => array( + 'restricted_post_title_replace' => array( + 'sanitize' => 'bool', + ), + 'restricted_access_post_title' => array( 'sanitize' => 'text', ), - 'restricted_access_message' => array( + 'restricted_access_message' => array( 'sanitize' => 'wp_kses', ), ) @@ -1751,6 +1761,14 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { '2.0' => __( '2.0 version', 'ultimate-member' ), ), ), + // backward compatibility option leave it disabled for better security and ability to exclude posts/terms pre-query + // otherwise we filtering only results and restricted posts/terms can be visible + array( + 'id' => 'disable_restriction_pre_queries', + 'type' => 'checkbox', + 'label' => __( 'Disable pre-queries for restriction content logic (advanced)', 'ultimate-member' ), + 'tooltip' => __( 'Please enable this option only in the cases when you have big or unnecessary queries on your site with active restriction logic. If you want to exclude posts only from the results queries instead of pre_get_posts and fully-hidden post logic also please enable this option. It activates the restriction content logic until 2.2.x version without latest security enhancements', 'ultimate-member' ), + ), $same_page_update, array( 'id' => 'uninstall_on_delete', diff --git a/includes/admin/templates/access/restrict_content.php b/includes/admin/templates/access/restrict_content.php index 28779908..42bd1b46 100644 --- a/includes/admin/templates/access/restrict_content.php +++ b/includes/admin/templates/access/restrict_content.php @@ -81,8 +81,8 @@ if ( ! defined( 'ABSPATH' ) ) { array( 'id' => '_um_access_hide_from_queries', 'type' => 'checkbox', - 'label' => __( 'Would you like to display 404 page when users haven\'t access?', 'ultimate-member' ), - 'tooltip' => __( 'Recommended to be enabled. Restricted post will be hidden by exclusion from WP Query. The safest and most effective method that hides post and its comments from all requests, RSS feeds, etc. on your site', 'ultimate-member' ), + 'label' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Hide from queries', 'ultimate-member' ) : __( 'Would you like to display 404 page when users haven\'t access?', 'ultimate-member' ), + 'tooltip' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? __( 'Exclude only from WP queries results', 'ultimate-member' ) : __( 'Recommended to be enabled. Restricted post will be hidden by exclusion from WP Query. The safest and most effective method that hides post and its comments from all requests, RSS feeds, etc. on your site', 'ultimate-member' ), 'value' => ! empty( $data['_um_access_hide_from_queries'] ) ? $data['_um_access_hide_from_queries'] : '', 'conditional' => array( '_um_accessible', '!=', '0' ), ), diff --git a/includes/class-config.php b/includes/class-config.php index 08e073c7..e8ccfc92 100644 --- a/includes/class-config.php +++ b/includes/class-config.php @@ -512,6 +512,7 @@ if ( ! class_exists( 'um\Config' ) ) { //settings defaults $this->settings_defaults = array( 'restricted_access_post_metabox' => array( 'post' => 1, 'page' => 1 ), + 'disable_restriction_pre_queries' => 0, 'uninstall_on_delete' => 0, 'permalink_base' => 'user_login', 'display_name' => 'full_name', @@ -543,6 +544,7 @@ if ( ! class_exists( 'um\Config' ) ) { 'access_exclude_uris' => array(), 'home_page_accessible' => 1, 'category_page_accessible' => 1, + 'restricted_post_title_replace' => 1, 'restricted_access_post_title' => __( 'Restricted content', 'ultimate-member' ), 'restricted_access_message' => '', 'restricted_blocks' => 0, diff --git a/includes/core/class-access.php b/includes/core/class-access.php index 5a7c440d..477902f8 100644 --- a/includes/core/class-access.php +++ b/includes/core/class-access.php @@ -105,6 +105,30 @@ if ( ! class_exists( 'um\core\Access' ) ) { add_action( 'template_redirect', array( &$this, 'template_redirect' ), 1000 ); add_action( 'um_access_check_individual_term_settings', array( &$this, 'um_access_check_individual_term_settings' ) ); add_action( 'um_access_check_global_settings', array( &$this, 'um_access_check_global_settings' ) ); + + + add_action( 'plugins_loaded', array( &$this, 'disable_restriction_pre_queries' ), 1 ); + } + + + /** + * Rollback function for old business logic to avoid security enhancements with 404 errors + */ + function disable_restriction_pre_queries() { + if ( ! UM()->options()->get( 'disable_restriction_pre_queries' ) ) { + return; + } + + remove_action( 'pre_get_terms', array( &$this, 'exclude_hidden_terms_query' ), 99 ); + remove_filter( 'widget_posts_args', array( &$this, 'exclude_restricted_posts_widget' ), 99 ); + remove_filter( 'wp_list_pages_excludes', array( &$this, 'exclude_restricted_pages' ), 10 ); + remove_filter( 'getarchives_where', array( &$this, 'exclude_restricted_posts_archives_widget' ), 99 ); + remove_filter( 'get_next_post_where', array( &$this, 'exclude_navigation_posts' ), 99 ); + remove_filter( 'get_previous_post_where', array( &$this, 'exclude_navigation_posts' ), 99 ); + remove_action( 'pre_get_posts', array( &$this, 'exclude_posts' ), 99 ); + remove_filter( 'posts_where', array( &$this, 'exclude_posts_where' ), 10 ); + remove_filter( 'wp_count_posts', array( &$this, 'custom_count_posts_handler' ), 99 ); + remove_filter( 'the_title', array( &$this, 'filter_restricted_post_title' ), 10 ); } @@ -628,6 +652,10 @@ if ( ! class_exists( 'um\core\Access' ) ) { * @return string */ function filter_restricted_post_title( $title, $id = null ) { + if ( ! UM()->options()->get( 'restricted_post_title_replace' ) ) { + return $title; + } + if ( current_user_can( 'administrator' ) ) { return $title; } diff --git a/includes/um-short-functions.php b/includes/um-short-functions.php index 56f96180..541afeff 100644 --- a/includes/um-short-functions.php +++ b/includes/um-short-functions.php @@ -1669,13 +1669,15 @@ function um_is_myprofile() { /** * Returns the edit profile link * + * @param int $user_id + * * @return string */ -function um_edit_profile_url() { +function um_edit_profile_url( $user_id = null ) { if ( um_is_core_page( 'user' ) ) { $url = UM()->permalinks()->get_current_url(); } else { - $url = um_user_profile_url(); + $url = isset( $user_id ) ? um_user_profile_url( $user_id ) : um_user_profile_url(); } $url = remove_query_arg( 'profiletab', $url ); From 773e7f26da9f589d5aab50850e4725a46a887a44 Mon Sep 17 00:00:00 2001 From: Nikita Sinelnikov Date: Wed, 25 Aug 2021 01:13:49 +0300 Subject: [PATCH 3/4] - updated readme; --- readme.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.txt b/readme.txt index 1fe0148f..ef895bd4 100644 --- a/readme.txt +++ b/readme.txt @@ -160,6 +160,8 @@ The plugin works with popular caching plugins by automatically excluding Ultimat * Enhancements: - Added: 'um_ignore_restricted_title' hook for workaround show post title of the restricted post + - Added: Disable pre-queries for restriction content logic ('disable_restriction_pre_queries') option for backward compatibility with business logic where 404 error for restricted content isn't a good way + - Added: Replace the restricted Post Title ('restricted_post_title_replace') option for ability to disable restricted post's title replace * Bugfixes: @@ -175,6 +177,7 @@ The plugin works with popular caching plugins by automatically excluding Ultimat - Fixed: The "Assignment to constant variable" JS error on some sites - Fixed: Keep description formatting in a view mode - Fixed: Profile form nonce handling, security enhancement + - Fixed: `um_edit_profile_url()`` function and added $user_id attribute - Optimized: Restriction content handlers, avoid queries duplicates or unnecessary queries = 2.2.2: August 3, 2021 = From c28e0211f13e05a7b9daaf1207493664001ace11 Mon Sep 17 00:00:00 2001 From: Nikita Sinelnikov Date: Wed, 25 Aug 2021 13:31:38 +0300 Subject: [PATCH 4/4] - fixed restriction logic; --- includes/admin/core/class-admin-metabox.php | 4 ++-- includes/admin/templates/access/restrict_content.php | 2 +- includes/core/class-access.php | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/includes/admin/core/class-admin-metabox.php b/includes/admin/core/class-admin-metabox.php index 01b73dbb..dd69ad14 100644 --- a/includes/admin/core/class-admin-metabox.php +++ b/includes/admin/core/class-admin-metabox.php @@ -431,7 +431,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) { '0' => __( 'Show access restricted message', 'ultimate-member' ), '1' => __( 'Redirect user', 'ultimate-member' ), ), - 'conditional' => array( '_um_access_hide_from_queries', '=', '0' ), + 'conditional' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? '' : array( '_um_access_hide_from_queries', '=', '0' ), ), array( 'id' => '_um_restrict_by_custom_message', @@ -583,7 +583,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) { '0' => __( 'Show access restricted message', 'ultimate-member' ), '1' => __( 'Redirect user', 'ultimate-member' ), ), - 'conditional' => array( '_um_access_hide_from_queries', '=', '0' ), + 'conditional' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? '' : array( '_um_access_hide_from_queries', '=', '0' ), ), array( 'id' => '_um_restrict_by_custom_message', diff --git a/includes/admin/templates/access/restrict_content.php b/includes/admin/templates/access/restrict_content.php index 42bd1b46..44a37b0d 100644 --- a/includes/admin/templates/access/restrict_content.php +++ b/includes/admin/templates/access/restrict_content.php @@ -96,7 +96,7 @@ if ( ! defined( 'ABSPATH' ) ) { '0' => __( 'Show access restricted message', 'ultimate-member' ), '1' => __( 'Redirect user', 'ultimate-member' ), ), - 'conditional' => array( '_um_access_hide_from_queries', '=', '0' ), + 'conditional' => UM()->options()->get( 'disable_restriction_pre_queries' ) ? '' : array( '_um_access_hide_from_queries', '=', '0' ), ), array( 'id' => '_um_restrict_by_custom_message', diff --git a/includes/core/class-access.php b/includes/core/class-access.php index 477902f8..92837eb6 100644 --- a/includes/core/class-access.php +++ b/includes/core/class-access.php @@ -1100,7 +1100,7 @@ if ( ! class_exists( 'um\core\Access' ) ) { continue; } else { $restriction_settings = $this->get_post_privacy_settings( $menu_item->object_id ); - if ( empty( $restriction_settings['_um_access_hide_from_queries'] ) ) { + if ( UM()->options()->get( 'disable_restriction_pre_queries' ) || empty( $restriction_settings['_um_access_hide_from_queries'] ) ) { $filtered_items[] = $menu_item; continue; } @@ -1241,7 +1241,7 @@ if ( ! class_exists( 'um\core\Access' ) ) { if ( is_object( $query ) && is_a( $query, '\WP_Query' ) && ( $query->is_main_query() || ! empty( $query->query_vars['um_main_query'] ) ) ) { if ( $is_singular ) { - if ( $this->is_restricted( $posts[0]->ID ) ) { + if ( ! UM()->options()->get( 'disable_restriction_pre_queries' ) && $this->is_restricted( $posts[0]->ID ) ) { $content_restriction = $this->get_post_privacy_settings( $posts[0]->ID ); if ( ! empty( $content_restriction['_um_access_hide_from_queries'] ) ) { unset( $posts[0] ); @@ -1276,7 +1276,7 @@ if ( ! class_exists( 'um\core\Access' ) ) { } else { if ( $is_singular ) { if ( ! isset( $restriction['_um_noaccess_action'] ) || '0' == $restriction['_um_noaccess_action'] ) { - if ( empty( $restriction['_um_access_hide_from_queries'] ) ) { + if ( UM()->options()->get( 'disable_restriction_pre_queries' ) || empty( $restriction['_um_access_hide_from_queries'] ) ) { /** * UM hook * @@ -1318,7 +1318,7 @@ if ( ! class_exists( 'um\core\Access' ) ) { } } } else { - if ( empty( $restriction['_um_access_hide_from_queries'] ) ) { + if ( UM()->options()->get( 'disable_restriction_pre_queries' ) || empty( $restriction['_um_access_hide_from_queries'] ) ) { $filtered_posts[] = $post; continue; }