Bug 27342: (QA follow-up) Fix test
[koha.git] / t / db_dependent / Log.t
1 #!/usr/bin/perl
2 #
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with Koha; if not, see <http://www.gnu.org/licenses>.
16
17 use Modern::Perl;
18 use Data::Dumper qw( Dumper );
19 use Test::More tests => 4;
20
21 use C4::Context;
22 use C4::Log qw( logaction cronlogaction );
23 use C4::Auth qw( checkpw );
24 use Koha::Database;
25 use Koha::ActionLogs;
26
27 use t::lib::Mocks qw/mock_preference/; # to mock CronjobLog
28 use t::lib::TestBuilder;
29
30 # Make sure we can rollback.
31 our $schema  = Koha::Database->new->schema;
32 $schema->storage->txn_begin;
33
34 subtest 'Existing tests' => sub {
35     plan tests => 3;
36
37     my $success;
38     eval {
39         # FIXME: are we sure there is an member number 1?
40         logaction("MEMBERS","MODIFY",1,"test operation");
41         $success = 1;
42     } or do {
43         diag($@);
44         $success = 0;
45     };
46     ok($success, "logaction seemed to work");
47
48     # We want numbers to be the same between runs.
49     Koha::ActionLogs->search->delete;
50
51     t::lib::Mocks::mock_preference('CronjobLog',0);
52     cronlogaction();
53     is(Koha::ActionLogs->search({ module => 'CRONJOBS' })->count,0,"Cronjob not logged as expected.");
54
55     t::lib::Mocks::mock_preference('CronjobLog',1);
56     cronlogaction();
57     is(Koha::ActionLogs->search({ module => 'CRONJOBS' })->count,1,"Cronjob logged as expected.");
58 };
59
60 subtest 'logaction(): interface is correctly logged' => sub {
61
62     plan tests => 4;
63
64     # No interface passed, using C4::Context->interface
65     Koha::ActionLogs->search->delete;
66     C4::Context->interface( 'commandline' );
67     logaction( "MEMBERS", "MODIFY", 1, "test operation");
68     my $log = Koha::ActionLogs->search->next;
69     is( $log->interface, 'commandline', 'Interface correctly deduced (commandline)');
70
71     # No interface passed, using C4::Context->interface
72     Koha::ActionLogs->search->delete;
73     C4::Context->interface( 'opac' );
74     logaction( "MEMBERS", "MODIFY", 1, "test operation");
75     $log = Koha::ActionLogs->search->next;
76     is( $log->interface, 'opac', 'Interface correctly deduced (opac)');
77
78     # Explicit interfaces
79     Koha::ActionLogs->search->delete;
80     C4::Context->interface( 'intranet' );
81     logaction( "MEMBERS", "MODIFY", 1, 'test info', 'intranet');
82     $log = Koha::ActionLogs->search->next;
83     is( $log->interface, 'intranet', 'Passed interface is respected (intranet)');
84
85     # Explicit interfaces
86     Koha::ActionLogs->search->delete;
87     C4::Context->interface( 'sip' );
88     logaction( "MEMBERS", "MODIFY", 1, 'test info', 'sip');
89     $log = Koha::ActionLogs->search->next;
90     is( $log->interface, 'sip', 'Passed interface is respected (sip)');
91 };
92
93 subtest 'GDPR logging' => sub {
94     plan tests => 6;
95
96     my $builder = t::lib::TestBuilder->new;
97     my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
98
99     t::lib::Mocks::mock_userenv({ patron => $patron });
100     logaction( 'AUTH', 'FAILURE', $patron->id, '', 'opac' );
101     my $logs = Koha::ActionLogs->search(
102         {
103             user   => $patron->id,
104             module => 'AUTH',
105             action => 'FAILURE',
106             object => $patron->id,
107         }
108     );
109     is( $logs->count, 1, 'We should find one auth failure' );
110
111     t::lib::Mocks::mock_preference('AuthFailureLog', 1);
112     my $strong_password = 'N0tStr0ngAnyM0reN0w:)';
113     $patron->set_password({ password => $strong_password });
114     my @ret = checkpw( $patron->userid, 'WrongPassword', undef, undef, 1);
115     is( $ret[0], 0, 'Authentication failed' );
116     # Look for auth failure but NOT on patron id, pass userid in info parameter
117     $logs = Koha::ActionLogs->search(
118         {
119             module => 'AUTH',
120             action => 'FAILURE',
121             info   => { -like => '%'.$patron->userid.'%' },
122         }
123     );
124     is( $logs->count, 1, 'We should find one auth failure with this userid' );
125     t::lib::Mocks::mock_preference('AuthFailureLog', 0);
126     @ret = checkpw( $patron->userid, 'WrongPassword', undef, undef, 1);
127     $logs = Koha::ActionLogs->search(
128         {
129             module => 'AUTH',
130             action => 'FAILURE',
131             info   => { -like => '%'.$patron->userid.'%' },
132         }
133     );
134     is( $logs->count, 1, 'Still only one failure with this userid' );
135     t::lib::Mocks::mock_preference('AuthSuccessLog', 1);
136     @ret = checkpw( $patron->userid, $strong_password, undef, undef, 1);
137     is( $ret[0], 1, 'Authentication succeeded' );
138     # Now we can look for patron id
139     $logs = Koha::ActionLogs->search(
140         {
141             user   => $patron->id,
142             module => 'AUTH',
143             action => 'SUCCESS',
144             object => $patron->id,
145         }
146     );
147
148     is( $logs->count, 1, 'We expect only one auth success line for this patron' );
149 };
150
151 subtest 'Reduce log size by unblessing Koha objects' => sub {
152     plan tests => 7;
153
154     my $builder = t::lib::TestBuilder->new;
155     my $item = $builder->build_sample_item;
156
157     logaction( 'MY_MODULE', 'TEST01', $item->itemnumber, $item, 'opac' );
158     my $str = Dumper($item->unblessed);
159     my $logs = Koha::ActionLogs->search({ module => 'MY_MODULE', action => 'TEST01', object => $item->itemnumber });
160     is( $logs->count, 1, 'Action found' );
161     is( length($logs->next->info), length($str), 'Length exactly identical' );
162
163     logaction( 'CATALOGUING', 'MODIFY', $item->itemnumber, $item, 'opac' );
164     $logs = Koha::ActionLogs->search({ module => 'CATALOGUING', action => 'MODIFY', object => $item->itemnumber });
165     is( substr($logs->next->info, 0, 5), 'item ', 'Prefix item' );
166     is( length($logs->reset->next->info), 5+length($str), 'Length + 5' );
167
168     my $hold = $builder->build_object({ class => 'Koha::Holds' });
169     logaction( 'MY_CIRC_MODULE', 'TEST', $item->itemnumber, $hold, 'opac' );
170     $logs = Koha::ActionLogs->search({ module => 'MY_CIRC_MODULE', action => 'TEST', object => $item->itemnumber });
171     is( length($logs->next->info), length( Dumper($hold->unblessed)), 'Length of dumped unblessed hold' );
172
173     logaction( 'MY_MODULE', 'TEST02', $item->itemnumber, [], 'opac' );
174     $logs = Koha::ActionLogs->search({ module => 'MY_MODULE', action => 'TEST02', object => $item->itemnumber });
175     like( $logs->next->info, qr/^ARRAY\(/, 'Dumped arrayref' );
176
177     logaction( 'MY_MODULE', 'TEST03', $item->itemnumber, $builder, 'opac' );
178     $logs = Koha::ActionLogs->search({ module => 'MY_MODULE', action => 'TEST03', object => $item->itemnumber });
179     like( $logs->next->info, qr/^t::lib::TestBuilder/, 'Dumped TestBuilder object' );
180 };
181
182 $schema->storage->txn_rollback;