This commit is contained in:
Javier Casares 2026-03-28 09:59:03 +00:00
commit b8e17df2db
17 changed files with 1145 additions and 732 deletions

View file

@ -63,7 +63,7 @@ class Two_Factor_Extended_Enforcement {
*
* @param WP_User|WP_Error|null $user User object or error.
*
* @return WP_User|WP_Error User object or error if requirements not met.
* @return WP_User|WP_Error|null User object or error if requirements not met.
*/
public function check_user_requirements( $user ) {
// Skip if not a user object.
@ -111,7 +111,7 @@ class Two_Factor_Extended_Enforcement {
*
* @param int $user_id User ID.
*
* @return array Array of required provider class names.
* @return array<int, string> Array of required provider class names.
*/
public function get_required_providers_for_user( int $user_id ): array {
$required = array();
@ -119,15 +119,25 @@ class Two_Factor_Extended_Enforcement {
// Check if user is super admin (Multisite).
if ( is_multisite() && Two_Factor_Extended_Role_Manager::is_super_admin( $user_id ) ) {
$network_settings = get_site_option( TWO_FACTOR_EXTENDED_NETWORK_OPTION_SETTINGS, array() );
if ( ! is_array( $network_settings ) ) {
$network_settings = array();
}
if ( isset( $network_settings['super_admin_requirements'] ) && is_array( $network_settings['super_admin_requirements'] ) ) {
$required = array_merge( $required, $network_settings['super_admin_requirements'] );
foreach ( $network_settings['super_admin_requirements'] as $provider ) {
if ( is_string( $provider ) ) {
$required[] = $provider;
}
}
}
}
// Check network-wide settings (Multisite).
if ( is_multisite() ) {
$network_settings = get_site_option( TWO_FACTOR_EXTENDED_NETWORK_OPTION_SETTINGS, array() );
if ( ! is_array( $network_settings ) ) {
$network_settings = array();
}
if ( ! empty( $network_settings['enforce_network_wide'] ) ) {
// Network enforcement is enabled.
@ -136,35 +146,46 @@ class Two_Factor_Extended_Enforcement {
if ( isset( $network_settings['role_requirements'] ) && is_array( $network_settings['role_requirements'] ) ) {
foreach ( $user_roles as $role ) {
if ( isset( $network_settings['role_requirements'][ $role ] ) && is_array( $network_settings['role_requirements'][ $role ] ) ) {
$required = array_merge( $required, $network_settings['role_requirements'][ $role ] );
foreach ( $network_settings['role_requirements'][ $role ] as $provider ) {
if ( is_string( $provider ) ) {
$required[] = $provider;
}
}
}
}
}
// If site override is not allowed, return only network requirements.
if ( empty( $network_settings['allow_site_override'] ) ) {
return array_unique( $required );
return array_values( array_unique( $required ) );
}
}
}
// Get site-level requirements.
$settings = get_option( TWO_FACTOR_EXTENDED_OPTION_SETTINGS, array() );
$settings = get_option( TWO_FACTOR_EXTENDED_OPTION_SETTINGS, array() );
if ( ! is_array( $settings ) ) {
$settings = array();
}
$user_roles = Two_Factor_Extended_Role_Manager::get_user_roles( $user_id );
if ( ! empty( $user_roles ) && isset( $settings['role_requirements'] ) ) {
if ( ! empty( $user_roles ) && isset( $settings['role_requirements'] ) && is_array( $settings['role_requirements'] ) ) {
foreach ( $user_roles as $role ) {
if ( isset( $settings['role_requirements'][ $role ] ) ) {
$role_requirements = $settings['role_requirements'][ $role ];
if ( is_array( $role_requirements ) ) {
$required = array_merge( $required, $role_requirements );
foreach ( $role_requirements as $provider ) {
if ( is_string( $provider ) ) {
$required[] = $provider;
}
}
}
}
}
}
return array_unique( $required );
return array_values( array_unique( $required ) );
}
/**
@ -172,8 +193,8 @@ class Two_Factor_Extended_Enforcement {
*
* @since 0.1.0
*
* @param int $user_id User ID.
* @param array $required_providers Required provider class names.
* @param int $user_id User ID.
* @param array<int, string> $required_providers Required provider class names.
*
* @return bool True if user meets requirements, false otherwise.
*/
@ -204,7 +225,10 @@ class Two_Factor_Extended_Enforcement {
*/
public function is_in_grace_period( int $user_id ): bool {
$settings = get_option( TWO_FACTOR_EXTENDED_OPTION_SETTINGS, array() );
$grace_days = isset( $settings['grace_period_days'] ) ? (int) $settings['grace_period_days'] : 0;
if ( ! is_array( $settings ) ) {
$settings = array();
}
$grace_days = isset( $settings['grace_period_days'] ) && is_numeric( $settings['grace_period_days'] ) ? (int) $settings['grace_period_days'] : 0;
// No grace period configured.
if ( 0 === $grace_days ) {
@ -219,7 +243,7 @@ class Two_Factor_Extended_Enforcement {
return true;
}
$days_elapsed = ( time() - (int) $start_date ) / DAY_IN_SECONDS;
$days_elapsed = ( time() - ( is_numeric( $start_date ) ? (int) $start_date : 0 ) ) / DAY_IN_SECONDS;
return $days_elapsed < $grace_days;
}
@ -234,15 +258,18 @@ class Two_Factor_Extended_Enforcement {
* @return int Remaining days in grace period.
*/
public function get_grace_period_remaining_days( int $user_id ): int {
$settings = get_option( TWO_FACTOR_EXTENDED_OPTION_SETTINGS, array() );
$grace_days = isset( $settings['grace_period_days'] ) ? (int) $settings['grace_period_days'] : 0;
$settings = get_option( TWO_FACTOR_EXTENDED_OPTION_SETTINGS, array() );
if ( ! is_array( $settings ) ) {
$settings = array();
}
$grace_days = isset( $settings['grace_period_days'] ) && is_numeric( $settings['grace_period_days'] ) ? (int) $settings['grace_period_days'] : 0;
$start_date = get_user_meta( $user_id, self::META_ENFORCEMENT_START, true );
if ( empty( $start_date ) || 0 === $grace_days ) {
return 0;
}
$days_elapsed = ( time() - (int) $start_date ) / DAY_IN_SECONDS;
$days_elapsed = ( time() - ( is_numeric( $start_date ) ? (int) $start_date : 0 ) ) / DAY_IN_SECONDS;
$remaining = $grace_days - $days_elapsed;
return max( 0, (int) ceil( $remaining ) );
@ -292,7 +319,7 @@ class Two_Factor_Extended_Enforcement {
<strong><?php esc_html_e( 'Two Factor Extended:', 'two-factor-extended' ); ?></strong>
<?php
printf(
esc_html(
esc_html(
/* translators: 1: Number of days, 2: Required providers list */
_n(
'You have %1$d day remaining to configure the required 2FA methods: %2$s',
@ -341,9 +368,9 @@ class Two_Factor_Extended_Enforcement {
*
* @since 0.1.0
*
* @param array $provider_classes Array of provider class names.
* @param array<int, string> $provider_classes Array of provider class names.
*
* @return array Array of provider labels.
* @return array<int, string> Array of provider labels.
*/
private function get_provider_labels( array $provider_classes ): array {
$names = Two_Factor_Extended_Provider_Detector::get_provider_names();