Bug 29894: Send a confirmation notice

When registering or deregistering, send a confirmation.

Test plan:
Register or deregister with patron having email address.
Verify that you got a confirmation mail.
Run t/db_dependent/Koha/Auth/TwoFactorAuth.t

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Fridolin Somers <fridolin.somers@biblibre.com>
This commit is contained in:
Marcel de Rooy 2022-01-21 07:58:45 +00:00 committed by Fridolin Somers
parent 0a1fc0f946
commit 279d9d62a3
4 changed files with 92 additions and 1 deletions

View file

@ -19,10 +19,15 @@ use Modern::Perl;
use GD::Barcode;
use MIME::Base64 qw( encode_base64 );
use C4::Letters;
use Koha::Exceptions;
use Koha::Exceptions::Patron;
use base qw( Auth::GoogleAuth );
use constant CONFIRM_NOTICE_REG => '2FA_REGISTER';
use constant CONFIRM_NOTICE_DEREG => '2FA_DEREGISTER';
=head1 NAME
Koha::Auth::TwoFactorAuth- Koha class deal with Two factor authentication
@ -33,7 +38,9 @@ use Koha::Auth::TwoFactorAuth;
my $secret = Koha::AuthUtils::generate_salt( 'weak', 16 );
my $auth = Koha::Auth::TwoFactorAuth->new({ patron => $patron, secret => $secret });
my $image_src = $auth->qr_code;
my $ok = $auth->verify( $pin_code, 1 );
$auth->send_confirm_notice({ patron => $patron });
It's based on Auth::GoogleAuth
@ -101,4 +108,42 @@ sub qr_code {
return "data:image/png;base64,". encode_base64( $data, q{} ); # does not contain newlines
}
=head3 send_confirm_notice
$auth->send_confirm_notice({ patron => $p, deregister => 1 });
Send a notice to confirm (de)registering 2FA.
Parameter patron is mandatory.
If there is no deregister param, a register notice is sent.
If the patron has no email address, we throw an exception.
=cut
sub send_confirm_notice {
my ( $self, $params ) = @_;
my $patron = $params->{patron};
my $deregister = $params->{deregister};
Koha::Exceptions::MissingParameter->throw("Mandatory patron parameter missing")
unless $patron && ref($patron) eq 'Koha::Patron';
Koha::Exceptions::Patron::MissingEmailAddress->throw
if !$patron->notice_email_address;
my $letter = C4::Letters::GetPreparedLetter (
module => 'members', # called patrons on interface
letter_code => $deregister ? CONFIRM_NOTICE_DEREG : CONFIRM_NOTICE_REG,
branchcode => $patron->branchcode,
lang => $patron->lang,
tables => {
'branches' => $patron->branchcode,
'borrowers' => $patron->id,
},
);
C4::Letters::EnqueueLetter({
letter => $letter,
borrowernumber => $patron->id,
message_transport_type => 'email',
}) or warn "Couldnt enqueue 2FA notice for patron ". $patron->id;
}
1;

View file

@ -8,6 +8,9 @@ use Exception::Class (
'Koha::Exceptions::Patron' => {
isa => 'Koha::Exception',
},
'Koha::Exceptions::Patron::MissingEmailAddress' => {
description => "Patron has no email address",
},
'Koha::Exceptions::Patron::FailedDelete' => {
isa => 'Koha::Exceptions::Patron',
description => "Deleting patron failed"

View file

@ -72,6 +72,9 @@ if ( $op eq 'register-2FA' ) {
$logged_in_user->secret($secret32);
$logged_in_user->auth_method('two-factor')->store;
$op = 'registered';
if( $logged_in_user->notice_email_address ) {
$auth->send_confirm_notice({ patron => $logged_in_user });
}
}
else {
$template->param( invalid_pin => 1, );
@ -97,8 +100,12 @@ if ( $op eq 'enable-2FA' ) {
elsif ( $op eq 'disable-2FA' ) {
output_and_exit( $cgi, $cookie, $template, 'wrong_csrf_token' )
unless Koha::Token->new->check_csrf($csrf_pars);
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 ) {
$auth->send_confirm_notice({ patron => $logged_in_user, deregister => 1 });
}
}
$template->param(

View file

@ -1,15 +1,21 @@
use Modern::Perl;
use Test::More tests => 2;
use Test::More tests => 3;
use Test::Exception;
use Test::MockModule;
use t::lib::Mocks;
use t::lib::TestBuilder;
use Koha::Database;
use Koha::Auth::TwoFactorAuth;
use Koha::Exceptions;
use Koha::Exceptions::Patron;
use Koha::Notice::Messages;
our $schema = Koha::Database->new->schema;
our $builder = t::lib::TestBuilder->new;
our $mocked_stuffer = Test::MockModule->new('Email::Stuffer');
$mocked_stuffer->mock( 'send_or_die', sub { warn 'I do not send mails now'; } );
subtest 'new' => sub {
plan tests => 10;
@ -79,3 +85,33 @@ subtest 'qr_code' => sub {
$schema->storage->txn_rollback;
};
subtest 'send_confirm_notice' => sub {
plan tests => 4;
$schema->storage->txn_begin;
t::lib::Mocks::mock_preference('TwoFactorAuthentication', 1);
my $patron = $builder->build_object({ class => 'Koha::Patrons' });
$patron->secret('you2wont2guess2it'); # this is base32 btw
$patron->auth_method('two-factor');
$patron->store;
my $auth = Koha::Auth::TwoFactorAuth->new({ patron => $patron });
# Trivial tests: no patron, no email
throws_ok { $auth->send_confirm_notice; }
'Koha::Exceptions::MissingParameter',
'Croaked on missing patron';
$patron->set({ email => undef, emailpro => undef, B_email => undef });
throws_ok { $auth->send_confirm_notice({ patron => $patron }) }
'Koha::Exceptions::Patron::MissingEmailAddress',
'Croaked on missing email';
$patron->email('noreply@doof.nl')->store;
$auth->send_confirm_notice({ patron => $patron });
is( Koha::Notice::Messages->search({ borrowernumber => $patron->id, letter_code => '2FA_REGISTER' })->count, 1, 'Found message' );
$auth->send_confirm_notice({ patron => $patron, deregister => 1 });
is( Koha::Notice::Messages->search({ borrowernumber => $patron->id, letter_code => '2FA_DEREGISTER' })->count, 1, 'Found message' );
$schema->storage->txn_rollback;
$mocked_stuffer->unmock;
};