mirror of
https://github.com/10h30/ultimatemember.git
synced 2026-06-05 15:09:37 +09:00
- review for secure functionality;
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
jQuery(document).on("ready", function(){
|
||||
|
||||
const scan_results_wrapper = jQuery(".um-secure-scan-results");
|
||||
const scan_button_elem = jQuery(".um-secure-scan-content");
|
||||
const scan_capabilities = jQuery("input[data-field_id^='banned_capabilities']");
|
||||
|
||||
var UM_Secure = {
|
||||
init: function() {
|
||||
scan_results_wrapper.css({
|
||||
'margin-top': '10px',
|
||||
'padding': '10px',
|
||||
'padding-bottom': '10px',
|
||||
'background-color': '#fff',
|
||||
'display': 'block',
|
||||
'max-height': '200px',
|
||||
'height': '500px',
|
||||
'overflow-y': 'scroll',
|
||||
});
|
||||
|
||||
scan_button_elem.on("click", function(e){
|
||||
UM_Secure.effect();
|
||||
e.preventDefault();
|
||||
var me = jQuery(this);
|
||||
me.prop("disabled", true);
|
||||
scan_results_wrapper.empty();
|
||||
|
||||
UM_Secure.log( wp.i18n.__( 'Scanning site..', 'ultimate-member' ) );
|
||||
|
||||
UM_Secure.ajax('');
|
||||
|
||||
});
|
||||
scan_capabilities.on("change", function(){
|
||||
scan_button_elem.attr('disabled', true );
|
||||
scan_button_elem.after( ' <small style="color: red;">' + wp.i18n.__( 'You must save the settings before you can run the scan.', 'ultimate-member' ) + '</small>' );
|
||||
scan_capabilities.off("change");
|
||||
})
|
||||
},
|
||||
ajax: function( last_capability ) {
|
||||
let checkedCaps = [];
|
||||
let checkedCapsInputs = scan_results_wrapper.parents('.um-form-table').find('input[type="checkbox"][data-field_id^="banned_capabilities_"]:checked');
|
||||
checkedCapsInputs.each(function (){
|
||||
checkedCaps.push( jQuery(this).data('field_id').replace('banned_capabilities_', '') );
|
||||
});
|
||||
|
||||
var request = {
|
||||
nonce: um_admin_scripts.nonce,
|
||||
capabilities: checkedCaps,
|
||||
last_scanned_capability: last_capability,
|
||||
};
|
||||
|
||||
wp.ajax.send('um_secure_scan_affected_users', {
|
||||
data: request,
|
||||
success: function (response) {
|
||||
if ( ! response.completed ) {
|
||||
UM_Secure.ajax( response.last_scanned_capability );
|
||||
UM_Secure.log( response.message );
|
||||
} else if ( response.completed ) {
|
||||
scan_results_wrapper.empty();
|
||||
UM_Secure.log( response.recommendations );
|
||||
scan_results_wrapper.find('.current').removeClass('current');
|
||||
scan_button_elem.removeAttr('disabled');
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
log: function( str ) {
|
||||
scan_results_wrapper.find('.current').removeClass('current');
|
||||
scan_results_wrapper.append( '<span class="current">' + str + '</span><br/>' );
|
||||
},
|
||||
effect: function() {
|
||||
var blink = function(){
|
||||
scan_results_wrapper.find(".current").fadeTo(100, 0.1).fadeTo(200, 1.0);
|
||||
};
|
||||
setInterval(blink, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
UM_Secure.init();
|
||||
});
|
||||
@@ -88,6 +88,11 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
|
||||
add_filter( 'post_updated_messages', array( &$this, 'post_updated_messages' ) );
|
||||
}
|
||||
|
||||
public function includes() {
|
||||
$this->notices();
|
||||
$this->secure();
|
||||
}
|
||||
|
||||
|
||||
function init_variables() {
|
||||
$this->role_meta = apply_filters(
|
||||
@@ -2056,13 +2061,12 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
|
||||
return $parent_file;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
*
|
||||
* @return core\Admin_Notices()
|
||||
*/
|
||||
function notices() {
|
||||
public function notices() {
|
||||
if ( empty( UM()->classes['admin_notices'] ) ) {
|
||||
UM()->classes['admin_notices'] = new core\Admin_Notices();
|
||||
}
|
||||
@@ -2072,13 +2076,13 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
|
||||
/**
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @return core\Secure
|
||||
* @return Secure
|
||||
*/
|
||||
public function secure() {
|
||||
if ( empty( UM()->classes['admin_secure'] ) ) {
|
||||
UM()->classes['admin_secure'] = new core\Secure();
|
||||
if ( empty( UM()->classes['um\admin\secure'] ) ) {
|
||||
UM()->classes['um\admin\secure'] = new Secure();
|
||||
}
|
||||
return UM()->classes['admin_secure'];
|
||||
return UM()->classes['um\admin\secure'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,28 @@
|
||||
<?php
|
||||
namespace um\admin\core;
|
||||
/**
|
||||
* Usermeta which we use:
|
||||
*
|
||||
* um_user_blocked__metadata
|
||||
* um_user_blocked
|
||||
* um_user_blocked__timestamp
|
||||
*
|
||||
* um_secure_has_reset_password
|
||||
* um_secure_has_reset_password__timestamp
|
||||
*/
|
||||
namespace um\admin;
|
||||
|
||||
use WP_User;
|
||||
use WP_Session_Tokens;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'um\admin\core\Secure' ) ) {
|
||||
if ( ! class_exists( 'um\admin\Secure' ) ) {
|
||||
|
||||
/**
|
||||
* Class Secure
|
||||
*
|
||||
* @package um\admin\core
|
||||
* @package um\admin
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
@@ -37,6 +47,21 @@ if ( ! class_exists( 'um\admin\core\Secure' ) ) {
|
||||
|
||||
add_action( 'um_settings_before_save', array( $this, 'check_secure_changes' ) );
|
||||
add_action( 'um_settings_save', array( $this, 'on_settings_save' ) );
|
||||
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
|
||||
|
||||
add_action( 'wp_ajax_um_secure_scan_affected_users', array( $this, 'ajax_scanner' ) );
|
||||
}
|
||||
|
||||
public function admin_scripts( $hook ) {
|
||||
// phpcs:disable WordPress.Security.NonceVerification
|
||||
if ( 'ultimate-member_page_um_options' !== $hook || ( isset( $_GET['tab'] ) && 'secure' !== $_GET['tab'] ) ) {
|
||||
return;
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification
|
||||
|
||||
wp_register_script( 'um_admin_secure', UM()->admin_enqueue()->js_url . 'um-admin-secure.js', array( 'jquery' ), UM_VERSION, true );
|
||||
wp_enqueue_script( 'um_admin_secure' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +93,7 @@ if ( ! class_exists( 'um\admin\core\Secure' ) ) {
|
||||
if ( ! empty( $users ) ) {
|
||||
foreach ( $users as $user_id ) {
|
||||
// Get an instance of WP_User_Meta_Session_Tokens
|
||||
$sessions_manager = \WP_Session_Tokens::get_instance( $user_id );
|
||||
$sessions_manager = WP_Session_Tokens::get_instance( $user_id );
|
||||
// Remove all the session for instance user.
|
||||
$sessions_manager->destroy_all();
|
||||
|
||||
@@ -119,7 +144,7 @@ if ( ! class_exists( 'um\admin\core\Secure' ) ) {
|
||||
// Delete blocked meta.
|
||||
delete_user_meta( $user_id, 'um_user_blocked__metadata' );
|
||||
delete_user_meta( $user_id, 'um_user_blocked' );
|
||||
delete_user_meta( $user_id, 'um_user_blocked__datetime' );
|
||||
delete_user_meta( $user_id, 'um_user_blocked__timestamp' );
|
||||
|
||||
// Don't need to reset a password.
|
||||
update_user_meta( $user_id, 'um_secure_has_reset_password', true );
|
||||
@@ -144,77 +169,49 @@ if ( ! class_exists( 'um\admin\core\Secure' ) ) {
|
||||
$nonce = wp_create_nonce( 'um-secure-expire-session-nonce' );
|
||||
$count_users = count_users();
|
||||
|
||||
/**
|
||||
* UM hook
|
||||
*
|
||||
* @type filter
|
||||
* @title um_secure_register_form_banned_capabilities
|
||||
* @description Modify banned capabilities for Register forms
|
||||
* @input_vars
|
||||
* [{"var":"$capabilities","type":"array","desc":"WordPress Administratrive Capabilities"}]
|
||||
* @change_log
|
||||
* ["Since: 2.6.8"]
|
||||
* @usage
|
||||
* <?php add_filter( 'um_secure_register_form_banned_capabilities', 'function_name', 10, 1 ); ?>
|
||||
* @example
|
||||
* <?php
|
||||
* add_filter( 'um_secure_register_form_banned_capabilities', 'my_banned_capabilities', 10, 1 );
|
||||
* function my_banned_capabilities( $capabiities ) {
|
||||
* // your code here
|
||||
* $capabiities[ ] = 'read'; // rejects all users with `read` capabilitiy.
|
||||
* return $capabiities;
|
||||
* }
|
||||
* ?>
|
||||
*/
|
||||
$banned_admin_capabilities = apply_filters(
|
||||
'um_secure_register_form_banned_capabilities',
|
||||
array(
|
||||
'create_sites',
|
||||
'delete_sites',
|
||||
'manage_network',
|
||||
'manage_sites',
|
||||
'manage_network_users',
|
||||
'manage_network_plugins',
|
||||
'manage_network_themes',
|
||||
'manage_network_options',
|
||||
'upgrade_network',
|
||||
'setup_network',
|
||||
'activate_plugins',
|
||||
'edit_dashboard',
|
||||
'edit_theme_options',
|
||||
'export',
|
||||
'import',
|
||||
'list_users',
|
||||
'remove_users',
|
||||
'switch_themes',
|
||||
'customize',
|
||||
'delete_site',
|
||||
'update_core',
|
||||
'update_plugins',
|
||||
'update_themes',
|
||||
'install_plugins',
|
||||
'install_themes',
|
||||
'delete_themes',
|
||||
'delete_plugins',
|
||||
'edit_plugins',
|
||||
'edit_themes',
|
||||
'edit_files',
|
||||
'edit_users',
|
||||
'add_users',
|
||||
'create_users',
|
||||
'delete_users',
|
||||
'level_10',
|
||||
'manage_options',
|
||||
'promote_users',
|
||||
)
|
||||
);
|
||||
|
||||
$banned_capabilities = array();
|
||||
$banned_capabilities = array();
|
||||
$banned_admin_capabilities = UM()->common()->secure()->get_banned_capabilities_list();
|
||||
foreach ( $banned_admin_capabilities as $cap ) {
|
||||
$banned_capabilities[ $cap ] = $cap;
|
||||
}
|
||||
|
||||
$disabled_capabilities = UM()->options()->get_default( 'banned_capabilities' );
|
||||
$disabled_capabilities_text = '<strong>' . implode( '</strong>, <strong>', $disabled_capabilities ) . '</strong>';
|
||||
|
||||
$scanner_content = '<button class="button um-secure-scan-content">' . esc_html__( 'Scan Now', 'ultimate-member' ) . '</button>';
|
||||
$scanner_content .= '<span class="um-secure-scan-results">';
|
||||
$scanner_content .= esc_html__( 'Last scan:', 'ultimate-member' ) . ' ';
|
||||
$scan_status = get_option( 'um_secure_scan_status' );
|
||||
$last_scanned_time = get_option( 'um_secure_last_time_scanned' );
|
||||
if ( ! empty( $last_scanned_time ) ) {
|
||||
$scanner_content .= human_time_diff( strtotime( $last_scanned_time ), strtotime( current_time( 'mysql' ) ) ) . ' ' . esc_html__( 'ago', 'ultimate-member' );
|
||||
if ( 'started' === $scan_status ) {
|
||||
$scanner_content .= ' - ' . esc_html__( 'Not Completed.', 'ultimate-member' );
|
||||
}
|
||||
} else {
|
||||
$scanner_content .= esc_html__( 'Not Scanned yet.', 'ultimate-member' );
|
||||
}
|
||||
$scanner_content .= '</span>';
|
||||
|
||||
$secure_fields = array(
|
||||
array(
|
||||
'id' => 'banned_capabilities',
|
||||
'type' => 'multi_checkbox',
|
||||
'multi' => true,
|
||||
'columns' => 2,
|
||||
'options_disabled' => $disabled_capabilities,
|
||||
'options' => $banned_capabilities,
|
||||
'label' => __( 'Banned Administrative Capabilities', 'ultimate-member' ),
|
||||
// translators: %s are disabled default capabilities that are enabled by default.
|
||||
'description' => sprintf( __( 'All the above are default Administrator & Super Admin capabilities. When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be flagged with this option. The %s capabilities are locked to ensure no users will be created with these capabilities.', 'ultimate-member' ), $disabled_capabilities_text ),
|
||||
),
|
||||
array(
|
||||
'id' => 'secure_scan_affected_users',
|
||||
'type' => 'info_text',
|
||||
'label' => __( 'Scanner', 'ultimate-member' ),
|
||||
'value' => $scanner_content,
|
||||
'description' => __( 'Scan your site to check for vulnerabilities prior to Ultimate Member version 2.6.7 and get recommendations to secure your site.', 'ultimate-member' ),
|
||||
),
|
||||
array(
|
||||
'id' => 'lock_register_forms',
|
||||
'type' => 'checkbox',
|
||||
@@ -241,28 +238,21 @@ if ( ! class_exists( 'um\admin\core\Secure' ) ) {
|
||||
);
|
||||
}
|
||||
|
||||
$disabled_capabilities = UM()->options()->get_default( 'banned_capabilities' );
|
||||
$disabled_capabilities_text = '<strong>' . implode( '</strong>, <strong>', $disabled_capabilities ) . '</strong>';
|
||||
|
||||
$secure_fields = array_merge(
|
||||
$secure_fields,
|
||||
array(
|
||||
array(
|
||||
'id' => 'banned_capabilities',
|
||||
'type' => 'multi_checkbox',
|
||||
'multi' => true,
|
||||
'columns' => 2,
|
||||
'options_disabled' => UM()->options()->get_default( 'banned_capabilities' ),
|
||||
'options' => $banned_capabilities,
|
||||
'label' => __( 'Banned Administrative Capabilities', 'ultimate-member' ),
|
||||
// translators: %s are disabled default capabilities that are enabled by default.
|
||||
'description' => sprintf( __( 'All the above are default Administrator & Super Admin capabilities. When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be flagged with this option. The %s capabilities are locked to ensure no users will be created with these capabilities.', 'ultimate-member' ), $disabled_capabilities_text ),
|
||||
'id' => 'secure_ban_admins_accounts',
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable ban for administrative capabilities', 'ultimate-member' ),
|
||||
'description' => __( ' When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be banned.', 'ultimate-member' ),
|
||||
),
|
||||
array(
|
||||
'id' => 'secure_notify_admins_banned_accounts',
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Notify Administrators', 'ultimate-member' ),
|
||||
'description' => __( 'When enabled, All administrators will be notified when someone has suspicious activities in Profile & Register forms.', 'ultimate-member' ),
|
||||
'conditional' => array( 'secure_ban_admins_accounts', '=', 1 ),
|
||||
),
|
||||
array(
|
||||
'id' => 'secure_notify_admins_banned_accounts__interval',
|
||||
@@ -303,7 +293,7 @@ if ( ! class_exists( 'um\admin\core\Secure' ) ) {
|
||||
$is_blocked = um_user( 'um_user_blocked' );
|
||||
$account_status = um_user( 'account_status' );
|
||||
if ( ! empty( $is_blocked ) && in_array( $account_status, array( 'rejected', 'inactive' ), true ) ) {
|
||||
$datetime = um_user( 'um_user_blocked__datetime' );
|
||||
$datetime = um_user( 'um_user_blocked__timestamp' );
|
||||
$val .= '<div><small>' . esc_html__( 'Blocked Due to Suspicious Activity', 'ultimate-member' ) . '</small></div>';
|
||||
$nonce = wp_create_nonce( 'um-security-restore-account-nonce-' . $user_id );
|
||||
$restore_account_url = admin_url( 'users.php?user_id=' . $user_id . '&um_secure_restore_account=1&_wpnonce=' . $nonce );
|
||||
@@ -61,6 +61,8 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
|
||||
|
||||
//$this->future_changed();
|
||||
|
||||
$this->common_secure();
|
||||
|
||||
/**
|
||||
* UM hook
|
||||
*
|
||||
@@ -522,7 +524,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
|
||||
$messages[1]['content'] = __( 'Other users have been updated.', 'ultimate-member' );
|
||||
break;
|
||||
case 'um_secure_expire_sessions':
|
||||
$messages[0]['content'] = __( 'All users sessions have been expired.', 'ultimate-member' );
|
||||
$messages[0]['content'] = __( 'All users sessions have been successfully destroyed.', 'ultimate-member' );
|
||||
break;
|
||||
case 'um_secure_restore':
|
||||
$messages[0]['content'] = __( 'Account has been successfully restored.', 'ultimate-member' );
|
||||
@@ -786,6 +788,65 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
|
||||
);
|
||||
}
|
||||
|
||||
public function common_secure() {
|
||||
if ( UM()->options()->get( 'lock_register_forms' ) ) {
|
||||
ob_start();
|
||||
?>
|
||||
<p>
|
||||
<?php esc_html_e( 'Your Register forms are now locked. You can unlock them in Ultimate Member > Settings > Secure > Lock All Register Forms.', 'ultimate-member' ); ?>
|
||||
</p>
|
||||
<?php
|
||||
$message = ob_get_clean();
|
||||
$this->add_notice(
|
||||
'common_secure_register',
|
||||
array(
|
||||
'class' => 'warning',
|
||||
'message' => $message,
|
||||
'dismissible' => true,
|
||||
),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
if ( UM()->options()->get( 'display_login_form_notice' ) ) {
|
||||
ob_start();
|
||||
?>
|
||||
<p>
|
||||
<?php esc_html_e( 'Mandatory password changes has been enabled. You can disable them in Ultimate Member > Settings > Secure > Display Login form notice to reset passwords.', 'ultimate-member' ); ?>
|
||||
</p>
|
||||
<?php
|
||||
$message = ob_get_clean();
|
||||
$this->add_notice(
|
||||
'common_secure_password_reset',
|
||||
array(
|
||||
'class' => 'warning',
|
||||
'message' => $message,
|
||||
'dismissible' => true,
|
||||
),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
if ( UM()->options()->get( 'secure_ban_admins_accounts' ) ) {
|
||||
ob_start();
|
||||
?>
|
||||
<p>
|
||||
<?php esc_html_e( 'Ban for administrative capabilities is enabled. You can disable them in Ultimate Member > Settings > Secure > Enable ban for administrative capabilities.', 'ultimate-member' ); ?>
|
||||
</p>
|
||||
<?php
|
||||
$message = ob_get_clean();
|
||||
$this->add_notice(
|
||||
'common_secure_suspicious_activity',
|
||||
array(
|
||||
'class' => 'warning',
|
||||
'message' => $message,
|
||||
'dismissible' => true,
|
||||
),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function dismiss_notice() {
|
||||
UM()->admin()->check_ajax_nonce();
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace um\ajax;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'um\ajax\Init' ) ) {
|
||||
|
||||
/**
|
||||
* Class Init
|
||||
*
|
||||
* @package um\ajax
|
||||
*/
|
||||
class Init {
|
||||
|
||||
/**
|
||||
* Create classes' instances where __construct isn't empty for hooks init
|
||||
*
|
||||
* @used-by \UM::includes()
|
||||
*/
|
||||
public function includes() {
|
||||
$this->secure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @return Secure
|
||||
*/
|
||||
public function secure() {
|
||||
if ( empty( UM()->classes['um\ajax\secure'] ) ) {
|
||||
UM()->classes['um\ajax\secure'] = new Secure();
|
||||
}
|
||||
return UM()->classes['um\ajax\secure'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,410 @@
|
||||
<?php
|
||||
namespace um\ajax;
|
||||
|
||||
use WP_Session_Tokens;
|
||||
use WP_User_Query;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Secure
|
||||
*
|
||||
* @package um\ajax
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
class Secure {
|
||||
|
||||
/**
|
||||
* Secure constructor.
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'wp_ajax_um_secure_scan_affected_users', array( $this, 'ajax_scanner' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan affected users
|
||||
*/
|
||||
public function ajax_scanner() {
|
||||
if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'um-admin-nonce' ) || ! current_user_can( 'manage_options' ) ) {
|
||||
wp_die( esc_attr__( 'Security Check', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
$last_scanned_capability = sanitize_key( $_REQUEST['last_scanned_capability'] );
|
||||
|
||||
if ( empty( $last_scanned_capability ) ) {
|
||||
delete_option( 'um_secure_scanned_details' );
|
||||
update_option( 'um_secure_scan_status', 'started' );
|
||||
update_option( 'um_secure_last_time_scanned', current_time( 'mysql' ) );
|
||||
}
|
||||
|
||||
$scan_details = get_option( 'um_secure_scanned_details' );
|
||||
|
||||
if ( ! empty( $_REQUEST['capabilities'] ) ) {
|
||||
$request_capabilities = is_array( $_REQUEST['capabilities'] ) ? $_REQUEST['capabilities'] : array( $_REQUEST['capabilities'] );
|
||||
$arr_banned_caps = array_map( 'sanitize_key', $request_capabilities );
|
||||
} else {
|
||||
$arr_banned_caps = UM()->options()->get( 'banned_capabilities' );
|
||||
}
|
||||
|
||||
$proceed = false;
|
||||
$completed = false;
|
||||
$message = '';
|
||||
$scanned_cap = '';
|
||||
$user_affected = false;
|
||||
$count_users = 0;
|
||||
|
||||
$last_element = end( $arr_banned_caps );
|
||||
|
||||
foreach ( $arr_banned_caps as $cap ) {
|
||||
|
||||
if ( empty( $last_scanned_capability ) ) {
|
||||
$proceed = true;
|
||||
} else {
|
||||
if ( $last_scanned_capability === $cap ) { // if this was the last capability, skip this and proceed the next loop.
|
||||
$proceed = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $proceed ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'capability' => $cap,
|
||||
'role__not_in' => array( 'administrator' ),
|
||||
'fields' => 'ids',
|
||||
);
|
||||
$wp_user_query = new WP_User_Query( $args );
|
||||
$count_users = $wp_user_query->get_total();
|
||||
if ( $count_users <= 0 ) {
|
||||
$message = '<strong>`' . esc_html( $cap ) . '`</strong> <span style="color:green">' . esc_html__( ' is safe ' ) . '</span>';
|
||||
} else {
|
||||
$user_affected = true;
|
||||
$message = '<strong>`' . esc_html( $cap ) . '`</strong> <span style="color:red">' . sprintf( /* translators: has affected %d user account */ _n( 'has affected %d user account.', ' has affected %d user accounts.', $count_users, 'ultimate-member' ), $count_users ) . '</span>';
|
||||
}
|
||||
|
||||
if ( $last_element === $cap ) {
|
||||
$completed = true;
|
||||
update_option( 'um_secure_scan_status', 'completed' );
|
||||
}
|
||||
|
||||
$scanned_cap = $cap;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ( $user_affected ) {
|
||||
$scan_details['affected_caps'][] = $scanned_cap;
|
||||
|
||||
$scan_details['scanned_caps'][ $scanned_cap ] = array(
|
||||
'total_affected_users' => $count_users,
|
||||
'users' => $wp_user_query->get_results(),
|
||||
);
|
||||
|
||||
if ( ! isset( $scan_details['scanned_caps']['total_all_cap_flagged'] ) ) {
|
||||
$scan_details['scanned_caps']['total_all_cap_flagged'] = 1;
|
||||
} else {
|
||||
++$scan_details['scanned_caps']['total_all_cap_flagged'];
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset( $scan_details['scanned_caps']['total_all_affected_users'] ) ) {
|
||||
$scan_details['scanned_caps']['total_all_affected_users'] = absint( $count_users );
|
||||
} else {
|
||||
$scan_details['scanned_caps']['total_all_affected_users'] = absint( $scan_details['scanned_caps']['total_all_affected_users'] ) + absint( $count_users );
|
||||
}
|
||||
|
||||
update_option( 'um_secure_scanned_details', $scan_details );
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'last_scanned_capability' => $scanned_cap,
|
||||
'message' => $message,
|
||||
'completed' => $completed,
|
||||
'recommendations' => $completed ? wp_kses( $this->scan_recommendations(), UM()->get_allowed_html( 'templates' ) ) : '',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recommendations after the scan completed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function scan_recommendations() {
|
||||
global $wp_roles, $wpdb;
|
||||
$br = '</br>';
|
||||
$check = '<span class="dashicons dashicons-yes-alt" style="color:green"></span>';
|
||||
$flag = '<span class="dashicons dashicons-flag" style="color:red"></span>';
|
||||
$warning = '<span class="dashicons dashicons-warning" style="color:red"></span>';
|
||||
|
||||
$all_plugins = get_plugins();
|
||||
$active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) );
|
||||
|
||||
$content = '-----' . $br . $br;
|
||||
|
||||
$suspicious_accounts = new WP_User_Query(
|
||||
array(
|
||||
'relation' => 'AND',
|
||||
'number' => -1,
|
||||
'meta_query' => array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => 'submitted',
|
||||
'value' => sprintf( ':"%s";', $wpdb->prefix . '_capabilities' ),
|
||||
'compare' => 'LIKE',
|
||||
),
|
||||
array(
|
||||
'key' => 'submitted',
|
||||
'value' => sprintf( ':"%s";', $wpdb->prefix . '_user_level' ),
|
||||
'compare' => 'LIKE',
|
||||
),
|
||||
array(
|
||||
'key' => 'submitted',
|
||||
'value' => sprintf( '.*%s";', '_capabilities' ),
|
||||
'compare' => 'REGEXP',
|
||||
),
|
||||
array(
|
||||
'key' => 'submitted',
|
||||
'value' => sprintf( '.*%s";', '_user_level' ),
|
||||
'compare' => 'LIKE',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$suspicious_accounts_count = $suspicious_accounts->get_total();
|
||||
$susp_accounts = $suspicious_accounts->get_results();
|
||||
|
||||
/**
|
||||
* Disable and Kickout Suspicious accounts.
|
||||
*/
|
||||
if ( $suspicious_accounts_count > 0 ) {
|
||||
$arr_might_lookout_accounts = array();
|
||||
$arr_dates_registered = array();
|
||||
$arr_suspected_accounts = array();
|
||||
if ( ! empty( $susp_accounts ) ) {
|
||||
foreach ( $susp_accounts as $user ) {
|
||||
|
||||
$arr_suspected_accounts[] = $user->ID;
|
||||
$arr_dates_registered[] = strtotime( $user->user_registered );
|
||||
|
||||
if ( $user->__get( 'um_user_blocked' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UM()->common()->secure()->revoke_caps( $user );
|
||||
// Get an instance of WP_User_Meta_Session_Tokens
|
||||
$sessions_manager = WP_Session_Tokens::get_instance( $user->ID );
|
||||
// Remove all the session data for all users.
|
||||
$sessions_manager->destroy_all();
|
||||
}
|
||||
}
|
||||
|
||||
$date_query = array();
|
||||
$oldest_date = min( $arr_dates_registered );
|
||||
$newest_date = max( $arr_dates_registered );
|
||||
|
||||
$might_affected_users = new WP_User_Query(
|
||||
array(
|
||||
'number' => -1,
|
||||
'relation' => 'AND',
|
||||
'date_query' => array(
|
||||
'after' => human_time_diff( $oldest_date, strtotime( current_time( 'mysql' ) ) ) . ' ago',
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$content .= '<span style="font-size:19px;padding-bottom:10px;display:block;border-bottom:1px solid #ccc;" id="um-secure-scanner-complete">' . ( $suspicious_accounts_count > 0 ? $warning : $check ) . __( 'Scan Complete.', 'ultimate-member' ) . '</span>';
|
||||
|
||||
$option = get_option( 'um_secure_scanned_details', $susp_accounts );
|
||||
$scan_details = $option['scanned_caps'];
|
||||
|
||||
if ( $suspicious_accounts_count > 0 ) {
|
||||
update_option( 'um_secure_found_suspicious_accounts', true );
|
||||
$content .= $br . $flag . '<strong>Suspcious Accounts Detected!</strong> <br/>';
|
||||
$content .= $br . __( 'We have found ', 'ultimate-member' ) . '<strong style="color:red;">' . /* translators: %s suspcious account */ sprintf( _n( '%s suspcious account', '%s suspcious accounts', $suspicious_accounts_count, 'ultimate-member' ), $suspicious_accounts_count ) . '</strong> ' . __( 'created on your site via Ultimate Member Forms.', 'ultimate-member' );
|
||||
$content .= $br . __( 'We\'ve temporarily disabled the suspcious account(s) for you to <strong>take actions</strong>.', 'ultimate-member' );
|
||||
|
||||
if ( $might_affected_users->get_total() > 0 ) {
|
||||
$od = gmdate( 'F m, Y', $oldest_date );
|
||||
$nd = gmdate( 'F m, Y', $newest_date );
|
||||
if ( $od !== $nd ) {
|
||||
$date_registered = $od . ' to ' . $nd;
|
||||
} else {
|
||||
$date_registered = $od;
|
||||
}
|
||||
$content .= $br . $br . __( 'Also, We\'ve found ', 'ultimate-member' ) . '<strong style="color:red;">' . /* translators: %s suspcious account */ sprintf( _n( '%s account', '%s accounts', $might_affected_users->get_total(), 'ultimate-member' ), $might_affected_users->get_total() ) . '</strong> ' . sprintf( _n( 'created on %s when the suspicious account was created.', 'created on %s when the suspicious accounts were created.', $suspicious_accounts_count, 'ultimate-member' ), $date_registered );
|
||||
|
||||
}
|
||||
} else {
|
||||
$content .= $br . '<strong>Suspcious Accounts</strong> <br/>';
|
||||
$content .= $br . $check . ' No suspicious accounts found. <br/>';
|
||||
}
|
||||
|
||||
$content .= $br . $br . __( 'PLEASE READ OUR <strong>RECOMMENDATIONS</strong> BELOW: ', 'ultimate-member' ) . $br;
|
||||
|
||||
$content .= $br . '<div style="padding:10px; border:1px solid #ccc;"><strong style="color:red">WARNING:</strong> Ensure that you\'ve created a full backup of your site as your restoration point before changing anything on your site with our recommendations.</div>';
|
||||
if ( $suspicious_accounts_count > 0 ) {
|
||||
$lock_register_forms_url = admin_url( 'admin.php?page=um_options&tab=secure&um_secure_lock_register_forms=1&_wpnonce=' . wp_create_nonce( 'um_secure_lock_register_forms' ) );
|
||||
$content .= $br . '1. Please temporarily lock all your active Register forms. <a href="' . esc_attr( $lock_register_forms_url ) . '" target="_blank">Click here to lock them now.</a> You can unblock the Register forms later. Just go to Ultimate Member > Settings > Secure > uncheck the option "Lock All Register Forms".';
|
||||
$content .= $br . $br;
|
||||
$suspicious_accounts_url = admin_url( 'users.php?um_status=inactive' );
|
||||
|
||||
$content .= '2. Review all suspicious accounts and delete them completely. <a href="' . esc_attr( $suspicious_accounts_url ) . '" target="_blank">Click here to review accounts.</a>';
|
||||
$content .= $br . $br;
|
||||
|
||||
$nonce = wp_create_nonce( 'um-secure-expire-session-nonce' );
|
||||
$destroy_all_sessions_url = admin_url( '?um_secure_expire_all_sessions=1&_wpnonce=' . esc_attr( $nonce ) . '&except_me=1' );
|
||||
$content .= '3. If accounts are suspicious to you, please destroy all user sessions to logout active users on your site. <a href="' . esc_attr( $destroy_all_sessions_url ) . '" target="_blanl">Click here to Destroy Sessions now</a>';
|
||||
|
||||
$content .= $br . $br;
|
||||
$content .= '4. Run a complete scan on your site using third-party Security plugins such as <a target="_blank" href="' . esc_attr( admin_url( 'plugin-install.php?s=Jetpack%2520Protect%2520WP%2520Scan&tab=search&type=term' ) ) . '">WPScan/Jetpack Protect or WordFence Security</a>.';
|
||||
|
||||
$content .= $br . $br;
|
||||
$nonce = wp_create_nonce( 'um-secure-enable-reset-pass-nonce' );
|
||||
$reset_pass_sessions_url = admin_url( '?um_secure_enable_reset_password=1&_wpnonce=' . esc_attr( $nonce ) . '&except_me=1' );
|
||||
|
||||
$content .= '5. Force users to Reset their Passwords. <a target="_blank" href="' . esc_attr( $reset_pass_sessions_url ) . '">Click here to enable this option</a>. When this option is enabled, users will be asked to reset their passwords(one-time) on the next login in the UM Login form.';
|
||||
$content .= $br . $br;
|
||||
|
||||
$content .= '6. Once your site is secured, please create or enable Daily Backups of your server/site. You can contact your hosting provider to assist you on this matter.';
|
||||
$content .= $br . $br;
|
||||
|
||||
$content .= '👇 Read more Recommendations below.';
|
||||
$content .= $br;
|
||||
}
|
||||
|
||||
if ( get_option( 'users_can_register' ) ) {
|
||||
$content .= $br . $flag . '<strong>Default WP Register Form is Enabled</strong>';
|
||||
$content .= $br . 'The default WordPress Register form is enabled. If you\'re getting Spam User Registrations, we recommend that you enable a Challenge-Response plugin such as our <a href="https://wordpress.org/plugins/um-recaptcha/" target="_blank">Ultimate Member - ReCaptcha</a> extension.';
|
||||
$content .= $br;
|
||||
}
|
||||
|
||||
$content .= $br . '<strong>Block Disposable Email Addresses/Domains</strong>';
|
||||
if ( empty( UM()->options()->get( 'blocked_emails' ) ) ) {
|
||||
$content .= $br . $flag . 'You are not blocking email addresses or disposable email domains that are mostly used for Spam Account Registrations. You can get the list of disposable email domains from <a href="https://github.com/champsupertramp/disposable-email-domains/blob/master/um_disposable_email_blocklist.txt" target="_blank">this repository</a> and then add them to <a target="_blank" href="' . esc_attr( 'admin.php?page=um_options&tab=access§ion=other' ) . '">Blocked Email Addresses</a> options.';
|
||||
$content .= $br;
|
||||
} else {
|
||||
$content .= $br . 'The default WordPress Register form is enabled. If you\'re getting Spam User Registrations, we recommend that you enable a Challenge-Response plugin such as our <a href="https://wordpress.org/plugins/um-recaptcha/" target="_blank">Ultimate Member - ReCaptcha</a> extension.';
|
||||
$content .= $br;
|
||||
}
|
||||
|
||||
$content .= $br . '<strong>Manage User Roles & Capabilities</strong> <br/>';
|
||||
if ( absint( $scan_details['total_all_affected_users'] ) > 0 ) {
|
||||
$count_flagged_caps = $scan_details['total_all_cap_flagged'];
|
||||
$count_users = $scan_details['total_all_affected_users'];
|
||||
$affected_caps = $option['affected_caps'];
|
||||
$affected_roles = array();
|
||||
|
||||
$all_roles = $wp_roles->roles;
|
||||
$editable_roles = apply_filters( 'editable_roles', $all_roles );
|
||||
foreach ( $affected_caps as $cap ) {
|
||||
foreach ( $editable_roles as $role_key => $role ) {
|
||||
if ( in_array( $cap, array_keys( $role['capabilities'] ), true ) ) {
|
||||
$affected_roles[ $role_key ] = $role['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$content .= $br . $flag . 'We have found ' . sprintf( /* translators: */ _n( ' %d user account', ' %d user accounts ', $count_users, 'ultimate-member' ), $count_users );
|
||||
$content .= sprintf( /* translators: */ _n( ' affected by %d capability selected in the Banned Administrative Capabilities.', ' affected by one of the %d capabilities selected in the Banned Administrative Capabilities.', $count_flagged_caps, 'ultimate-member' ), $count_flagged_caps );
|
||||
|
||||
$content .= $br . '- ' . implode( '<br/> - ', $affected_caps );
|
||||
|
||||
$content .= $br . $br . 'The flagged capabilities are related to the following roles: ' . $br . ' - ' . implode( '<br/> - ', array_values( $affected_roles ) );
|
||||
|
||||
$content .= $br . $br . 'The affected user accounts will be flagged as suspicious when they update their Profile/Account. If you are not using these capabilities, you may remove them from the roles in the <a target="_blank" href="' . admin_url( 'admin.php?page=um_roles' ) . '">User Role settings</a>. If the roles are not created via Ultimate Member > User Roles, you can use a <a href="' . admin_url( 'plugin-install.php?s=User%2520Role%2520Editor%2520WordPress%2520&tab=search&type=term' ) . '" target="_blank">third-party plugin</a> to modify the role capability.';
|
||||
$content .= $br . $br . 'We strongly recommend that you never assign roles with the same capabilities as your administrators for your members/users and that may allow them to access the admin-side features and functionalities of your WordPress site.';
|
||||
} else {
|
||||
$content .= $check . 'Roles & Capabilities are all secured. No users are using the same capabilities as your administrators.';
|
||||
}
|
||||
|
||||
$content .= $br . $br . '<strong>Require Strong Passwords</strong>';
|
||||
if ( ! UM()->options()->get( 'require_strongpass' ) ) {
|
||||
$content .= $br . $flag . 'We recommend that you enable and require "Strong Password" feature for all the Register, Reset Password & Account forms.';
|
||||
$content .= $br . ' <a href="' . admin_url( 'admin.php?page=um_options§ion=users' ) . '" target="_blank" >Click here to enable.</a>';
|
||||
} else {
|
||||
$content .= $br . $check . 'Your forms are already configured to require of using strong passwords.';
|
||||
}
|
||||
|
||||
$content .= $br . $br . '<strong>Secure Site\'s Connection</strong>';
|
||||
if ( ! isset( $_SERVER['HTTPS'] ) || 'on' !== $_SERVER['HTTPS'] ) {
|
||||
$content .= $br . $flag . 'Your site cannot provide a secure connection. Please contact your hosting provider to enable SSL certifications on your server.';
|
||||
}
|
||||
|
||||
$content .= $br . $br . '<strong>Install Challenge-Response plugin to Login & Register Forms</strong>';
|
||||
if ( ! array_key_exists( 'um-recaptcha/um-recaptcha.php', $all_plugins ) ) {
|
||||
if ( ! isset( $_SERVER['HTTPS'] ) || 'on' !== $_SERVER['HTTPS'] ) {
|
||||
$content .= $br . $flag . 'We recommend that you install and enable ReCaptcha to Login & Register forms.';
|
||||
}
|
||||
} else {
|
||||
if ( in_array( 'um-recaptcha/um-recaptcha.php', $active_plugins, true ) ) {
|
||||
$content .= $br . $check . 'Ultimate Member ReCaptcha is actived.';
|
||||
$um_forms = get_posts( 'post_type=um_form&numberposts=-1&fields=ids' );
|
||||
foreach ( $um_forms as $fid ) {
|
||||
switch ( get_post_meta( $fid, '_um_mode', true ) ) {
|
||||
case 'register':
|
||||
$has_captcha = absint( get_post_meta( $fid, '_um_register_g_recaptcha_status', true ) );
|
||||
$content .= $br . ' - Register: <a target="_blank" href="' . get_edit_post_link( $fid ) . '">' . get_the_title( $fid ) . '</a> recaptcha ' . ( 1 === $has_captcha ? ' is <strong>enabled</strong> ' . $check : 'is <strong>disabled</strong> ' . $flag );
|
||||
break;
|
||||
case 'login':
|
||||
$has_captcha = absint( get_post_meta( $fid, '_um_login_g_recaptcha_status', true ) );
|
||||
$content .= $br . ' - Login: <a target="_blank" href="' . get_edit_post_link( $fid ) . '">' . get_the_title( $fid ) . '</a> recaptcha ' . ( 1 === $has_captcha ? ' is <strong>enabled</strong> ' . $check : 'is <strong>disabled</strong> ' . $flag );
|
||||
break;
|
||||
}
|
||||
}
|
||||
$reset_pass_form = absint( UM()->options()->get( 'g_recaptcha_password_reset' ) );
|
||||
$content .= $br . ' - Reset Password Form\'s recaptcha ' . ( 1 === $reset_pass_form ? ' is <strong>enabled</strong> ' . $check : 'is <strong>disabled</strong> ' . $flag );
|
||||
|
||||
} elseif ( array_key_exists( 'um-recaptcha/um-recaptcha.php', $all_plugins ) ) {
|
||||
$content .= $br . $flag . 'Ultimate Member ReCaptcha is installed but not activated.';
|
||||
} else {
|
||||
$content .= $br . $flag . 'We recommend that you install and enable <a href="https://wordpress.org/plugins/um-recaptcha/" target="_blank">ReCaptcha</a> to Login & Register forms.';
|
||||
}
|
||||
}
|
||||
|
||||
$update_plugins = get_site_transient( 'update_plugins' );
|
||||
$update_themes = get_site_transient( 'update_themes' );
|
||||
$update_wp_core = get_site_transient( 'update_core' );
|
||||
global $wp_version;
|
||||
$content .= $br . $br . '<strong>Keep Themes & Plugins up to date.</strong>';
|
||||
$content .= $br . __( 'It is important that you update your themes/plugins if the theme/plugin creators update is aimed at fixing security, bug and vulnerability issues. It is not a good idea to ignore available updates as this may give hackers an advantage when trying to access your website.', 'ultimate-member' );
|
||||
|
||||
if ( isset( $update_plugins->response ) && ! empty( $update_plugins->response ) ) {
|
||||
$content .= $br . $br . $flag . sprintf( /* translators: */ _n( 'There\'s %d plugin that requires an update.', 'There are %d plugins that require updates', count( $update_plugins->response ), 'ultimate-member' ), count( $update_plugins->response ) ) . ' <a target="_blank" href="' . admin_url( 'update-core.php' ) . '">Update Plugins Now</a>';
|
||||
foreach ( $update_plugins->response as $plugin_name => $data ) {
|
||||
$content .= $br . ' - ' . $plugin_name;
|
||||
}
|
||||
} else {
|
||||
$content .= $br . $br . $check . __( 'Plugins are up to date.', 'ultimate-member' );
|
||||
}
|
||||
|
||||
if ( isset( $update_themes->response ) && ! empty( $update_themes->response ) ) {
|
||||
$content .= $br . $br . $flag . sprintf( /* translators: */ _n( 'There\'s %d theme that requires an update.', 'There are %d themes that require updates', count( $update_plugins->response ), 'ultimate-member' ), count( $update_plugins->response ) ) . ' <a target="_blank" href="' . admin_url( 'update-core.php' ) . '">Update Themes Now</a>';
|
||||
foreach ( $update_themes->response as $theme_name => $data ) {
|
||||
$content .= $br . ' - ' . $theme_name;
|
||||
}
|
||||
} else {
|
||||
$content .= $br . $br . $check . __( 'Themes are up to date.', 'ultimate-member' );
|
||||
}
|
||||
|
||||
if ( isset( $update_themes->current ) && $wp_version !== $update_themes->current ) {
|
||||
$content .= $br . $br . $flag . __( 'There\'s a new version of WordPress.', 'ultimate-member' ) . '<a target="_blank" href="' . admin_url( 'update-core.php' ) . '">Update WordPress Now</a>';
|
||||
} else {
|
||||
$content .= $br . $br . $check . __( 'You\'re using the latest version of WordPress', 'ultimate-member' ) . '(' . esc_attr( $wp_version ) . ')';
|
||||
}
|
||||
|
||||
$content .= $br . $br . __( 'That\'s all. If you have any recommendation on how to secure your site or have questions, please contact us on our <a href="https://ultimatemember.com/feedback/" target="_blank">feedback page</a>. ', 'ultimate-member' );
|
||||
|
||||
update_option( 'um_secure_scan_result_content', $content );
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
@@ -495,10 +495,18 @@ if ( ! class_exists( 'um\Config' ) ) {
|
||||
'body' => '{display_name} has just deleted their {site_name} account.',
|
||||
'description' => __('Whether to receive notification when an account is deleted','ultimate-member'),
|
||||
'recipient' => 'admin'
|
||||
)
|
||||
),
|
||||
'suspicious-activity' => array(
|
||||
'key' => 'suspicious-activity',
|
||||
'title' => __( 'Secure: Suspicious Account Activity', 'ultimate-member' ),
|
||||
'subject' => __( '[{site_name}] Suspicious Account Activity', 'ultimate-member' ),
|
||||
'body' => 'This is to inform you that there are suspicious activities with the following accounts: {user_profile_link}',
|
||||
'description' => __( 'Whether to receive notification when suspicious account activity is detected.', 'ultimate-member' ),
|
||||
'recipient' => 'admin',
|
||||
'default_active' => true,
|
||||
),
|
||||
) );
|
||||
|
||||
|
||||
//settings defaults
|
||||
$this->settings_defaults = array(
|
||||
'restricted_access_post_metabox' => array( 'post' => 1, 'page' => 1 ),
|
||||
@@ -577,6 +585,7 @@ if ( ! class_exists( 'um\Config' ) ) {
|
||||
'activation_link_expiry_time' => '',
|
||||
'lock_register_forms' => false,
|
||||
'display_login_form_notice' => false,
|
||||
'secure_ban_admins_accounts' => false,
|
||||
'banned_capabilities' => array( 'manage_options', 'promote_users', 'level_10' ),
|
||||
'secure_notify_admins_banned_accounts' => false,
|
||||
'secure_notify_admins_banned_accounts__interval' => 'instant',
|
||||
|
||||
+36
-27
@@ -527,7 +527,7 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
}
|
||||
|
||||
//run setup
|
||||
$this->common()->create_post_types();
|
||||
$this->common()->cpt()->create_post_types();
|
||||
$this->setup()->run_setup();
|
||||
}
|
||||
|
||||
@@ -549,10 +549,11 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
*/
|
||||
public function includes() {
|
||||
|
||||
$this->common();
|
||||
$this->common()->includes();
|
||||
$this->access();
|
||||
|
||||
if ( $this->is_request( 'ajax' ) ) {
|
||||
$this->ajax()->includes();
|
||||
$this->admin();
|
||||
$this->ajax_init();
|
||||
$this->admin_ajax_hooks();
|
||||
@@ -565,6 +566,7 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
$this->plugin_updater();
|
||||
$this->theme_updater();
|
||||
} elseif ( $this->is_request( 'admin' ) ) {
|
||||
$this->admin()->includes();
|
||||
$this->admin();
|
||||
$this->admin_menu();
|
||||
$this->admin_upgrade();
|
||||
@@ -572,8 +574,6 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
$this->columns();
|
||||
$this->admin_enqueue();
|
||||
$this->metabox();
|
||||
$this->admin()->notices();
|
||||
$this->admin()->secure();
|
||||
$this->users();
|
||||
$this->dragdrop();
|
||||
$this->admin_gdpr();
|
||||
@@ -581,6 +581,7 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
$this->plugin_updater();
|
||||
$this->theme_updater();
|
||||
} elseif ( $this->is_request( 'frontend' ) ) {
|
||||
$this->frontend()->includes();
|
||||
$this->enqueue();
|
||||
$this->account();
|
||||
$this->password();
|
||||
@@ -651,21 +652,6 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
return $this->classes['blocks'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.6.7
|
||||
*
|
||||
* @return um\core\Secure()
|
||||
*/
|
||||
public function secure() {
|
||||
if ( empty( $this->classes['secure'] ) ) {
|
||||
$this->classes['secure'] = new um\core\Secure();
|
||||
}
|
||||
|
||||
return $this->classes['secure'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get extension API
|
||||
*
|
||||
@@ -704,19 +690,43 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
return $this->classes[ $key ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @return um\ajax\Init
|
||||
*/
|
||||
public function ajax() {
|
||||
if ( empty( $this->classes['um\ajax\init'] ) ) {
|
||||
$this->classes['um\ajax\init'] = new um\ajax\Init();
|
||||
}
|
||||
|
||||
return $this->classes['um\ajax\init'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
* @since 2.6.8 changed namespace and class content.
|
||||
*
|
||||
* @return um\core\Common()
|
||||
* @return um\common\Init
|
||||
*/
|
||||
function common() {
|
||||
if ( empty( $this->classes['common'] ) ) {
|
||||
$this->classes['common'] = new um\core\Common();
|
||||
public function common() {
|
||||
if ( empty( $this->classes['um\common\init'] ) ) {
|
||||
$this->classes['um\common\init'] = new um\common\Init();
|
||||
}
|
||||
return $this->classes['common'];
|
||||
return $this->classes['um\common\init'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @return um\frontend\Init
|
||||
*/
|
||||
public function frontend() {
|
||||
if ( empty( $this->classes['um\frontend\init'] ) ) {
|
||||
$this->classes['um\frontend\init'] = new um\frontend\Init();
|
||||
}
|
||||
return $this->classes['um\frontend\init'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
@@ -776,7 +786,6 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
new um\core\AJAX_Common();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.0.30
|
||||
*/
|
||||
@@ -791,9 +800,9 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
/**
|
||||
* @since 2.0
|
||||
*
|
||||
* @return um\admin\Admin()
|
||||
* @return um\admin\Admin
|
||||
*/
|
||||
function admin() {
|
||||
public function admin() {
|
||||
if ( empty( $this->classes['admin'] ) ) {
|
||||
$this->classes['admin'] = new um\admin\Admin();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
namespace um\common;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'um\common\CPT' ) ) {
|
||||
|
||||
/**
|
||||
* Class CPT
|
||||
*
|
||||
* @package um\common
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
class CPT {
|
||||
|
||||
public function hooks() {
|
||||
add_action( 'init', array( &$this, 'create_post_types' ), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create taxonomies for use for UM
|
||||
*/
|
||||
public function create_post_types() {
|
||||
register_post_type(
|
||||
'um_form',
|
||||
array(
|
||||
'labels' => array(
|
||||
'name' => __( 'Forms', 'ultimate-member' ),
|
||||
'singular_name' => __( 'Form', 'ultimate-member' ),
|
||||
'add_new' => __( 'Add New', 'ultimate-member' ),
|
||||
'add_new_item' => __( 'Add New Form', 'ultimate-member' ),
|
||||
'edit_item' => __( 'Edit Form', 'ultimate-member' ),
|
||||
'not_found' => __( 'You did not create any forms yet', 'ultimate-member' ),
|
||||
'not_found_in_trash' => __( 'Nothing found in Trash', 'ultimate-member' ),
|
||||
'search_items' => __( 'Search Forms', 'ultimate-member' ),
|
||||
),
|
||||
'capabilities' => array(
|
||||
'edit_post' => 'manage_options',
|
||||
'read_post' => 'manage_options',
|
||||
'delete_post' => 'manage_options',
|
||||
'edit_posts' => 'manage_options',
|
||||
'edit_others_posts' => 'manage_options',
|
||||
'delete_posts' => 'manage_options',
|
||||
'publish_posts' => 'manage_options',
|
||||
'read_private_posts' => 'manage_options',
|
||||
),
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false,
|
||||
'public' => false,
|
||||
'show_in_rest' => true,
|
||||
'supports' => array( 'title' ),
|
||||
)
|
||||
);
|
||||
|
||||
if ( UM()->options()->get( 'members_page' ) ) {
|
||||
register_post_type(
|
||||
'um_directory',
|
||||
array(
|
||||
'labels' => array(
|
||||
'name' => __( 'Member Directories', 'ultimate-member' ),
|
||||
'singular_name' => __( 'Member Directory', 'ultimate-member' ),
|
||||
'add_new' => __( 'Add New', 'ultimate-member' ),
|
||||
'add_new_item' => __( 'Add New Member Directory', 'ultimate-member' ),
|
||||
'edit_item' => __( 'Edit Member Directory', 'ultimate-member' ),
|
||||
'not_found' => __( 'You did not create any member directories yet', 'ultimate-member' ),
|
||||
'not_found_in_trash' => __( 'Nothing found in Trash', 'ultimate-member' ),
|
||||
'search_items' => __( 'Search Member Directories', 'ultimate-member' ),
|
||||
),
|
||||
'capabilities' => array(
|
||||
'edit_post' => 'manage_options',
|
||||
'read_post' => 'manage_options',
|
||||
'delete_post' => 'manage_options',
|
||||
'edit_posts' => 'manage_options',
|
||||
'edit_others_posts' => 'manage_options',
|
||||
'delete_posts' => 'manage_options',
|
||||
'publish_posts' => 'manage_options',
|
||||
'read_private_posts' => 'manage_options',
|
||||
),
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false,
|
||||
'public' => false,
|
||||
'show_in_rest' => true,
|
||||
'supports' => array( 'title' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace um\common;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'um\common\Init' ) ) {
|
||||
|
||||
/**
|
||||
* Class Init
|
||||
*
|
||||
* @package um\common
|
||||
*/
|
||||
class Init {
|
||||
|
||||
/**
|
||||
* Create classes' instances where __construct isn't empty for hooks init
|
||||
*
|
||||
* @used-by \UM::includes()
|
||||
*/
|
||||
public function includes() {
|
||||
$this->cpt()->hooks();
|
||||
$this->screen();
|
||||
$this->secure()->hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @return CPT
|
||||
*/
|
||||
public function cpt() {
|
||||
if ( empty( UM()->classes['um\common\cpt'] ) ) {
|
||||
UM()->classes['um\common\cpt'] = new CPT();
|
||||
}
|
||||
return UM()->classes['um\common\cpt'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @return Screen
|
||||
*/
|
||||
public function screen() {
|
||||
if ( empty( UM()->classes['um\common\screen'] ) ) {
|
||||
UM()->classes['um\common\screen'] = new Screen();
|
||||
}
|
||||
return UM()->classes['um\common\screen'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @return Secure
|
||||
*/
|
||||
public function secure() {
|
||||
if ( empty( UM()->classes['um\common\secure'] ) ) {
|
||||
UM()->classes['um\common\secure'] = new Secure();
|
||||
}
|
||||
return UM()->classes['um\common\secure'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
namespace um\common;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'um\common\Screen' ) ) {
|
||||
|
||||
/**
|
||||
* Class Screen
|
||||
*
|
||||
* @package um\common
|
||||
*/
|
||||
class Screen {
|
||||
|
||||
/**
|
||||
* Screen constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_filter( 'body_class', array( &$this, 'remove_admin_bar' ), 1000, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove admin bar classes
|
||||
*
|
||||
* @param array $classes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function remove_admin_bar( $classes ) {
|
||||
if ( is_user_logged_in() ) {
|
||||
if ( um_user( 'can_not_see_adminbar' ) ) {
|
||||
$search = array_search( 'admin-bar', $classes, true );
|
||||
if ( ! empty( $search ) ) {
|
||||
unset( $classes[ $search ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
namespace um\common;
|
||||
|
||||
use WP_User;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'um\common\Secure' ) ) {
|
||||
|
||||
/**
|
||||
* Class Secure
|
||||
*
|
||||
* @package um\common
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
class Secure {
|
||||
|
||||
public function hooks() {
|
||||
add_action( 'wp', array( $this, 'schedule_events' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add callbacks to Schedule Events.
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function schedule_events() {
|
||||
if ( ! UM()->options()->get( 'secure_ban_admins_accounts' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( UM()->options()->get( 'secure_notify_admins_banned_accounts' ) ) {
|
||||
$notification_interval = UM()->options()->get( 'secure_notify_admins_banned_accounts__interval' );
|
||||
if ( 'instant' === $notification_interval ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'hourly' === $notification_interval ) {
|
||||
add_action( 'um_hourly_scheduled_events', array( $this, 'notify_administrators_hourly' ) );
|
||||
} elseif ( 'daily' === $notification_interval ) {
|
||||
add_action( 'um_daily_scheduled_events', array( $this, 'notify_administrators_daily' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify Administrators hourly - Suspicious activities in an hour
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function notify_administrators_hourly() {
|
||||
$user_ids = get_users(
|
||||
array(
|
||||
'fields' => 'ids',
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'um_user_blocked__timestamp',
|
||||
'value' => gmdate( 'Y-m-d H:i:s', strtotime( '-1 hour' ) ),
|
||||
'compare' => '>=',
|
||||
'type' => 'DATETIME',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$this->send_notification( $user_ids );
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify Administrators daily - Today's suspicious activity
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function notify_administrators_daily() {
|
||||
$user_ids = get_users(
|
||||
array(
|
||||
'fields' => 'ids',
|
||||
'relation' => 'AND',
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'um_user_blocked__timestamp',
|
||||
'value' => gmdate( 'Y-m-d H:i:s', strtotime( '-1 day' ) ),
|
||||
'compare' => '>=',
|
||||
'type' => 'DATE',
|
||||
),
|
||||
array(
|
||||
'key' => 'um_user_blocked__timestamp',
|
||||
'value' => gmdate( 'Y-m-d H:i:s', strtotime( 'now' ) ),
|
||||
'compare' => '<=',
|
||||
'type' => 'DATE',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$this->send_notification( $user_ids );
|
||||
}
|
||||
|
||||
public function send_notification( $user_ids ) {
|
||||
$banned_profile_links = '';
|
||||
foreach ( $user_ids as $uid ) {
|
||||
um_fetch_user( $uid );
|
||||
$banned_profile_links .= UM()->user()->get_profile_link( $uid ) . ' ' . um_user( 'account_status' ) . '<br />';
|
||||
}
|
||||
um_reset_user();
|
||||
|
||||
$emails = um_multi_admin_email();
|
||||
if ( ! empty( $emails ) ) {
|
||||
foreach ( $emails as $email ) {
|
||||
UM()->mail()->send(
|
||||
$email,
|
||||
'suspicious-activity',
|
||||
array(
|
||||
'admin' => true,
|
||||
'tags' => array(
|
||||
'banned_profile_links',
|
||||
),
|
||||
'tags_replace' => array(
|
||||
$banned_profile_links,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the banned capabilities list.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_banned_capabilities_list() {
|
||||
/**
|
||||
* Filters the banned capabilities for UM Register forms.
|
||||
*
|
||||
* @param {array} $capabilities WordPress Administrative Capabilities.
|
||||
*
|
||||
* @return {array} Banned admin capabilities.
|
||||
*
|
||||
* @since 2.6.8
|
||||
* @hook um_secure_register_form_banned_capabilities
|
||||
*
|
||||
* @example <caption>Added `read` capability as banned.</caption>
|
||||
* function my_banned_capabilities( $capabilities ) {
|
||||
* $capabilities[] = 'read';
|
||||
* return $capabilities;
|
||||
* }
|
||||
* add_filter( 'um_secure_register_form_banned_capabilities', 'my_banned_capabilities' );
|
||||
*/
|
||||
$banned_admin_capabilities = apply_filters(
|
||||
'um_secure_register_form_banned_capabilities',
|
||||
array(
|
||||
'create_sites',
|
||||
'delete_sites',
|
||||
'manage_network',
|
||||
'manage_sites',
|
||||
'manage_network_users',
|
||||
'manage_network_plugins',
|
||||
'manage_network_themes',
|
||||
'manage_network_options',
|
||||
'upgrade_network',
|
||||
'setup_network',
|
||||
'activate_plugins',
|
||||
'edit_dashboard',
|
||||
'edit_theme_options',
|
||||
'export',
|
||||
'import',
|
||||
'list_users',
|
||||
'remove_users',
|
||||
'switch_themes',
|
||||
'customize',
|
||||
'delete_site',
|
||||
'update_core',
|
||||
'update_plugins',
|
||||
'update_themes',
|
||||
'install_plugins',
|
||||
'install_themes',
|
||||
'delete_themes',
|
||||
'delete_plugins',
|
||||
'edit_plugins',
|
||||
'edit_themes',
|
||||
'edit_files',
|
||||
'edit_users',
|
||||
'add_users',
|
||||
'create_users',
|
||||
'delete_users',
|
||||
'level_10',
|
||||
'manage_options',
|
||||
'promote_users',
|
||||
)
|
||||
);
|
||||
return $banned_admin_capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke Caps & Mark rejected as suspicious
|
||||
*
|
||||
* @param WP_User $user
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function revoke_caps( $user ) {
|
||||
$user_agent = '';
|
||||
if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
|
||||
$user_agent = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) );
|
||||
}
|
||||
// Capture details.
|
||||
$captured = array(
|
||||
'capabilities' => $user->allcaps,
|
||||
'submitted' => ! empty( UM()->form()->post_form ) ? UM()->form()->post_form : '',
|
||||
'roles' => $user->roles,
|
||||
'user_agent' => $user_agent,
|
||||
'account_status' => get_user_meta( $user->ID, 'account_status', true ),
|
||||
);
|
||||
update_user_meta( $user->ID, 'um_user_blocked__metadata', $captured );
|
||||
|
||||
$user->remove_all_caps();
|
||||
$user->update_user_level_from_caps();
|
||||
um_fetch_user( $user->ID );
|
||||
if ( is_user_logged_in() ) {
|
||||
UM()->user()->set_status( 'inactive' );
|
||||
} else {
|
||||
UM()->user()->set_status( 'rejected' );
|
||||
}
|
||||
um_reset_user();
|
||||
update_user_meta( $user->ID, 'um_user_blocked', 'suspicious_activity' );
|
||||
update_user_meta( $user->ID, 'um_user_blocked__timestamp', current_time( 'mysql' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
<?php
|
||||
namespace um\core;
|
||||
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
|
||||
if ( ! class_exists( 'um\core\Common' ) ) {
|
||||
|
||||
|
||||
/**
|
||||
* Class Common
|
||||
*
|
||||
* @package um\core
|
||||
*/
|
||||
class Common {
|
||||
|
||||
|
||||
/**
|
||||
* Common constructor.
|
||||
*/
|
||||
function __construct() {
|
||||
add_action( 'init', array( &$this, 'create_post_types' ), 1 );
|
||||
|
||||
add_filter( 'body_class', array( &$this, 'remove_admin_bar' ), 1000, 1 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove admin bar classes
|
||||
*
|
||||
* @param array $classes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function remove_admin_bar( $classes ) {
|
||||
|
||||
if ( is_user_logged_in() ) {
|
||||
if ( um_user( 'can_not_see_adminbar' ) ) {
|
||||
$search = array_search( 'admin-bar', $classes );
|
||||
if ( ! empty( $search ) ) {
|
||||
unset( $classes[ $search ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create taxonomies for use for UM
|
||||
*/
|
||||
function create_post_types() {
|
||||
|
||||
register_post_type( 'um_form', array(
|
||||
'labels' => array(
|
||||
'name' => __( 'Forms', 'ultimate-member' ),
|
||||
'singular_name' => __( 'Form', 'ultimate-member' ),
|
||||
'add_new' => __( 'Add New', 'ultimate-member' ),
|
||||
'add_new_item' => __( 'Add New Form', 'ultimate-member' ),
|
||||
'edit_item' => __( 'Edit Form', 'ultimate-member' ),
|
||||
'not_found' => __( 'You did not create any forms yet', 'ultimate-member' ),
|
||||
'not_found_in_trash' => __( 'Nothing found in Trash', 'ultimate-member' ),
|
||||
'search_items' => __( 'Search Forms', 'ultimate-member' ),
|
||||
),
|
||||
'capabilities' => array(
|
||||
'edit_post' => 'manage_options',
|
||||
'read_post' => 'manage_options',
|
||||
'delete_post' => 'manage_options',
|
||||
'edit_posts' => 'manage_options',
|
||||
'edit_others_posts' => 'manage_options',
|
||||
'delete_posts' => 'manage_options',
|
||||
'publish_posts' => 'manage_options',
|
||||
'read_private_posts' => 'manage_options',
|
||||
),
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false,
|
||||
'public' => false,
|
||||
'show_in_rest' => true,
|
||||
'supports' => array( 'title' ),
|
||||
) );
|
||||
|
||||
if ( UM()->options()->get( 'members_page' ) || ! get_option( 'um_options' ) ) {
|
||||
|
||||
register_post_type( 'um_directory', array(
|
||||
'labels' => array(
|
||||
'name' => __( 'Member Directories', 'ultimate-member' ),
|
||||
'singular_name' => __( 'Member Directory', 'ultimate-member' ),
|
||||
'add_new' => __( 'Add New', 'ultimate-member' ),
|
||||
'add_new_item' => __( 'Add New Member Directory', 'ultimate-member' ),
|
||||
'edit_item' => __( 'Edit Member Directory', 'ultimate-member' ),
|
||||
'not_found' => __( 'You did not create any member directories yet', 'ultimate-member' ),
|
||||
'not_found_in_trash' => __( 'Nothing found in Trash', 'ultimate-member' ),
|
||||
'search_items' => __( 'Search Member Directories', 'ultimate-member' ),
|
||||
),
|
||||
'capabilities' => array(
|
||||
'edit_post' => 'manage_options',
|
||||
'read_post' => 'manage_options',
|
||||
'delete_post' => 'manage_options',
|
||||
'edit_posts' => 'manage_options',
|
||||
'edit_others_posts' => 'manage_options',
|
||||
'delete_posts' => 'manage_options',
|
||||
'publish_posts' => 'manage_options',
|
||||
'read_private_posts' => 'manage_options',
|
||||
),
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false,
|
||||
'public' => false,
|
||||
'show_in_rest' => true,
|
||||
'supports' => array( 'title' ),
|
||||
) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace um\frontend;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'um\frontend\Init' ) ) {
|
||||
|
||||
/**
|
||||
* Class Init
|
||||
*
|
||||
* @package um\frontend
|
||||
*/
|
||||
class Init {
|
||||
|
||||
/**
|
||||
* Create classes' instances where __construct isn't empty for hooks init
|
||||
*
|
||||
* @used-by \UM::includes()
|
||||
*/
|
||||
public function includes() {
|
||||
$this->secure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @return Secure
|
||||
*/
|
||||
public function secure() {
|
||||
if ( empty( UM()->classes['um\frontend\secure'] ) ) {
|
||||
UM()->classes['um\frontend\secure'] = new Secure();
|
||||
}
|
||||
return UM()->classes['um\frontend\secure'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,26 @@
|
||||
<?php
|
||||
namespace um\core;
|
||||
namespace um\frontend;
|
||||
|
||||
use WP_Error;
|
||||
use WP_User;
|
||||
use WP_User_Query;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
if ( ! class_exists( 'um\frontend\Secure' ) ) {
|
||||
|
||||
/**
|
||||
* Class Secure
|
||||
*
|
||||
* @package um\core
|
||||
* @package um\frontend
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
class Secure {
|
||||
|
||||
/**
|
||||
* Login constructor.
|
||||
* Secure constructor.
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function __construct() {
|
||||
@@ -36,11 +35,6 @@ if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
add_action( 'um_user_login', array( $this, 'login_validate_expired_pass' ), 1 );
|
||||
|
||||
add_action( 'validate_password_reset', array( $this, 'avoid_old_password' ), 1, 2 );
|
||||
|
||||
/**
|
||||
* WP Schedule Events for Notification
|
||||
*/
|
||||
add_action( 'wp', array( $this, 'schedule_events' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,6 +43,10 @@ if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function init() {
|
||||
if ( ! UM()->options()->get( 'secure_ban_admins_accounts' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the integrity of Current User's Capabilities
|
||||
*/
|
||||
@@ -79,7 +77,7 @@ if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
echo "<p class='um-notice warning'>";
|
||||
echo wp_kses(
|
||||
sprintf(
|
||||
// translators: One-time change requires you to reset your password
|
||||
// translators: One-time change requires you to reset your password
|
||||
__( '<strong>Important:</strong> Your password has expired. This (one-time) change requires you to reset your password. Please <a href="%s">click here</a> to reset your password via Email.', 'ultimate-member' ),
|
||||
um_get_core_page( 'password-reset' )
|
||||
),
|
||||
@@ -125,10 +123,9 @@ if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
/**
|
||||
* Block all UM Register form submissions.
|
||||
*
|
||||
* @param array $args Form settings.
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function block_register_forms( $args ) {
|
||||
public function block_register_forms() {
|
||||
if ( UM()->options()->get( 'lock_register_forms' ) ) {
|
||||
$login_url = add_query_arg( 'notice', 'maintenance', um_get_core_page( 'login' ) );
|
||||
nocache_headers();
|
||||
@@ -186,6 +183,8 @@ if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
* Secure user capabilities and revoke administrative ones.
|
||||
*
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @param int $user_id
|
||||
*/
|
||||
public function secure_user_capabilities( $user_id ) {
|
||||
global $wpdb;
|
||||
@@ -229,14 +228,14 @@ if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
}
|
||||
|
||||
if ( $has_admin_cap ) {
|
||||
$this->revoke_caps( $user );
|
||||
UM()->common()->secure()->revoke_caps( $user );
|
||||
/**
|
||||
* Notify Administrators Immediately
|
||||
*/
|
||||
if ( UM()->options()->get( 'secure_notify_admins_banned_accounts' ) ) {
|
||||
$interval = UM()->options()->get( 'secure_notify_admins_banned_accounts__interval' );
|
||||
if ( 'instant' === $interval ) {
|
||||
$this->send_email( array( $user_id ) );
|
||||
UM()->common()->secure()->send_notification( array( $user_id ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,12 +258,13 @@ if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Secure user capabilities and revoke administrative ones.
|
||||
* Set meta (no need to reset his password) if the user is a new registered.
|
||||
*
|
||||
* @since 2.6.8
|
||||
*
|
||||
* @param int $user_id
|
||||
*/
|
||||
public function maybe_set_whitelisted_password( $user_id ) {
|
||||
global $wpdb;
|
||||
$user = get_userdata( $user_id );
|
||||
if ( empty( $user ) ) {
|
||||
return;
|
||||
@@ -275,187 +275,5 @@ if ( ! class_exists( 'um\core\Secure' ) ) {
|
||||
update_user_meta( $user_id, 'um_secure_has_reset_password__timestamp', current_time( 'mysql' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke Caps & Mark rejected as suspicious
|
||||
*
|
||||
* @param object $user \WP_User
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function revoke_caps( $user ) {
|
||||
$user_agent = '';
|
||||
if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
|
||||
$user_agent = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) );
|
||||
}
|
||||
// Capture details.
|
||||
$captured = array(
|
||||
'capabilities' => $user->allcaps,
|
||||
'submitted' => UM()->form()->post_form,
|
||||
'roles' => $user->roles,
|
||||
'user_agent' => $user_agent,
|
||||
'account_status' => get_user_meta( $user->ID, 'account_status', true ),
|
||||
);
|
||||
update_user_meta( $user->ID, 'um_user_blocked__metadata', $captured );
|
||||
|
||||
$user->remove_all_caps();
|
||||
if ( is_user_logged_in() ) {
|
||||
UM()->user()->set_status( 'inactive' );
|
||||
} else {
|
||||
UM()->user()->set_status( 'rejected' );
|
||||
}
|
||||
update_user_meta( $user->ID, 'um_user_blocked', 'suspicious_activity' );
|
||||
update_user_meta( $user->ID, 'um_user_blocked__datetime', current_time( 'mysql' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add callbacks to Schedule Events.
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function schedule_events() {
|
||||
if ( UM()->options()->get( 'secure_notify_admins_banned_accounts' ) ) {
|
||||
$notification_interval = UM()->options()->get( 'secure_notify_admins_banned_accounts__interval' );
|
||||
if ( 'instant' === $notification_interval ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'hourly' === $notification_interval ) {
|
||||
add_action( 'um_hourly_scheduled_events', array( $this, 'notify_administrators_hourly' ) );
|
||||
} elseif ( 'daily' === $notification_interval ) {
|
||||
add_action( 'um_daily_scheduled_events', array( $this, 'notify_administrators_daily' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify Administrators hourly - Suspicious activities in an hour
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function notify_administrators_hourly() {
|
||||
$args = array(
|
||||
'fields' => 'ID',
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'um_user_blocked__datetime',
|
||||
'value' => gmdate( 'Y-m-d H:i:s', strtotime( '-1 hour' ) ),
|
||||
'compare' => '>=',
|
||||
'type' => 'DATETIME',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$users = new WP_User_Query( $args );
|
||||
|
||||
$this->send_email( array_values( $users->get_results() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify Administrators daily - Today's suspicious activity
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function notify_administrators_daily() {
|
||||
$args = array(
|
||||
'fields' => 'ID',
|
||||
'relation' => 'AND',
|
||||
'meta_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'key' => 'um_user_blocked__datetime',
|
||||
'value' => gmdate( 'Y-m-d H:i:s', strtotime( '-1 day' ) ),
|
||||
'compare' => '>=',
|
||||
'type' => 'DATE',
|
||||
),
|
||||
array(
|
||||
'key' => 'um_user_blocked__datetime',
|
||||
'value' => gmdate( 'Y-m-d H:i:s', strtotime( 'now' ) ),
|
||||
'compare' => '<=',
|
||||
'type' => 'DATE',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$users = new WP_User_Query( $args );
|
||||
|
||||
$this->send_email( array_values( $users->get_results() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Email template
|
||||
*
|
||||
* @param bool $single Whether the template is for single or multiple user activities
|
||||
* @param array $profile_urls Profile URLs to include in the email body
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function get_email_template( $single = true, $profile_urls = array() ) {
|
||||
$action = '';
|
||||
if ( ! is_user_logged_in() ) {
|
||||
$action = 'Rejected';
|
||||
} else {
|
||||
$action = 'Deactivated';
|
||||
}
|
||||
|
||||
$body = '';
|
||||
if ( $single ) {
|
||||
$body = 'This is to inform you that there\'s a suspicious activity with the following account: ';
|
||||
$body .= '<br/>';
|
||||
$body .= '{user_profile_link}';
|
||||
$body .= '<br/><br/>';
|
||||
$body .= 'Due to that we have set the account status to ' . $action . ', Revoked Roles & Destroyed the Login Session.';
|
||||
$body .= '</br>';
|
||||
} else {
|
||||
$body = 'This is to inform you that there are suspicious activities with the following accounts: ';
|
||||
$body .= '</br>';
|
||||
$body .= '{user_profile_link}';
|
||||
$body .= '</br></br>';
|
||||
$body .= 'Due to that we have set each account\'s status to ' . $action . ', revoked roles & destroyed the login session.';
|
||||
$body .= '</br>';
|
||||
}
|
||||
|
||||
$urls = implode( '</br>', $profile_urls );
|
||||
$body = str_replace( '{user_profile_link}', $urls, $body );
|
||||
$body .= '<br/><br/>- Sent via Ultimate Member plugin. ';
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Email
|
||||
*
|
||||
* @param array $user_ids User IDs.
|
||||
*
|
||||
* @since 2.6.8
|
||||
*/
|
||||
public function send_email( $user_ids = array() ) {
|
||||
|
||||
if ( empty( $user_ids ) ) {
|
||||
return '';
|
||||
}
|
||||
$multiple_recipients = array();
|
||||
$admins = get_users( 'role=Administrator' );
|
||||
foreach ( $admins as $user ) {
|
||||
$multiple_recipients[] = $user->user_email;
|
||||
}
|
||||
|
||||
$subject = _n( 'Suspicious Account Activity on ', 'Suspicious Accounts & Activities on ', count( $user_ids ), 'ultimate-member' ) . wp_parse_url( get_site_url() )['host'];
|
||||
|
||||
if ( count( $user_ids ) <= 1 ) {
|
||||
$url = UM()->user()->get_profile_link( $user_ids[0] );
|
||||
$body = $this->get_email_template( true, array( $url ) );
|
||||
} else {
|
||||
$arr_urls = array();
|
||||
foreach ( $user_ids as $i => $uid ) {
|
||||
$arr_urls[] = UM()->user()->get_profile_link( $uid );
|
||||
}
|
||||
$body = $this->get_email_template( false, $arr_urls );
|
||||
}
|
||||
|
||||
wp_mail( $multiple_recipients, $subject, $body );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Template for the "Secure: Suspicious Account Activity".
|
||||
* Whether to receive notification when suspicious account activity is detected.
|
||||
*
|
||||
* This template can be overridden by copying it to {your-theme}/ultimate-member/email/suspicious-activity.php
|
||||
*
|
||||
* @version 2.6.8
|
||||
*/
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div style="max-width: 560px;padding: 20px;background: #ffffff;border-radius: 5px;margin:40px auto;font-family: Open Sans,Helvetica,Arial;font-size: 15px;color: #666;">
|
||||
|
||||
<div style="color: #444444;font-weight: normal;">
|
||||
<div style="text-align: center;font-weight:600;font-size:26px;padding: 10px 0;border-bottom: solid 3px #eeeeee;">{site_name}</div>
|
||||
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
|
||||
<div style="padding: 0 30px 30px 30px;border-bottom: 3px solid #eeeeee;">
|
||||
|
||||
<div style="padding: 30px 0;font-size: 14px;">This is to inform you that there are suspicious activities with the following account(s):</div>
|
||||
<div style="padding: 30px 0;font-size: 14px;">{banned_profile_links}</div>
|
||||
<div style="padding: 30px 0;font-size: 14px;">Due to that we have set each account(s) status to rejected or deactivated, revoked roles & destroyed the login session.</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="color: #999;padding: 20px 30px">
|
||||
|
||||
<div style="">- Sent via Ultimate Member plugin.</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
Reference in New Issue
Block a user