From b44758762c9b4bf2179f2bdc6fa89f11c77ae37d Mon Sep 17 00:00:00 2001 From: Travis Weston Date: Wed, 31 Jan 2024 15:50:06 -0500 Subject: [PATCH] Move to login nonce feature --- .../features/class-disable-login-cache.php | 51 ------------- .../alleyvate/features/class-login-nonce.php | 21 ++++++ src/alley/wp/alleyvate/load.php | 1 - .../features/test-disable-login-cache.php | 75 ------------------- .../alleyvate/features/test-login-nonce.php | 36 +++++++++ 5 files changed, 57 insertions(+), 127 deletions(-) delete mode 100644 src/alley/wp/alleyvate/features/class-disable-login-cache.php delete mode 100644 tests/alley/wp/alleyvate/features/test-disable-login-cache.php diff --git a/src/alley/wp/alleyvate/features/class-disable-login-cache.php b/src/alley/wp/alleyvate/features/class-disable-login-cache.php deleted file mode 100644 index b06ddd9c..00000000 --- a/src/alley/wp/alleyvate/features/class-disable-login-cache.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @package wp-alleyvate - */ - -namespace Alley\WP\Alleyvate\Features; - -use Alley\WP\Alleyvate\Feature; - -/** - * Adds an HTTP header to the login page to disable storing of that page in - * cache. The login page already requires cache revalidation, but it doesn't - * block cache's from storing a local copy. Enabling this allows us to - * remove the risk of local changes from being ignored because a stored cache - * copy. - */ -final class Disable_Login_Cache implements Feature { - /** - * Boot the feature. - */ - public function boot(): void { - add_filter( 'nocache_headers', [ $this, 'add_no_store_to_login' ] ); - } - - /** - * Adds the `no-store` flag to the `Cache-Control` headers. - * - * @param array $headers The headers array. - * @return array - */ - public function add_no_store_to_login( $headers ): array { - if ( ! is_array( $headers ) ) { - $headers = []; - } - - if ( 'wp-login.php' !== ( $GLOBALS['pagenow'] ?? '' ) ) { - return $headers; - } - - $headers['Cache-Control'] = 'no-cache, must-revalidate, max-age=0, no-store'; - - return $headers; - } -} diff --git a/src/alley/wp/alleyvate/features/class-login-nonce.php b/src/alley/wp/alleyvate/features/class-login-nonce.php index ae49a7ea..85acd438 100644 --- a/src/alley/wp/alleyvate/features/class-login-nonce.php +++ b/src/alley/wp/alleyvate/features/class-login-nonce.php @@ -51,6 +51,27 @@ public function boot(): void { add_action( 'login_form_login', [ self::class, 'action__add_nonce_life_filter' ] ); add_action( 'login_head', [ self::class, 'action__add_meta_refresh' ] ); add_action( 'after_setup_theme', [ self::class, 'action__pre_validate_login_nonce' ], 9999 ); + add_filter( 'nocache_headers', [ self::class, 'add_no_store_to_login' ] ); + } + + /** + * Adds the `no-store` flag to the `Cache-Control` headers. + * + * @param array $headers The headers array. + * @return array + */ + public static function add_no_store_to_login( $headers ): array { + if ( ! is_array( $headers ) ) { + $headers = []; + } + + if ( 'wp-login.php' !== ( $GLOBALS['pagenow'] ?? '' ) ) { + return $headers; + } + + $headers['Cache-Control'] = 'no-cache, must-revalidate, max-age=0, no-store'; + + return $headers; } /** diff --git a/src/alley/wp/alleyvate/load.php b/src/alley/wp/alleyvate/load.php index 848416a7..048773a3 100644 --- a/src/alley/wp/alleyvate/load.php +++ b/src/alley/wp/alleyvate/load.php @@ -28,7 +28,6 @@ function available_features(): array { 'disable_sticky_posts' => new Features\Disable_Sticky_Posts(), 'disable_trackbacks' => new Features\Disable_Trackbacks(), 'disallow_file_edit' => new Features\Disallow_File_Edit(), - 'disable_login_cache' => new Features\Disable_Login_Cache(), 'login_nonce' => new Features\Login_Nonce(), 'prevent_framing' => new Features\Prevent_Framing(), 'redirect_guess_shortcircuit' => new Features\Redirect_Guess_Shortcircuit(), diff --git a/tests/alley/wp/alleyvate/features/test-disable-login-cache.php b/tests/alley/wp/alleyvate/features/test-disable-login-cache.php deleted file mode 100644 index d5fc8b30..00000000 --- a/tests/alley/wp/alleyvate/features/test-disable-login-cache.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @package wp-alleyvate - * - * @phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited, Generic.CodeAnalysis.EmptyStatement.DetectedCatch, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound - */ - -namespace Alley\WP\Alleyvate\Features; - -use Alley\WP\Alleyvate\Feature; -use Mantle\Testkit\Test_Case; - -/** - * Tests for the disabling the login cache. - */ -final class Test_Disable_Login_Cache extends Test_Case { - /** - * Feature instance. - * - * @var Feature - */ - private Feature $feature; - - /** - * Set up. - */ - protected function setUp(): void { - parent::setUp(); - - $this->feature = new Disable_Login_Cache(); - } - - /** - * Verify that the no-store flag is added to the login page. - * - * Note: `wp_get_nocache_headers()` is used by `nocache_headers()` which - * in turn is called on `wp-login.php`. We call it directly here so - * we can assert against an array instead of trying to send headers. - */ - public function test_login_page_cache_is_no_stored() { - global $pagenow; - - $pagenow = 'wp-login.php'; - - $this->feature->boot(); - - $headers = \wp_get_nocache_headers(); - - self::assertArrayHasKey( 'Cache-Control', $headers ); - self::assertStringContainsString( 'no-store', $headers['Cache-Control'] ); - } - - /** - * Verify that the no-store flag isn't added to other pages. - */ - public function test_non_login_page_is_stored() { - global $pagenow; - - $pagenow = 'single.php'; // Anything other than wp-login.php. - - $this->feature->boot(); - - $headers = \wp_get_nocache_headers(); - - self::assertArrayHasKey( 'Cache-Control', $headers ); - self::assertStringNotContainsString( 'no-store', $headers['Cache-Control'] ); - } -} diff --git a/tests/alley/wp/alleyvate/features/test-login-nonce.php b/tests/alley/wp/alleyvate/features/test-login-nonce.php index 2918b50f..cd612f47 100644 --- a/tests/alley/wp/alleyvate/features/test-login-nonce.php +++ b/tests/alley/wp/alleyvate/features/test-login-nonce.php @@ -144,4 +144,40 @@ public function test_logout_nonce_validates(): void { $this->assertTrue( wp_validate_boolean( wp_verify_nonce( $token, 'log-out' ) ) ); } + + /** + * Verify that the no-store flag is added to the login page. + * + * Note: `wp_get_nocache_headers()` is used by `nocache_headers()` which + * in turn is called on `wp-login.php`. We call it directly here so + * we can assert against an array instead of trying to send headers. + */ + public function test_login_page_cache_is_no_stored() { + global $pagenow; + + $pagenow = 'wp-login.php'; + + $this->feature->boot(); + + $headers = \wp_get_nocache_headers(); + + self::assertArrayHasKey( 'Cache-Control', $headers ); + self::assertStringContainsString( 'no-store', $headers['Cache-Control'] ); + } + + /** + * Verify that the no-store flag isn't added to other pages. + */ + public function test_non_login_page_is_stored() { + global $pagenow; + + $pagenow = 'single.php'; // Anything other than wp-login.php. + + $this->feature->boot(); + + $headers = \wp_get_nocache_headers(); + + self::assertArrayHasKey( 'Cache-Control', $headers ); + self::assertStringNotContainsString( 'no-store', $headers['Cache-Control'] ); + } }