Bugzilla – Attachment 184938 Details for
Bug 30724
Add ability for administrator to reset a users 2FA
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 30724: Allow superlibrarians to manage 2FA for other patrons
Bug-30724-Allow-superlibrarians-to-manage-2FA-for-.patch (text/plain), 9.25 KB, created by
Tomás Cohen Arazi (tcohen)
on 2025-07-31 17:20:49 UTC
(
hide
)
Description:
Bug 30724: Allow superlibrarians to manage 2FA for other patrons
Filename:
MIME Type:
Creator:
Tomás Cohen Arazi (tcohen)
Created:
2025-07-31 17:20:49 UTC
Size:
9.25 KB
patch
obsolete
>From 0d40ddc822fcf5936dbdbd6648e0eeb3b6173ecc Mon Sep 17 00:00:00 2001 >From: Tomas Cohen Arazi <tomascohen@theke.io> >Date: Thu, 31 Jul 2025 11:11:43 -0300 >Subject: [PATCH] Bug 30724: Allow superlibrarians to manage 2FA for other > patrons > >This enhances the two-factor authentication management interface to allow >superlibrarians to disable 2FA for other patrons when they lose access to >their authenticator device. > >Controller changes (members/two_factor_auth.pl): >* Accept borrowernumber parameter to select target patron >* Implement authorization checks (self-service or superlibrarian) >* Use proper HTTP status codes (403/404) for error conditions >* Update all patron operations to use selected patron >* Integrate with new reset_2fa() method for consistency >* Pass another_user flag to template for conditional display > >Template changes (two_factor_auth.tt): >* Use has_2fa_enabled() method instead of auth_method string comparison >* Prevent superlibrarians from enabling 2FA for other users >* Show explanatory message when 2FA setup is restricted >* Maintain proper conditional display logic > >UI Integration changes: >* Update members toolbar to show 2FA option for superlibrarians >* Pass borrowernumber parameter in all 2FA-related URLs >* Maintain context when canceling 2FA registration >* Use consistent parameter naming (borrowernumber vs patron_id) > >To test: >1. Enable TwoFactorAuthentication system preference >2. Set up 2FA for a test patron >3. As superlibrarian, visit patron details page >4. Click 'Manage two-factor authentication' in toolbar >=> SUCCESS: 2FA management page loads for the selected patron >5. Disable 2FA for the patron >=> SUCCESS: 2FA is disabled for the target patron, not the superlibrarian >6. Verify 'Enable 2FA' button is hidden with explanatory text >=> SUCCESS: Shows message that users must enable 2FA themselves >7. Test authorization: try accessing as non-superlibrarian for different patron >=> FAIL: Returns 403 Forbidden error >8. Sign off :-D >--- > .../prog/en/includes/auth-two-factor.inc | 2 +- > .../prog/en/includes/members-toolbar.inc | 4 +- > .../en/modules/members/two_factor_auth.tt | 16 +++--- > members/two_factor_auth.pl | 49 ++++++++++++------- > 4 files changed, 45 insertions(+), 26 deletions(-) > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/auth-two-factor.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/auth-two-factor.inc >index f7fe863c609..767f6c23556 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/auth-two-factor.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/auth-two-factor.inc >@@ -26,7 +26,7 @@ > </fieldset> > <fieldset class="action"> > <input id="register-2FA" class="btn btn-primary" type="submit" value="Register with two-factor app" /> >- <a class="cancel" href="/cgi-bin/koha/members/two_factor_auth.pl">Cancel</a> >+ <a class="cancel" href="/cgi-bin/koha/members/two_factor_auth.pl?borrowernumber=[% patron.borrowernumber | uri %]">Cancel</a> > </fieldset> > </div> > [% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/members-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/members-toolbar.inc >index c40f34ebceb..0d8499a350f 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/members-toolbar.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/members-toolbar.inc >@@ -93,8 +93,8 @@ > <a class="dropdown-item disabled" aria-disabled="true" id="patronflags" href="#">Set permissions</a> > </li> > [% END %] >- [% IF ( Koha.Preference('TwoFactorAuthentication') == 'enforced' || Koha.Preference('TwoFactorAuthentication') == 'enabled' ) && logged_in_user.borrowernumber == patron.borrowernumber %] >- <li><a class="dropdown-item" id="twofa" href="/cgi-bin/koha/members/two_factor_auth.pl">Manage two-factor authentication</a></li> >+ [% IF ( Koha.Preference('TwoFactorAuthentication') == 'enforced' || Koha.Preference('TwoFactorAuthentication') == 'enabled' ) && ( logged_in_user.borrowernumber == patron.borrowernumber || logged_in_user.is_superlibrarian ) %] >+ <li><a class="dropdown-item" id="twofa" href="/cgi-bin/koha/members/two_factor_auth.pl?borrowernumber=[% patron.borrowernumber | uri %]">Manage two-factor authentication</a></li> > [% END %] > > [% IF CAN_user_borrowers_edit_borrowers && useDischarge %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/two_factor_auth.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/two_factor_auth.tt >index 3359686effb..bbdcde441b1 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/two_factor_auth.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/two_factor_auth.tt >@@ -46,7 +46,7 @@ > [% PROCESS registration_form %] > > <div id="registration-status"> >- <div id="registration-status-enabled" [% IF patron.auth_method != "two-factor" %]style="display: none;"[% END %]> >+ <div id="registration-status-enabled" [% IF !patron.has_2fa_enabled %]style="display: none;"[% END %]> > <div class="alert alert-info two-factor-status">Status: Enabled</div> > > <form id="two-factor-auth" action="/cgi-bin/koha/members/two_factor_auth.pl" method="post"> >@@ -56,13 +56,17 @@ > </form> > </div> > >- <div id="registration-status-disabled" [% IF patron.auth_method != "password" %]style="display: none;"[% END %]> >+ <div id="registration-status-disabled" [% IF patron.has_2fa_enabled %]style="display: none;"[% END %]> > <div class="alert alert-info two-factor-status">Status: Disabled</div> >- [% IF Koha.Preference('TwoFactorAuthentication') == 'enforced' %] >- <div>Two-factor authentication is mandatory to login. If you do not enable now it will be asked at your next login.</div> >- [% END %] >+ [% IF another_user %] >+ <div>You cannot enable two-factor authentication for a user. They need to do it themselves.</div> >+ [% ELSE %] >+ [% IF Koha.Preference('TwoFactorAuthentication') == 'enforced' %] >+ <div>Two-factor authentication is mandatory to login. If you do not enable now it will be asked at your next login.</div> >+ [% END %] > >- <input id="enable-2FA" class="btn btn-primary" type="submit" value="Enable two-factor authentication" /> >+ <input id="enable-2FA" class="btn btn-primary" type="submit" value="Enable two-factor authentication" /> >+ [% END %] > </div> > </div> > [% END %] >diff --git a/members/two_factor_auth.pl b/members/two_factor_auth.pl >index 303440d9ae3..3c980e10f85 100755 >--- a/members/two_factor_auth.pl >+++ b/members/two_factor_auth.pl >@@ -42,33 +42,47 @@ if ( $TwoFactorAuthentication ne 'enabled' && $TwoFactorAuthentication ne 'enfor > exit; > } > >+my $op = $cgi->param('op') // ''; >+my $patron_id = $cgi->param('borrowernumber') // ''; >+ >+my $another_user = $patron_id ne $loggedinuser; >+ > my $logged_in_user = Koha::Patrons->find($loggedinuser); >-my $op = $cgi->param('op') // ''; >+ >+unless ( !$another_user || $logged_in_user->is_superlibrarian() ) { >+ print $cgi->redirect("/cgi-bin/koha/errors/403.pl"); >+ exit; >+} >+ >+my $patron = >+ $another_user >+ ? Koha::Patrons->find($patron_id) >+ : $logged_in_user; >+ >+if ( !$patron ) { >+ print $cgi->redirect("/cgi-bin/koha/errors/404.pl"); >+ exit; >+} > > if ( !C4::Context->config('encryption_key') ) { > $template->param( missing_key => 1 ); > } else { > >- my $csrf_pars = { >- session_id => scalar $cgi->cookie('CGISESSID'), >- token => scalar $cgi->param('csrf_token'), >- }; >- > if ( $op eq 'cud-disable-2FA' ) { >- my $auth = Koha::Auth::TwoFactorAuth->new( { patron => $logged_in_user } ); >- $logged_in_user->secret(undef); >- $logged_in_user->auth_method('password')->store; >- if ( $logged_in_user->notice_email_address ) { >- $logged_in_user->queue_notice( >+ >+ $patron->reset_2fa(); >+ >+ if ( $patron->notice_email_address ) { >+ $patron->queue_notice( > { > letter_params => { > module => 'members', > letter_code => '2FA_DISABLE', >- branchcode => $logged_in_user->branchcode, >- lang => $logged_in_user->lang, >+ branchcode => $patron->branchcode, >+ lang => $patron->lang, > tables => { >- branches => $logged_in_user->branchcode, >- borrowers => $logged_in_user->id >+ branches => $patron->branchcode, >+ borrowers => $patron->id > }, > }, > message_transports => ['email'], >@@ -79,8 +93,9 @@ if ( !C4::Context->config('encryption_key') ) { > } > > $template->param( >- patron => $logged_in_user, >- op => $op, >+ another_user => $another_user, >+ op => $op, >+ patron => $patron, > ); > > output_html_with_http_headers $cgi, $cookie, $template->output; >-- >2.50.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 30724
:
184938
|
184939
|
186235
|
186236
|
186237
|
186251
|
186252
|
186253