342 lines
9 KiB
PHP
342 lines
9 KiB
PHP
<?php
|
|
/**
|
|
* WP-CLI commands
|
|
*
|
|
* @package TwoFactorExtended
|
|
* @since 0.1.0
|
|
*/
|
|
|
|
// Prevent direct access.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Class Two_Factor_Extended_CLI_Commands
|
|
*
|
|
* Provides WP-CLI commands for Two Factor Extended.
|
|
*
|
|
* @since 0.1.0
|
|
*/
|
|
class Two_Factor_Extended_CLI_Commands {
|
|
|
|
/**
|
|
* Display 2FA compliance status.
|
|
*
|
|
* ## OPTIONS
|
|
*
|
|
* [--role=<role>]
|
|
* : Filter by user role.
|
|
*
|
|
* [--format=<format>]
|
|
* : Output format (table, json, csv). Default: table.
|
|
*
|
|
* ## EXAMPLES
|
|
*
|
|
* wp two-factor-extended status
|
|
* wp two-factor-extended status --role=administrator
|
|
* wp two-factor-extended status --format=json
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $args Positional arguments.
|
|
* @param array $assoc_args Associative arguments.
|
|
*/
|
|
public function status( array $args, array $assoc_args ): void {
|
|
$role = $assoc_args['role'] ?? '';
|
|
$format = $assoc_args['format'] ?? 'table';
|
|
|
|
$compliance = two_factor_extended()->get_compliance_report();
|
|
$stats = $compliance->get_compliance_stats( array( 'role' => $role ) );
|
|
|
|
if ( 'json' === $format ) {
|
|
WP_CLI::line( wp_json_encode( $stats, JSON_PRETTY_PRINT ) );
|
|
return;
|
|
}
|
|
|
|
// Display overview.
|
|
WP_CLI::line( WP_CLI::colorize( '%G2FA Compliance Status%n' ) );
|
|
WP_CLI::line( str_repeat( '=', 40 ) );
|
|
|
|
$overview = array(
|
|
array(
|
|
'Metric' => 'Total Users',
|
|
'Count' => $stats['total_users'],
|
|
'Percentage' => '100%',
|
|
),
|
|
array(
|
|
'Metric' => 'Compliant',
|
|
'Count' => $stats['compliant_users'],
|
|
'Percentage' => $this->calculate_percentage( $stats['compliant_users'], $stats['total_users'] ),
|
|
),
|
|
array(
|
|
'Metric' => 'Non-Compliant',
|
|
'Count' => $stats['non_compliant'],
|
|
'Percentage' => $this->calculate_percentage( $stats['non_compliant'], $stats['total_users'] ),
|
|
),
|
|
array(
|
|
'Metric' => 'In Grace Period',
|
|
'Count' => $stats['grace_period'],
|
|
'Percentage' => $this->calculate_percentage( $stats['grace_period'], $stats['total_users'] ),
|
|
),
|
|
array(
|
|
'Metric' => 'No Requirements',
|
|
'Count' => $stats['no_requirements'],
|
|
'Percentage' => $this->calculate_percentage( $stats['no_requirements'], $stats['total_users'] ),
|
|
),
|
|
);
|
|
|
|
WP_CLI\Utils\format_items( $format, $overview, array( 'Metric', 'Count', 'Percentage' ) );
|
|
|
|
// Display by role if available.
|
|
if ( ! empty( $stats['by_role'] ) ) {
|
|
WP_CLI::line( '' );
|
|
WP_CLI::line( WP_CLI::colorize( '%GBy Role%n' ) );
|
|
WP_CLI::line( str_repeat( '=', 40 ) );
|
|
|
|
$by_role = array();
|
|
foreach ( $stats['by_role'] as $role_key => $role_stats ) {
|
|
$role_name = Two_Factor_Extended_Role_Manager::get_role_display_name( $role_key );
|
|
|
|
$by_role[] = array(
|
|
'Role' => $role_name,
|
|
'Total' => $role_stats['total'],
|
|
'Compliant' => $role_stats['compliant'],
|
|
'Non-Compliant' => $role_stats['non_compliant'],
|
|
'Compliance %' => $this->calculate_percentage( $role_stats['compliant'], $role_stats['total'] ),
|
|
);
|
|
}
|
|
|
|
WP_CLI\Utils\format_items( $format, $by_role, array( 'Role', 'Total', 'Compliant', 'Non-Compliant', 'Compliance %' ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enforce 2FA requirements for a role.
|
|
*
|
|
* ## OPTIONS
|
|
*
|
|
* --role=<role>
|
|
* : User role to enforce.
|
|
*
|
|
* [--reset-grace]
|
|
* : Reset grace period for all users in role.
|
|
*
|
|
* ## EXAMPLES
|
|
*
|
|
* wp two-factor-extended enforce --role=administrator
|
|
* wp two-factor-extended enforce --role=editor --reset-grace
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $args Positional arguments.
|
|
* @param array $assoc_args Associative arguments.
|
|
*/
|
|
public function enforce( array $args, array $assoc_args ): void {
|
|
if ( empty( $assoc_args['role'] ) ) {
|
|
WP_CLI::error( 'Please specify a role with --role=<role>' );
|
|
return;
|
|
}
|
|
|
|
$role = $assoc_args['role'];
|
|
$reset_grace = isset( $assoc_args['reset-grace'] );
|
|
|
|
// Get users with this role.
|
|
$users = get_users( array( 'role' => $role ) );
|
|
|
|
if ( empty( $users ) ) {
|
|
WP_CLI::warning( sprintf( 'No users found with role: %s', $role ) );
|
|
return;
|
|
}
|
|
|
|
$enforcement = two_factor_extended()->get_enforcement();
|
|
$processed = 0;
|
|
|
|
$progress = WP_CLI\Utils\make_progress_bar( 'Enforcing 2FA requirements', count( $users ) );
|
|
|
|
foreach ( $users as $user ) {
|
|
$required = $enforcement->get_required_providers_for_user( $user->ID );
|
|
|
|
if ( empty( $required ) ) {
|
|
$progress->tick();
|
|
continue;
|
|
}
|
|
|
|
// Set or reset enforcement start date.
|
|
update_user_meta( $user->ID, Two_Factor_Extended_Enforcement::META_ENFORCEMENT_START, time() );
|
|
|
|
if ( $reset_grace ) {
|
|
delete_user_meta( $user->ID, Two_Factor_Extended_Enforcement::META_GRACE_NOTIFIED );
|
|
}
|
|
|
|
// Log the action.
|
|
two_factor_extended()->get_audit_log()->log_event(
|
|
'cli_enforce',
|
|
sprintf( 'WP-CLI: Enforced 2FA for user %s', $user->user_login ),
|
|
$user->ID,
|
|
array(
|
|
'role' => $role,
|
|
'required_providers' => $required,
|
|
)
|
|
);
|
|
|
|
$processed++;
|
|
$progress->tick();
|
|
}
|
|
|
|
$progress->finish();
|
|
|
|
WP_CLI::success(
|
|
sprintf(
|
|
'Enforced 2FA requirements for %d users with role: %s',
|
|
$processed,
|
|
$role
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Generate compliance report.
|
|
*
|
|
* ## OPTIONS
|
|
*
|
|
* [--role=<role>]
|
|
* : Filter by user role.
|
|
*
|
|
* [--format=<format>]
|
|
* : Output format (table, json, csv). Default: table.
|
|
*
|
|
* [--non-compliant-only]
|
|
* : Show only non-compliant users.
|
|
*
|
|
* ## EXAMPLES
|
|
*
|
|
* wp two-factor-extended report
|
|
* wp two-factor-extended report --role=administrator
|
|
* wp two-factor-extended report --non-compliant-only --format=csv
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $args Positional arguments.
|
|
* @param array $assoc_args Associative arguments.
|
|
*/
|
|
public function report( array $args, array $assoc_args ): void {
|
|
$role = $assoc_args['role'] ?? '';
|
|
$format = $assoc_args['format'] ?? 'table';
|
|
$non_compliant_only = isset( $assoc_args['non-compliant-only'] );
|
|
|
|
$compliance = two_factor_extended()->get_compliance_report();
|
|
|
|
if ( $non_compliant_only ) {
|
|
$users = $compliance->get_non_compliant_users( array( 'role' => $role ) );
|
|
|
|
if ( empty( $users ) ) {
|
|
WP_CLI::success( 'All users are compliant!' );
|
|
return;
|
|
}
|
|
|
|
$items = array();
|
|
foreach ( $users as $user_data ) {
|
|
$items[] = array(
|
|
'User ID' => $user_data['user_id'],
|
|
'Username' => $user_data['user_login'],
|
|
'Email' => $user_data['user_email'],
|
|
'Roles' => implode( ', ', $user_data['roles'] ),
|
|
'Missing Providers' => implode( ', ', $user_data['missing_providers'] ),
|
|
'Grace Period' => $user_data['in_grace_period'] ? 'Yes' : 'No',
|
|
'Days Remaining' => $user_data['grace_remaining'],
|
|
);
|
|
}
|
|
|
|
WP_CLI\Utils\format_items(
|
|
$format,
|
|
$items,
|
|
array( 'User ID', 'Username', 'Email', 'Roles', 'Missing Providers', 'Grace Period', 'Days Remaining' )
|
|
);
|
|
} else {
|
|
// Show full statistics.
|
|
$this->status( $args, $assoc_args );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reset 2FA grace period for a user.
|
|
*
|
|
* ## OPTIONS
|
|
*
|
|
* --user=<user>
|
|
* : User ID, login, or email.
|
|
*
|
|
* ## EXAMPLES
|
|
*
|
|
* wp two-factor-extended reset --user=admin
|
|
* wp two-factor-extended reset --user=123
|
|
* wp two-factor-extended reset --user=admin@example.com
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param array $args Positional arguments.
|
|
* @param array $assoc_args Associative arguments.
|
|
*/
|
|
public function reset( array $args, array $assoc_args ): void {
|
|
if ( empty( $assoc_args['user'] ) ) {
|
|
WP_CLI::error( 'Please specify a user with --user=<user>' );
|
|
return;
|
|
}
|
|
|
|
// Get user by ID, login, or email.
|
|
$user_identifier = $assoc_args['user'];
|
|
|
|
if ( is_numeric( $user_identifier ) ) {
|
|
$user = get_userdata( $user_identifier );
|
|
} elseif ( is_email( $user_identifier ) ) {
|
|
$user = get_user_by( 'email', $user_identifier );
|
|
} else {
|
|
$user = get_user_by( 'login', $user_identifier );
|
|
}
|
|
|
|
if ( ! $user ) {
|
|
WP_CLI::error( sprintf( 'User not found: %s', $user_identifier ) );
|
|
return;
|
|
}
|
|
|
|
// Reset enforcement start date.
|
|
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(
|
|
'cli_reset_grace',
|
|
sprintf( 'WP-CLI: Reset grace period for user %s', $user->user_login ),
|
|
$user->ID
|
|
);
|
|
|
|
WP_CLI::success(
|
|
sprintf(
|
|
'Grace period reset for user: %s (ID: %d)',
|
|
$user->user_login,
|
|
$user->ID
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Calculate percentage.
|
|
*
|
|
* @since 0.1.0
|
|
*
|
|
* @param int $part Part value.
|
|
* @param int $total Total value.
|
|
*
|
|
* @return string Percentage string.
|
|
*/
|
|
private function calculate_percentage( int $part, int $total ): string {
|
|
if ( 0 === $total ) {
|
|
return '0%';
|
|
}
|
|
|
|
return sprintf( '%.1f%%', ( $part / $total ) * 100 );
|
|
}
|
|
}
|