Repository navigation
Let providers declare their secrets; move secrets logic behind an injectable store - #3
Merged
Merged
Conversation
Two_Factor_Secrets was all static, so tests reached into it through a public $test_overrides array and the two_factor_secrets_api_present filter, and most of them needed the real Secrets API loaded. The logic now lives in Two_Factor_Secrets_Manager, which is constructed with a Two_Factor_Secrets_Store. Two_Factor_Secrets_Api_Store is the only code that calls the Secrets API. Two_Factor_Secrets keeps every public static method, forwarding to a shared manager, so callers are unchanged. Tests install an in-memory store instead, which removes $test_overrides and the filter and lets the secrets tests run without the feature plugin. A small set of tests still exercises the real store.
All Secrets API handling for TOTP lived in Two_Factor_Totp, and the CLI called that class by name, so a custom provider got none of it. Providers now declare the user meta keys that hold secrets through the static Two_Factor_Provider::user_secret_meta_keys(). The storage logic (verified writes, lazy one-way migration, deletion, storage state) moves into Two_Factor_Secrets_Manager, generalised over a slug and a meta key. Two_Factor_Secrets_Lifecycle handles deletion with the user and on uninstall, the unreachable-secrets notice, Site Health and the counts for every declared secret, registered from Two_Factor_Core::add_hooks(). Two_Factor_Totp's public methods keep their signatures and become wrappers. Its slug, marker key and secret name are unchanged, so nothing already stored moves. Two_Factor_Totp::register_secret_lifecycle_hooks() is removed. Two_Factor_Core::get_provider_secrets() lists secrets from every provider class, including ones turned off site-wide, without instantiating any. A duplicate slug is refused. wp two-factor secrets migrate covers every declared secret, and secrets status prints one row per secret.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on WordPress#1010 (base:
secrets-api-totp). It answers two review comments from @kasparsd there:It is a refactor: no change to what is stored or where, and no change to login behaviour.
1. An instance class behind the static facade
Two_Factor_Secretswas all static, so tests reached into it through a public$test_overridesarray and thetwo_factor_secrets_api_presentfilter, and most of them needed the real Secrets API loaded.Two_Factor_Secrets_Storeis a small interface for where secrets are physically kept.Two_Factor_Secrets_Api_Storeimplements it and is now the only code that calls the Secrets API.Two_Factor_Secrets_Managerholds the logic and is constructed with a store.Two_Factor_Secretskeeps every public static method and forwards to a shared manager, so callers are unchanged.Tests install an in-memory store.
$test_overridesand thetwo_factor_secrets_api_presentfilter are removed, and the secrets tests run with or without the feature plugin. A small test class still runs against the real store, so the in-memory one can't drift unnoticed.2. Providers declare their secrets
All Secrets API handling for TOTP lived in
Two_Factor_Totp, and the CLI called that class by name. A custom provider got none of it.Providers declare secrets with one static method, modelled on
uninstall_user_meta_keys():The storage logic (verified writes, lazy one-way migration, deletion, storage state) moves into the manager, generalised over a slug and a meta key.
Two_Factor_Secrets_Lifecyclehandles deletion with the user and on uninstall, the unreachable-secrets notice, Site Health and the counts, for every declared secret. It is registered fromTwo_Factor_Core::add_hooks(), andTwo_Factor_Totp::register_secret_lifecycle_hooks()is gone.Two_Factor_Totp's public methods keep their signatures and become wrappers. The file drops by about 500 lines.wp two-factor secrets migratecovers every declared secret, andsecrets statusprints one row per secret with a newsecretcolumn.What stays the same
_two_factor_totp_key_networkmarker and thetwo-factor/totp-{user_id}secret name, so nothing stored by Store TOTP secrets with the WordPress Secrets API WordPress/two-factor#1010 moves.( $user_id, $slug ).Design points worth a look
two_factor_providersfilter that removes them, but a disabled provider may still hold users' secrets.Two_Factor_Core::get_provider_secrets()sets a flag that the enforcement filter checks and stands aside for. No provider is instantiated._doing_it_wrong()and the first declaration wins. A slug must not change once secrets exist.Two_Factor_Dummy_Secret).Not done here
--providerfilter onsecrets migrate.Renames
All of these were introduced in WordPress#1010 and have never been released:
two_factor_totp_secret_storage→two_factor_secret_storagetwo_factor_totp_affected_users→two_factor_secrets_affected_userssecrets migratelog lines now name the secret, e.g.User 12 (totp): …Testing
PHPCS, PHPStan and both PHPUnit suites pass locally (453 tests each, single site and multisite). New tests cover the real store, the registry (including disabled providers, invalid and duplicate declarations) and core handling a second provider's secret through migration, user deletion, uninstall, Site Health and the CLI.