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

Issue #70 - Add no-store cache header to wp-login.php #71

Merged
merged 6 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
51 changes: 51 additions & 0 deletions src/alley/wp/alleyvate/features/class-disable-login-cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/**
* Class file for Disable_Login_Cache
*
* (c) Alley <[email protected]>
*
* 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;
}
}
1 change: 1 addition & 0 deletions src/alley/wp/alleyvate/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ 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(),
Expand Down
75 changes: 75 additions & 0 deletions tests/alley/wp/alleyvate/features/test-disable-login-cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php
/**
* Class file for Test_Disable_Login_Cache
*
* (c) Alley <[email protected]>
*
* 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'] );
}
}
Loading