Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions modules/data-sync/class-data-sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Automattic\VIP\Security\Utils\Logger;
use Automattic\VIP\Security\Constants;
use Automattic\VIP\Security\MFAUsers\Forced_MFA_Users;

/**
* This is the class that sends data to Site Details Service (SDS)
Expand Down Expand Up @@ -42,31 +43,49 @@ public static function add_security_boost_extended_data( $data ) {


/**
* Add the two-factor enforcement status details to the Site Details Service (SDS) payload.
* Add the two-factor enforcement status and MFA additional capabilities details to the Site Details Service (SDS) payload.
*
* The function augments the incoming `$data` array by injecting a new element under the
* standard SDS data key (`Constants::SDS_DATA_KEY`). The resulting payload section has the
* following structure:
*
* 'two_factor_status' => [
* 'is_enforced_globally' => bool, // `wpcom_vip_is_two_factor_forced` hooked to `__return_true`
* 'is_not_enforced_globally' => bool, // `wpcom_vip_is_two_factor_forced` hooked to `__return_false`
* 'has_two_factor_forced_filter' => bool, // Any filter present on `wpcom_vip_is_two_factor_forced`
* 'is_entirely_disabled' => bool, // 2FA disabled via `wpcom_vip_enable_two_factor` returning false
* 'has_enable_two_factor_filter' => bool, // Any filter present on `wpcom_vip_enable_two_factor`
* 'is_enforced_globally' => bool, // `wpcom_vip_is_two_factor_forced` hooked to `__return_true`
* 'is_not_enforced_globally' => bool, // `wpcom_vip_is_two_factor_forced` hooked to `__return_false`
* 'has_two_factor_forced_filter' => bool, // Any filter present on `wpcom_vip_is_two_factor_forced`
* 'is_entirely_disabled' => bool, // 2FA disabled via `wpcom_vip_enable_two_factor` returning false
* 'has_enable_two_factor_filter' => bool, // Any filter present on `wpcom_vip_enable_two_factor`
* 'has_mfa_additional_capabilities_filter' => bool, // Any filter present on MFA additional capabilities
* 'mfa_additional_required_capabilities' => string, // Comma-separated list of additional capabilities when filter is present
* ],
*
* @param array $data The current SDS payload data array.
* @return array Modified SDS payload including the `two_factor_status` information.
*/
public static function add_two_factor_enforcement_status_to_sds_payload( $data ) {
$has_additional_capabilities_filter = has_filter( Forced_MFA_Users::ADDITIONAL_CAPABILITIES_FILTER_NAME ) !== false;
$mfa_additional_required_capabilities = '';
if ( $has_additional_capabilities_filter ) {
try {
$mfa_additional_required_capabilities = implode( ',', apply_filters( Forced_MFA_Users::ADDITIONAL_CAPABILITIES_FILTER_NAME, [] ) );
} catch ( \Exception $e ) {
Logger::error(
self::LOG_FEATURE_NAME,
'Error retrieving MFA additional required capabilities: ' . $e->getMessage()
);
}
}
$data['two_factor_status'] = [
// return wpcom_vip_is_two_factor_forced status
'is_enforced_globally' => \has_filter( 'wpcom_vip_is_two_factor_forced', '__return_true' ) !== false,
'is_not_enforced_globally' => \has_filter( 'wpcom_vip_is_two_factor_forced', '__return_false' ) !== false,
'has_two_factor_forced_filter' => has_filter( 'wpcom_vip_is_two_factor_forced' ) !== false,
'is_enforced_globally' => \has_filter( 'wpcom_vip_is_two_factor_forced', '__return_true' ) !== false,
'is_not_enforced_globally' => \has_filter( 'wpcom_vip_is_two_factor_forced', '__return_false' ) !== false,
'has_two_factor_forced_filter' => has_filter( 'wpcom_vip_is_two_factor_forced' ) !== false,
// return wpcom_vip_enable_two_factor status
'is_entirely_disabled' => \has_filter( 'wpcom_vip_enable_two_factor', '__return_false' ) !== false || apply_filters( 'wpcom_vip_enable_two_factor', true ) === false,
'has_enable_two_factor_filter' => \has_filter( 'wpcom_vip_enable_two_factor' ) !== false,
'is_entirely_disabled' => \has_filter( 'wpcom_vip_enable_two_factor', '__return_false' ) !== false || apply_filters( 'wpcom_vip_enable_two_factor', true ) === false,
'has_enable_two_factor_filter' => \has_filter( 'wpcom_vip_enable_two_factor' ) !== false,

'has_mfa_additional_capabilities_filter' => $has_additional_capabilities_filter,
'mfa_additional_required_capabilities' => $mfa_additional_required_capabilities,
];
return $data;
}
Expand Down
54 changes: 49 additions & 5 deletions tests/phpunit/test-data-sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ public function setUp(): void {
// Clear any pre-existing filters entirely to get a true default state.
remove_all_filters( 'wpcom_vip_is_two_factor_forced' );
remove_all_filters( 'wpcom_vip_enable_two_factor' );
remove_all_filters( \Automattic\VIP\Security\MFAUsers\Forced_MFA_Users::ADDITIONAL_CAPABILITIES_FILTER_NAME );
}

