Bug 35204: Add unit tests
[koha.git] / t / db_dependent / api / v1 / password_validation.t
1 #!/usr/bin/perl
2
3 #
4 # This file is part of Koha
5 #
6 # Koha is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # Koha is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with Koha; if not, see <http://www.gnu.org/licenses>.
18
19 use Modern::Perl;
20
21 use Test::More tests => 5;
22 use Test::Mojo;
23
24 use t::lib::TestBuilder;
25 use t::lib::Mocks;
26
27 use Koha::Database;
28 use Koha::DateUtils qw(dt_from_string);
29
30 my $schema  = Koha::Database->new->schema;
31 my $builder = t::lib::TestBuilder->new;
32
33 my $t = Test::Mojo->new('Koha::REST::V1');
34 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
35
36 $schema->storage->txn_begin;
37
38 # create a privileged user
39 my $librarian = $builder->build_object(
40     {
41         class => 'Koha::Patrons',
42         value => { flags => 2 ** 4 } # borrowers flag = 4
43     }
44 );
45 my $password = 'thePassword123';
46 $librarian->set_password( { password => $password, skip_validation => 1 } );
47 my $userid = $librarian->userid;
48
49 subtest 'password validation - account lock out' => sub {
50
51     plan tests => 6;
52
53     $schema->storage->txn_begin;
54
55     t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 1 );
56
57     my $json = {
58         identifier => $userid,
59         password   => "bad",
60     };
61
62     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
63       ->status_is(400)
64       ->json_is({ error => q{Validation failed} });
65
66     $json->{password} = $password;
67
68     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
69       ->status_is(400)
70       ->json_is({ error => q{Validation failed} });
71
72     $schema->storage->txn_rollback;
73 };
74
75 subtest 'password validation - unauthorized user' => sub {
76
77     plan tests => 3;
78
79     $schema->storage->txn_begin;
80
81     my $patron = $builder->build_object(
82         {
83             class => 'Koha::Patrons',
84             value => { flags => 2 ** 2 } # catalogue flag = 2
85         }
86     );
87     my $password = 'thePassword123';
88     $patron->set_password( { password => $password, skip_validation => 1 } );
89     my $userid = $patron->userid;
90
91     my $json = {
92         identifier => $userid,
93         password   => "test",
94     };
95
96     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
97       ->status_is(403)
98       ->json_is('/error' => 'Authorization failure. Missing required permission(s).');
99
100     $schema->storage->txn_rollback;
101 };
102
103 subtest 'password validation - unauthenticated user' => sub {
104     plan tests => 3;
105
106     $schema->storage->txn_begin;
107
108     my $json = {
109         identifier => "banana",
110         password   => "test",
111     };
112
113     $t->post_ok( "/api/v1/auth/password/validation" => json => $json )
114       ->json_is( '/error' => 'Authentication failure.' )
115       ->status_is(401);
116
117     $schema->storage->txn_rollback;
118 };
119
120 subtest 'Password validation - authorized requests tests' => sub {
121
122     plan tests => 24;
123
124     $schema->storage->txn_begin;
125
126     # generate a random unused userid
127     my $patron_to_delete = $builder->build_object( { class => 'Koha::Patrons' } );
128
129     my $deleted_userid     = $patron_to_delete->userid;
130     my $deleted_cardnumber = $patron_to_delete->cardnumber;
131
132     $patron_to_delete->delete;
133
134     my $json = {
135         identifier => $librarian->userid,
136         password   => $password,
137     };
138
139     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
140         ->status_is( 201, 'Validating using `cardnumber` works' )
141         ->json_is(
142         { cardnumber => $librarian->cardnumber, patron_id => $librarian->id, userid => $librarian->userid } );
143
144     $json = {
145         identifier => $librarian->cardnumber,
146         password   => $password,
147     };
148
149     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
150         ->status_is( 201, 'Validating using `cardnumber` works' )
151         ->json_is(
152         { cardnumber => $librarian->cardnumber, patron_id => $librarian->id, userid => $librarian->userid } );
153
154     $json = {
155         identifier => $deleted_cardnumber,
156         password   => $password,
157     };
158
159     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
160         ->status_is( 400, 'Validating using and invalid identifier fails' )
161         ->json_is( { error => 'Validation failed' } );
162
163     $json = {
164         identifier => $deleted_userid,
165         password   => $password,
166     };
167
168     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
169         ->status_is( 400, 'Validating using and invalid identifier fails' )
170         ->json_is( { error => 'Validation failed' } );
171
172     $json = {
173         password => $password,
174         userid   => $deleted_userid,
175     };
176
177     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
178         ->status_is( 400, 'Validating using and invalid userid fails' )->json_is( { error => 'Validation failed' } );
179
180     $json = {
181         password => $password,
182         userid   => $userid,
183     };
184
185     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
186         ->status_is( 201, 'Validating using the `userid` attribute works' )
187         ->json_is(
188         { cardnumber => $librarian->cardnumber, patron_id => $librarian->id, userid => $librarian->userid } );
189
190     $json = {
191         password => $password,
192         userid   => $librarian->cardnumber,
193     };
194
195     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
196         ->status_is( 400, 'Validating using a cardnumber as userid fails' )->json_is( { error => 'Validation failed' } );
197
198     $json = {
199         identifier => $userid,
200         password   => $password,
201         userid     => $userid,
202     };
203
204     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )
205         ->status_is( 400, 'Passing both parameters forbidden' )
206         ->json_is( { error => 'Bad request. Only one identifier attribute can be passed.' } );
207
208     $schema->storage->txn_rollback;
209 };
210
211 subtest 'password validation - expired password' => sub {
212
213     plan tests => 3;
214
215     $schema->storage->txn_begin;
216
217     my $patron = $builder->build_object(
218         {
219             class => 'Koha::Patrons',
220             value => { flags => 2**2 }    # catalogue flag = 2
221         }
222     );
223     my $patron_password = 'thePassword123';
224     $patron->set_password( { password => $patron_password, skip_validation => 1 } );
225
226     my $date            = dt_from_string();
227     my $expiration_date = $date->subtract( days => 1 );
228
229     $patron->password_expiration_date($expiration_date)->store;
230
231     my $json = {
232         identifier => $patron->userid,
233         password   => $patron_password,
234     };
235
236     $t->post_ok( "//$userid:$password@/api/v1/auth/password/validation" => json => $json )->status_is(400)
237         ->json_is( '/error' => 'Password expired' );
238
239     $schema->storage->txn_rollback;
240 };
241
242 $schema->storage->txn_rollback;