Major refactor of the 2FA enforcement model: per-journal configuration,
OR-based rule set, plugin is now always active.
Added
- Site-level login interception: a new
Authentication::authenticatehook
intercepts login attempts on the global (site-level) login form. Site-level
login always requires OTP, regardless of per-journal configuration. - Site-wide rules for elevated roles: Site Administrator and Journal Manager
(in any journal) always require OTP, on any journal and at site level. - Cautious default for external users: a user with no roles in the journal
they are logging into now always receives OTP. - Documented opt-out mechanism: saving a journal's required-roles list empty
opts that journal out of OTP for ordinary roles (Site Admin, JM, and external
users still receive OTP).
Changed
- OTP enforcement: from "highest-privilege role wins" to OR logic
(OTP is required if the user has any of the selected roles). - Settings storage: back to per-journal
plugin_settings(instead of the
site-widesite_settingsused in 1.0.1). - Plugin architecture: registers as a site plugin (
isSitePlugin()=true)
but cannot be disabled (getCanDisable()=false). Always-active component;
administrators configure required roles per journal, but cannot turn it off. - Configuration scope: settings are now per-journal. Each journal has its own
required-roles list. No single site-wide configuration anymore.
Removed
- Role hierarchy logic and the visual cascade in the settings form.
- Per-journal enable/disable toggle for the plugin.
Upgrade notes
This is a major version with breaking changes to the configuration model.
On upgrade from 1.x:
- Existing site-wide settings in
site_settingsare not migrated automatically. - After upgrade, configure the required roles per journal via the Plugins panel
of each journal. - The plugin cannot be disabled; to opt a journal out of OTP for ordinary
roles, save its required-roles list empty.
See the README for the full rule set and examples,
and the CHANGELOG for the full history.