public function tearDown(): void {
// Clean up any filters added in individual tests.
remove_all_filters( 'wpcom_vip_is_two_factor_forced' );
remove_all_filters( 'wpcom_vip_enable_two_factor' );
remove_all_filters( \Automattic\VIP\Security\MFAUsers\Forced_MFA_Users::ADDITIONAL_CAPABILITIES_FILTER_NAME );

parent::tearDown();
}
Expand All @@ -46,11 +48,13 @@ public function tearDown(): void {
public function test_two_factor_enforcement_status_defaults() {
$expected = [
'two_factor_status' => [
'is_enforced_globally' => false,
'is_not_enforced_globally' => false,
'has_two_factor_forced_filter' => false,
'is_entirely_disabled' => false,
'has_enable_two_factor_filter' => false,
'is_enforced_globally' => false,
'is_not_enforced_globally' => false,
'has_two_factor_forced_filter' => false,
'is_entirely_disabled' => false,
'has_enable_two_factor_filter' => false,
'has_mfa_additional_capabilities_filter' => false,
'mfa_additional_required_capabilities' => '',
],
];

Expand Down Expand Up @@ -108,6 +112,46 @@ public function test_add_two_factor_enforcement_status_to_sds_payload() {
$this->assertSame( $expected, $site_details[ Constants::SDS_DATA_KEY ] );
}

/**
* Test MFA additional capabilities filter detection and content extraction.
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function test_mfa_additional_capabilities_filter() {
// Test with no filter present
$status = Data_Sync::add_two_factor_enforcement_status_to_sds_payload( [] );
$this->assertFalse( $status['two_factor_status']['has_mfa_additional_capabilities_filter'] );
$this->assertSame( '', $status['two_factor_status']['mfa_additional_required_capabilities'] );

// Test with filter present returning capabilities
add_filter( \Automattic\VIP\Security\MFAUsers\Forced_MFA_Users::ADDITIONAL_CAPABILITIES_FILTER_NAME, function () {
return [ 'edit_posts', 'manage_options', 'upload_files' ];
} );

$status = Data_Sync::add_two_factor_enforcement_status_to_sds_payload( [] );
$this->assertTrue( $status['two_factor_status']['has_mfa_additional_capabilities_filter'] );
$this->assertSame( 'edit_posts,manage_options,upload_files', $status['two_factor_status']['mfa_additional_required_capabilities'] );

// Clean up
remove_all_filters( \Automattic\VIP\Security\MFAUsers\Forced_MFA_Users::ADDITIONAL_CAPABILITIES_FILTER_NAME );
}

/**
* Test status when two-factor is entirely disabled.
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function test_two_factor_entirely_disabled() {
add_filter( 'wpcom_vip_enable_two_factor', '__return_false' );

$status = Data_Sync::add_two_factor_enforcement_status_to_sds_payload( [] );

$this->assertTrue( $status['two_factor_status']['is_entirely_disabled'] );
$this->assertTrue( $status['two_factor_status']['has_enable_two_factor_filter'] );
}

// check that it adds a vip_site_details_index_data filter and it adds the vip_security_boost key
public function test_add_security_boost_extended_data() {
// Data_Sync hooks itself up in its init() call at the bottom of the file,
Expand Down
Loading