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 Sponsored-by: ByWater Solutions Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
parent
83ac70172b
commit
150c8c2487
|
|
@ -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 %]
|
||||
|
|
|
|||
|
|
@ -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 %]
|
||||
|
|
|
|||
|
|
@ -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 %]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue