Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account Protection: Add password detection flow #41105

Draft
wants to merge 16 commits into
base: add/protect/account-protection-settings
Choose a base branch
from
Draft
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
21 changes: 21 additions & 0 deletions projects/packages/account-protection/src/assets/jetpack-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
147 changes: 129 additions & 18 deletions projects/packages/account-protection/src/class-account-protection.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,78 +13,189 @@
* Class Account_Protection
*/
class Account_Protection {

const PACKAGE_VERSION = '1.0.0-alpha';

Check failure on line 16 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Changelogger validity

Version mismatch, expected 0.1.0-alpha but found 1.0.0-alpha! Before you can merge your PR, please run `tools/fixup-project-versions.sh`, commit, and push the generated changes to your branch to fix this.
const ACCOUNT_PROTECTION_MODULE_NAME = 'account-protection';
const STRICT_MODE_OPTION_NAME = 'jetpack_account_protection_strict_mode';

/**
* Modules dependency.
*
* @var Modules
*/
private $modules;

Check failure on line 25 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Static analysis

UndefError PhanUndeclaredTypeProperty Property \Automattic\Jetpack\Account_Protection\Account_Protection->modules has undeclared type \Automattic\Jetpack\Modules

/**
* Password Detection dependency.
*
* @var Password_Detection
*/
private $password_detection;

/**
* Constructor.
*
* @param Modules|null $modules Modules dependency.
* @param Password_Detection|null $password_detection Password detection dependency.
*/
public function __construct( Modules $modules = null, Password_Detection $password_detection = null ) {

Check warning on line 40 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / dev branch for PHP 8.0

Implicitly marking a parameter as nullable is deprecated since PHP 8.4. Update the type to be explicitly nullable instead. Found implicitly nullable parameter: $modules. (PHPCompatibility.FunctionDeclarations.RemovedImplicitlyNullableParam.Deprecated)

Check warning on line 40 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / dev branch for PHP 8.0

Implicitly marking a parameter as nullable is deprecated since PHP 8.4. Update the type to be explicitly nullable instead. Found implicitly nullable parameter: $password_detection. (PHPCompatibility.FunctionDeclarations.RemovedImplicitlyNullableParam.Deprecated)

Check failure on line 40 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Static analysis

DeprecatedError PhanDeprecatedImplicitNullableParam Implicit nullable parameters (\Automattic\Jetpack\Account_Protection\Password_Detection $password_detection = null) have been deprecated in PHP 8.4

Check failure on line 40 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Static analysis

DeprecatedError PhanDeprecatedImplicitNullableParam Implicit nullable parameters (\Automattic\Jetpack\Modules $modules = null) have been deprecated in PHP 8.4

Check failure on line 40 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Static analysis

UndefError PhanUndeclaredTypeParameter Parameter $modules has undeclared type \Automattic\Jetpack\Modules
$this->modules = $modules ?? new Modules();

Check failure on line 41 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Static analysis

UndefError PhanUndeclaredClassMethod Call to method __construct from undeclared class \Automattic\Jetpack\Modules
$this->password_detection = $password_detection ?? new Password_Detection();
}

/**
* Initializes the configurations needed for the account protection module.
*/
public static function init() {
public function init(): void {
$this->register_hooks();

if ( $this->is_enabled() ) {
$this->register_runtime_hooks();
}
}

/**
* Register hooks for module activation and environment validation.
*/
private function register_hooks(): void {
// Account protection activation/deactivation hooks
add_action( 'jetpack_activate_module_account-protection', __CLASS__ . '::on_account_protection_activation' );
add_action( 'jetpack_deactivate_module_account-protection', __CLASS__ . '::on_account_protection_deactivation' );
add_action( 'jetpack_activate_module_' . self::ACCOUNT_PROTECTION_MODULE_NAME, array( $this, 'on_account_protection_activation' ) );
add_action( 'jetpack_deactivate_module_' . self::ACCOUNT_PROTECTION_MODULE_NAME, array( $this, 'on_account_protection_deactivation' ) );

// Do not run in unsupported environments
add_action( 'jetpack_get_available_modules', array( $this, 'remove_module_on_unsupported_environments' ) );
add_action( 'jetpack_get_available_standalone_modules', array( $this, 'remove_standalone_module_on_unsupported_environments' ) );

// Register REST routes
add_action( 'rest_api_init', array( new REST_Controller(), 'register_rest_routes' ) );
}

/**
* Register hooks for runtime operations.
*/
private function register_runtime_hooks(): void {
// Validate password after successful login
add_action( 'wp_authenticate_user', array( $this->password_detection, 'login_form_password_detection' ), 10, 2 );

// Add password detection flow
add_action( 'login_form_password-detection', array( $this->password_detection, 'render_page' ), 10, 2 );

// Remove password detection usermeta after password reset and on profile password update
add_action( 'after_password_reset', array( $this->password_detection, 'delete_usermeta_after_password_reset' ), 10, 2 );
add_action( 'profile_update', array( $this->password_detection, 'delete_usermeta_on_profile_update' ), 10, 2 );

// Register AJAX resend password reset email action
add_action( 'wp_ajax_resend_password_reset', array( $this->password_detection, 'ajax_resend_password_reset_email' ) );
}

/**
* Activate the account protection on module activation.
*/
public static function on_account_protection_activation() {
// Account protection activated
public function on_account_protection_activation(): void {
// Activation logic can be added here
}

/**
* Deactivate the account protection on module activation.
* Deactivate the account protection on module deactivation.
*/
public static function on_account_protection_deactivation() {
// Account protection deactivated
public function on_account_protection_deactivation(): void {
// Remove password detection user meta on deactivation
// TODO: Run on Jetpack and Protect deactivation
$this->password_detection->delete_all_usermeta();
}

/**
* Determines if the account protection module is enabled on the site.
*
* @return bool
*/
public static function is_enabled() {
return ( new Modules() )->is_active( 'account-protection' );
public function is_enabled() {
return $this->modules->is_active( self::ACCOUNT_PROTECTION_MODULE_NAME );

Check failure on line 112 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Static analysis

UndefError PhanUndeclaredClassMethod Call to method is_active from undeclared class \Automattic\Jetpack\Modules
}

/**
* Enables the account protection module.
*
* @return bool
*/
public static function enable() {
public function enable() {
// Return true if already enabled.
if ( self::is_enabled() ) {
if ( $this->is_enabled() ) {
return true;
}
return ( new Modules() )->activate( 'account-protection', false, false );
return $this->modules->activate( self::ACCOUNT_PROTECTION_MODULE_NAME, false, false );

Check failure on line 125 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Static analysis

UndefError PhanUndeclaredClassMethod Call to method activate from undeclared class \Automattic\Jetpack\Modules
}

/**
* Disables the account protection module.
*
* @return bool
*/
public static function disable() {
public function disable(): bool {
// Return true if already disabled.
if ( ! self::is_enabled() ) {
if ( ! $this->is_enabled() ) {
return true;
}
return ( new Modules() )->deactivate( 'account-protection' );
return $this->modules->deactivate( self::ACCOUNT_PROTECTION_MODULE_NAME );

Check failure on line 138 in projects/packages/account-protection/src/class-account-protection.php

View workflow job for this annotation

GitHub Actions / Static analysis

UndefError PhanUndeclaredClassMethod Call to method deactivate from undeclared class \Automattic\Jetpack\Modules
}

/**
* Determines if Account Protection is supported in the current environment.
*
* @return bool
*/
public function is_supported_environment(): bool {
// Do not run when killswitch is enabled
if ( defined( 'DISABLE_JETPACK_ACCOUNT_PROTECTION' ) && DISABLE_JETPACK_ACCOUNT_PROTECTION ) {
return false;
}

return true;
}

/**
* Disables the Account Protection module when on an unsupported platform in Jetpack.
*
* @param array $modules Filterable value for `jetpack_get_available_modules`.
*
* @return array Array of module slugs.
*/
public function remove_module_on_unsupported_environments( array $modules ): array {
if ( ! $this->is_supported_environment() ) {
// Account protection should never be available on unsupported platforms.
unset( $modules[ self::ACCOUNT_PROTECTION_MODULE_NAME ] );
}

return $modules;
}

/**
* Disables the Account Protection module when on an unsupported platform in a standalone plugin.
*
* @param array $modules Filterable value for `jetpack_get_available_standalone_modules`.
*
* @return array Array of module slugs.
*/
public function remove_standalone_module_on_unsupported_environments( array $modules ): array {
if ( ! $this->is_supported_environment() ) {
// Account Protection should never be available on unsupported platforms.
$modules = array_filter(
$modules,
function ( $module ) {
return $module !== self::ACCOUNT_PROTECTION_MODULE_NAME;
}
);

}

return $modules;
}

/**
* Get the account protection settings.
*
* @return array
*/
public static function get_settings() {
public function get_settings(): array {
$settings = array(
self::STRICT_MODE_OPTION_NAME => get_option( self::STRICT_MODE_OPTION_NAME, false ),
);
Expand Down
Loading
Loading