diff --git a/.distignore b/.distignore
index 4df6c478..ffb1e0e4 100644
--- a/.distignore
+++ b/.distignore
@@ -2,7 +2,6 @@
/node_modules/
/tests/
/vendor/
-/wordpress/
# Files
.*
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 31327e92..c20d222e 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -2,47 +2,142 @@ name: Test
on: [push, pull_request]
+# Cancels all previous workflow runs for pull requests that have not completed.
+concurrency:
+ # The concurrency group contains the workflow name and the branch name for pull requests
+ # or the commit hash for any other events.
+ group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
+ cancel-in-progress: true
+
jobs:
+ lint-js-css:
+ name: Lint JS & CSS
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ cache: 'npm'
+ node-version-file: '.nvmrc'
+
+ - name: Install NPM dependencies
+ run: npm install
+
+ - name: Lint JS
+ run: npm run lint:js
+
+ - name: Lint CSS
+ run: npm run lint:css
+
+ lint-php-and-compatibility:
+ name: Lint PHP & PHP Compatibility checks.
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP and Composer
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.2'
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ cache: 'npm'
+ node-version-file: '.nvmrc'
+
+ - name: Install NPM dependencies
+ run: npm install
+
+ - name: Lint PHP
+ run: npm run lint:php || true # Ignore for now.
+
+ - name: Lint PHP Compatibility
+ run: composer lint-compat
+
+ test-php:
+ name: Test PHP ${{ matrix.php }} ${{ matrix.wp != '' && format( ' (WP {0}) ', matrix.wp ) || '' }}
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ php:
+ - '8.3'
+ - '8.2'
+ - '8.1'
+ - '8.0'
+ - '7.4'
+ - '7.3'
+ - '7.2'
+ wp:
+ - latest
+ - trunk
+ - '6.3'
+ env:
+ WP_ENV_PHP_VERSION: ${{ matrix.php }}
+ WP_ENV_CORE: ${{ matrix.wp == 'trunk' && 'WordPress/WordPress' || format( 'https://wordpress.org/wordpress-{0}.zip', matrix.wp ) }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.2'
- lint:
- name: Lint and Test
- runs-on: ubuntu-20.04
- steps:
- - name: Checkout
- uses: actions/checkout@v3
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ cache: 'npm'
+ node-version-file: '.nvmrc'
- - name: Setup Node
- uses: actions/setup-node@v3
- with:
- cache: 'npm'
- node-version-file: '.nvmrc'
+ - name: Install NPM dependencies
+ run: npm install
- - name: Setup PHP and Composer
- uses: shivammathur/setup-php@v2
- with:
- php-version: '7.4'
- tools: composer:v2
+ - name: Start the Docker testing environment
+ uses: nick-fields/retry@v3
+ with:
+ timeout_minutes: 10
+ max_attempts: 3
+ command: npm run env start
- - name: Install NPM dependencies
- run: npm install
+ - name: Composer install
+ run: |
+ rm composer.lock || true # We need to install fresh.
+ npm run composer install
- - name: Lint JS
- run: npm run lint:js
+ - name: Versions
+ run: |
+ npm run env run cli php -- -v
+ npm run env run cli wp core version
- - name: Lint CSS
- run: npm run lint:css
+ - name: Test
+ run: npm run test
- - name: Lint PHP
- run: npm run lint:php || true # Ignore for now.
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
- - name: Lint PHP Compatibility
- run: composer lint-compat
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.2'
- - name: Start the Docker testing environment
- run: npm run env start --xdebug=coverage
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ cache: 'npm'
+ node-version-file: '.nvmrc'
- - name: Test
- run: npm run test
+ - name: Install NPM dependencies
+ run: npm install
- - name: Build
- run: npm run build
+ - name: Build
+ run: npm run build
diff --git a/.gitignore b/.gitignore
index a58b0b78..6430f0ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,5 +4,4 @@
/vendor/
/dist/
/tests/logs/
-/wordpress/
.phpunit.result.cache
diff --git a/.nvmrc b/.nvmrc
index b6a7d89c..209e3ef4 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-16
+20
diff --git a/.wp-env.json b/.wp-env.json
index 0ee66b30..8e06478a 100644
--- a/.wp-env.json
+++ b/.wp-env.json
@@ -1,5 +1,15 @@
{
- "core": "./wordpress",
"phpVersion": "7.4",
- "plugins": [ "." ]
+ "plugins": [ "." ],
+ "env": {
+ "tests": {
+ "config": {
+ "WP_DEBUG": true,
+ "WP_TESTS_EMAIL": "admin@example.org",
+ "WP_TESTS_DOMAIN": "example.org",
+ "WP_SITEURL": "https://example.org",
+ "WP_HOME": "https://example.org"
+ }
+ }
+ }
}
diff --git a/Gruntfile.js b/Gruntfile.js
index e60363bf..9a58b436 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -11,16 +11,6 @@ module.exports = function( grunt ) {
invert: true,
} );
- /**
- * Check if CLI input appears to indicate a truthy value.
- *
- * @param {string} input Value to check.
- * @return {boolean} If value appears to be truthy.
- */
- function isTruthy( input ) {
- return ( '1' === input || 'true' === input );
- }
-
grunt.initConfig( {
pkg: grunt.file.readJSON( 'package.json' ),
@@ -47,23 +37,6 @@ module.exports = function( grunt ) {
],
},
},
-
- wp_deploy: {
- options: {
- plugin_slug: 'two-factor',
- build_dir: '<%= dist_dir %>',
- assets_dir: 'assets',
- },
- wporg: {
- options: {
- skip_confirmation: isTruthy( process.env.DEPLOY_SKIP_CONFIRMATION ),
- svn_user: process.env.DEPLOY_SVN_USERNAME,
- deploy_tag: isTruthy( process.env.DEPLOY_TAG ),
- deploy_trunk: isTruthy( process.env.DEPLOY_TRUNK ),
- assets_dir: ( isTruthy( process.env.DEPLOY_TAG ) || isTruthy( process.env.DEPLOY_TRUNK ) ) ? 'assets' : null,
- },
- },
- },
} );
grunt.registerTask(
@@ -72,11 +45,4 @@ module.exports = function( grunt ) {
'copy',
]
);
-
- grunt.registerTask(
- 'deploy', [
- 'build',
- 'wp_deploy',
- ]
- );
};
diff --git a/class-two-factor-core.php b/class-two-factor-core.php
index c6f28145..51c3cee3 100644
--- a/class-two-factor-core.php
+++ b/class-two-factor-core.php
@@ -57,7 +57,7 @@ class Two_Factor_Core {
const USER_PASSWORD_WAS_RESET_KEY = '_two_factor_password_was_reset';
/**
- * URL query paramater used for our custom actions.
+ * URL query parameter used for our custom actions.
*
* @var string
*/
@@ -389,7 +389,7 @@ public static function fetch_user( $user = null ) {
/**
* Get all Two-Factor Auth providers that are enabled for the specified|current user.
*
- * @param int|WP_User $user Optonal. User ID, or WP_User object of the the user. Defaults to current user.
+ * @param int|WP_User $user Optional. User ID, or WP_User object of the the user. Defaults to current user.
* @return array
*/
public static function get_enabled_providers_for_user( $user = null ) {
@@ -417,7 +417,7 @@ public static function get_enabled_providers_for_user( $user = null ) {
/**
* Get all Two-Factor Auth providers that are both enabled and configured for the specified|current user.
*
- * @param int|WP_User $user Optonal. User ID, or WP_User object of the the user. Defaults to current user.
+ * @param int|WP_User $user Optional. User ID, or WP_User object of the the user. Defaults to current user.
* @return array
*/
public static function get_available_providers_for_user( $user = null ) {
@@ -442,7 +442,7 @@ public static function get_available_providers_for_user( $user = null ) {
/**
* Fetch the provider for the request based on the user preferences.
*
- * @param int|WP_User $user Optonal. User ID, or WP_User object of the the user. Defaults to current user.
+ * @param int|WP_User $user Optional. User ID, or WP_User object of the the user. Defaults to current user.
* @param null|string|object $preferred_provider Optional. The name of the provider, the provider, or empty.
* @return null|object The provider
*/
@@ -480,7 +480,7 @@ public static function get_provider_for_user( $user = null, $preferred_provider
*
* @since 0.1-dev
*
- * @param int|WP_User $user Optonal. User ID, or WP_User object of the the user. Defaults to current user.
+ * @param int|WP_User $user Optional. User ID, or WP_User object of the the user. Defaults to current user.
* @return object|null
*/
public static function get_primary_provider_for_user( $user = null ) {
@@ -526,7 +526,7 @@ public static function get_primary_provider_for_user( $user = null ) {
*
* @since 0.1-dev
*
- * @param int|WP_User $user Optonal. User ID, or WP_User object of the the user. Defaults to current user.
+ * @param int|WP_User $user Optional. User ID, or WP_User object of the the user. Defaults to current user.
* @return bool
*/
public static function is_user_using_two_factor( $user = null ) {
@@ -683,8 +683,8 @@ public static function maybe_show_last_login_failure_notice( $user ) {
echo '
';
printf(
_n(
- 'WARNING: Your account has attempted to login without providing a valid two factor token. The last failed login occured %2$s ago. If this wasn\'t you, you should reset your password.',
- 'WARNING: Your account has attempted to login %1$s times without providing a valid two factor token. The last failed login occured %2$s ago. If this wasn\'t you, you should reset your password.',
+ 'WARNING: Your account has attempted to login without providing a valid two factor token. The last failed login occurred %2$s ago. If this wasn\'t you, you should reset your password.',
+ 'WARNING: Your account has attempted to login %1$s times without providing a valid two factor token. The last failed login occurred %2$s ago. If this wasn\'t you, you should reset your password.',
$failed_login_count,
'two-factor'
),
@@ -1405,6 +1405,8 @@ public static function _login_form_revalidate_2fa( $nonce = '', $provider = '',
'two-factor-login' => time(),
) );
+ do_action( 'two_factor_user_revalidated', $user, $provider );
+
// Must be global because that's how login_header() uses it.
global $interim_login;
$interim_login = isset( $_REQUEST['interim-login'] ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited,WordPress.Security.NonceVerification.Recommended
@@ -1435,7 +1437,7 @@ public static function _login_form_revalidate_2fa( $nonce = '', $provider = '',
* @param object $provider The Two Factor Provider.
* @param WP_User $user The user being authenticated.
* @param bool $is_post_request Whether the request is a POST request.
- * @return false|WP_Error|true WP_Error when an error occurs, true when the user is authenticated, false if no action occured.
+ * @return false|WP_Error|true WP_Error when an error occurs, true when the user is authenticated, false if no action occurred.
*/
public static function process_provider( $provider, $user, $is_post_request ) {
if ( ! $provider ) {
@@ -1471,7 +1473,7 @@ public static function process_provider( $provider, $user, $is_post_request ) {
// Ask the provider to verify the second factor.
if ( true !== $provider->validate_authentication( $user ) ) {
- // Store the last time a failed login occured.
+ // Store the last time a failed login occurred.
update_user_meta( $user->ID, self::USER_RATE_LIMIT_KEY, time() );
// Store the number of failed login attempts.
@@ -1720,48 +1722,47 @@ public static function user_two_factor_options( $user ) {
wp_nonce_field( 'user_two_factor_options', '_nonce_user_two_factor_options', false );
?>
+
-