my $is_locked = $patron->account_locked
-Return true if the patron has reach the maximum number of login attempts (see pref FailedLoginAttempts).
+Return true if the patron has reached the maximum number of login attempts
+(see pref FailedLoginAttempts). If login_attempts is < 0, this is interpreted
+as an administrative lockout (independent of FailedLoginAttempts; see also
+Koha::Patron->lock).
Otherwise return false.
-If the pref is not set (empty string, null or 0), the feature is considered as disabled.
+If the pref is not set (empty string, null or 0), the feature is considered as
+disabled.
=cut
sub account_locked {
my ($self) = @_;
my $FailedLoginAttempts = C4::Context->preference('FailedLoginAttempts');
- return ( $FailedLoginAttempts
+ return 1 if $FailedLoginAttempts
and $self->login_attempts
- and $self->login_attempts >= $FailedLoginAttempts )? 1 : 0;
+ and $self->login_attempts >= $FailedLoginAttempts;
+ return 1 if ($self->login_attempts || 0) < 0; # administrative lockout
+ return 0;
}
=head3 can_see_patron_infos
ok(C4::Auth::checkpw_hash('password', $hash2), 'password validates with second hash');
subtest 'Check value of login_attempts in checkpw' => sub {
- plan tests => 6;
+ plan tests => 11;
t::lib::Mocks::mock_preference('FailedLoginAttempts', 3);
is( @test, 0, 'checkpw failed again and returns nothing now' );
$patron->discard_changes; # refresh
is( $patron->login_attempts, 3, 'Login attempts not increased anymore' );
+
+ # Administrative lockout cannot be undone?
+ # Pass the right password now (or: add a nice mock).
+ my $auth = Test::MockModule->new( 'C4::Auth' );
+ $auth->mock( 'checkpw_hash', sub { return 1; } ); # not for production :)
+ $patron->login_attempts(0)->store;
+ @test = checkpw( $dbh, $patron->userid, '123', undef, 'opac', 1 );
+ is( $test[0], 1, 'Build confidence in the mock' );
+ $patron->login_attempts(-1)->store;
+ is( $patron->account_locked, 1, 'Check administrative lockout' );
+ @test = checkpw( $dbh, $patron->userid, '123', undef, 'opac', 1 );
+ is( @test, 0, 'checkpw gave red' );
+ $patron->discard_changes; # refresh
+ is( $patron->login_attempts, -1, 'Still locked out' );
+ t::lib::Mocks::mock_preference('FailedLoginAttempts', ''); # disable
+ is( $patron->account_locked, 1, 'Check administrative lockout without pref' );
};
$schema->storage->txn_rollback;