268 lines
6.3 KiB
PHP
268 lines
6.3 KiB
PHP
<?php
|
|
/**
|
|
* Bulk actions handler
|
|
*
|
|
* @package TwoFactorExtended
|
|
* @since 0.1.0
|
|
*/
|
|
|
|
// Prevent direct access.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Class Two_Factor_Extended_Bulk_Actions
|
|
*
|
|
* Handles bulk actions for users.
|
|
*
|
|
* @since 0.1.0
|
|
*/
|
|
class Two_Factor_Extended_Bulk_Actions {
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @since 0.1.0
|
|
*/
|
|
public function __construct() {
|
|
$this->init_hooks();
|
|
}
|
|
|
|
/**
|
|
* Initialize WordPress hooks.
|
|
*
|
|
* @since 0.1.0
|
|
*/
|
|
private function init_hooks(): void {
|
|
// Add bulk actions to users list.
|
|
add_filter( 'bulk_actions-users', array( $this, 'register_bulk_actions' ) );
|
|
|
|
// Handle bulk actions.
|
|
add_filter( 'handle_bulk_actions-users', array( $this, 'handle_bulk_actions' ), 10, 3 );
|
|
|
|
// Display admin notices after bulk actions.
|
|
add_action( 'admin_notices', array( $this, 'display_bulk_action_notices' ) );
|
|
}
|
|
|
|
/**
|
|
* Register bulk actions.
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $actions Existing bulk actions.
|
|
*
|
|
* @return array Modified bulk actions.
|
|
*/
|
|
public function register_bulk_actions( array $actions ): array {
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
return $actions;
|
|
}
|
|
|
|
$actions['two_factor_extended_require'] = __( 'Require 2FA Setup', 'two-factor-extended' );
|
|
$actions['two_factor_extended_reset'] = __( 'Reset 2FA Grace Period', 'two-factor-extended' );
|
|
|
|
return $actions;
|
|
}
|
|
|
|
/**
|
|
* Handle bulk actions.
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param string $redirect_to Redirect URL.
|
|
* @param string $action Action name.
|
|
* @param array $user_ids User IDs.
|
|
*
|
|
* @return string Modified redirect URL.
|
|
*/
|
|
public function handle_bulk_actions( string $redirect_to, string $action, array $user_ids ): string {
|
|
// Check capability.
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
return $redirect_to;
|
|
}
|
|
|
|
// Handle our bulk actions.
|
|
if ( 'two_factor_extended_require' === $action ) {
|
|
$processed = $this->bulk_require_2fa( $user_ids );
|
|
|
|
$redirect_to = add_query_arg(
|
|
array(
|
|
'two_factor_extended_bulk_require' => $processed,
|
|
),
|
|
$redirect_to
|
|
);
|
|
} elseif ( 'two_factor_extended_reset' === $action ) {
|
|
$processed = $this->bulk_reset_grace_period( $user_ids );
|
|
|
|
$redirect_to = add_query_arg(
|
|
array(
|
|
'two_factor_extended_bulk_reset' => $processed,
|
|
),
|
|
$redirect_to
|
|
);
|
|
}
|
|
|
|
return $redirect_to;
|
|
}
|
|
|
|
/**
|
|
* Bulk require 2FA for users.
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $user_ids User IDs.
|
|
*
|
|
* @return int Number of users processed.
|
|
*/
|
|
private function bulk_require_2fa( array $user_ids ): int {
|
|
$processed = 0;
|
|
$enforcement = two_factor_extended()->get_enforcement();
|
|
|
|
foreach ( $user_ids as $user_id ) {
|
|
// Skip if user doesn't exist.
|
|
$user = get_userdata( $user_id );
|
|
if ( ! $user ) {
|
|
continue;
|
|
}
|
|
|
|
// Get required providers for user.
|
|
$required = $enforcement->get_required_providers_for_user( $user_id );
|
|
|
|
// Skip if no requirements.
|
|
if ( empty( $required ) ) {
|
|
continue;
|
|
}
|
|
|
|
// Set enforcement start date to now (starts grace period).
|
|
update_user_meta( $user_id, Two_Factor_Extended_Enforcement::META_ENFORCEMENT_START, time() );
|
|
|
|
// Log the action.
|
|
two_factor_extended()->get_audit_log()->log_event(
|
|
'bulk_require_2fa',
|
|
sprintf(
|
|
'Bulk action: Require 2FA for user %s',
|
|
$user->user_login
|
|
),
|
|
$user_id,
|
|
array(
|
|
'required_providers' => $required,
|
|
)
|
|
);
|
|
|
|
$processed++;
|
|
}
|
|
|
|
return $processed;
|
|
}
|
|
|
|
/**
|
|
* Bulk reset grace period for users.
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $user_ids User IDs.
|
|
*
|
|
* @return int Number of users processed.
|
|
*/
|
|
private function bulk_reset_grace_period( array $user_ids ): int {
|
|
$processed = 0;
|
|
|
|
foreach ( $user_ids as $user_id ) {
|
|
// Skip if user doesn't exist.
|
|
$user = get_userdata( $user_id );
|
|
if ( ! $user ) {
|
|
continue;
|
|
}
|
|
|
|
// Reset enforcement start date (restarts grace period).
|
|
update_user_meta( $user_id, Two_Factor_Extended_Enforcement::META_ENFORCEMENT_START, time() );
|
|
|
|
// Clear grace period notified flag.
|
|
delete_user_meta( $user_id, Two_Factor_Extended_Enforcement::META_GRACE_NOTIFIED );
|
|
|
|
// Log the action.
|
|
two_factor_extended()->get_audit_log()->log_event(
|
|
'bulk_reset_grace',
|
|
sprintf(
|
|
'Bulk action: Reset grace period for user %s',
|
|
$user->user_login
|
|
),
|
|
$user_id
|
|
);
|
|
|
|
$processed++;
|
|
}
|
|
|
|
return $processed;
|
|
}
|
|
|
|
/**
|
|
* Display admin notices after bulk actions.
|
|
*
|
|
* This method displays success messages after bulk actions are completed.
|
|
* No nonce verification is needed here because:
|
|
* 1. This is a read-only operation (displaying a message)
|
|
* 2. The actual bulk action was already verified in handle_bulk_actions()
|
|
* 3. The GET parameters are the result of a POST-redirect-GET pattern
|
|
* 4. Only the count is used, which is safely cast to int
|
|
* 5. User capability is verified before displaying
|
|
*
|
|
* @since 0.1.0
|
|
*/
|
|
public function display_bulk_action_notices(): void {
|
|
// Check if on users page.
|
|
$screen = get_current_screen();
|
|
if ( ! $screen || 'users' !== $screen->id ) {
|
|
return;
|
|
}
|
|
|
|
// Verify user has capability to see these notices.
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
return;
|
|
}
|
|
|
|
// Bulk require 2FA notice.
|
|
// Use filter_input() for safe GET parameter access.
|
|
$bulk_require_count = filter_input( INPUT_GET, 'two_factor_extended_bulk_require', FILTER_VALIDATE_INT );
|
|
|
|
if ( $bulk_require_count && $bulk_require_count > 0 ) {
|
|
printf(
|
|
'<div class="notice notice-success is-dismissible"><p>%s</p></div>',
|
|
esc_html(
|
|
sprintf(
|
|
/* translators: %d: Number of users */
|
|
_n(
|
|
'2FA requirement set for %d user.',
|
|
'2FA requirement set for %d users.',
|
|
$bulk_require_count,
|
|
'two-factor-extended'
|
|
),
|
|
$bulk_require_count
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
// Bulk reset grace period notice.
|
|
$bulk_reset_count = filter_input( INPUT_GET, 'two_factor_extended_bulk_reset', FILTER_VALIDATE_INT );
|
|
|
|
if ( $bulk_reset_count && $bulk_reset_count > 0 ) {
|
|
printf(
|
|
'<div class="notice notice-success is-dismissible"><p>%s</p></div>',
|
|
esc_html(
|
|
sprintf(
|
|
/* translators: %d: Number of users */
|
|
_n(
|
|
'Grace period reset for %d user.',
|
|
'Grace period reset for %d users.',
|
|
$bulk_reset_count,
|
|
'two-factor-extended'
|
|
),
|
|
$bulk_reset_count
|
|
)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|