Line 0
Link Here
|
0 |
- |
1 |
#!/usr/bin/env 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, write to the Free Software Foundation, Inc., |
16 |
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
17 |
|
18 |
use Modern::Perl; |
19 |
|
20 |
use Test::More tests => 5; |
21 |
use Test::Mojo; |
22 |
use Test::Warn; |
23 |
|
24 |
use t::lib::TestBuilder; |
25 |
use t::lib::Mocks; |
26 |
|
27 |
use C4::Auth; |
28 |
use Koha::Libraries; |
29 |
use Koha::Database; |
30 |
|
31 |
my $schema = Koha::Database->new->schema; |
32 |
my $builder = t::lib::TestBuilder->new; |
33 |
|
34 |
# FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling |
35 |
# this affects the other REST api tests |
36 |
t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' ); |
37 |
|
38 |
my $remote_address = '127.0.0.1'; |
39 |
my $t = Test::Mojo->new('Koha::REST::V1'); |
40 |
|
41 |
subtest 'list() tests' => sub { |
42 |
plan tests => 8; |
43 |
|
44 |
$schema->storage->txn_begin; |
45 |
|
46 |
# Create test context |
47 |
my $library = $builder->build( { source => 'Branch' } ); |
48 |
my $another_library = { %$library }; # create a copy of $library but make |
49 |
delete $another_library->{branchcode}; # sure branchcode will be regenerated |
50 |
$another_library = $builder->build( |
51 |
{ source => 'Branch', value => $another_library } ); |
52 |
my ( $borrowernumber, $session_id ) = |
53 |
create_user_and_session( { authorized => 0 } ); |
54 |
|
55 |
## Authorized user tests |
56 |
my $count_of_libraries = Koha::Libraries->search->count; |
57 |
# Make sure we are returned with the correct amount of libraries |
58 |
my $tx = $t->ua->build_tx( GET => '/api/v1/libraries' ); |
59 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
60 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
61 |
$t->request_ok($tx) |
62 |
->status_is(200) |
63 |
->json_has('/'.($count_of_libraries-1).'/branchcode') |
64 |
->json_hasnt('/'.($count_of_libraries).'/branchcode'); |
65 |
|
66 |
subtest 'query parameters' => sub { |
67 |
my @fields = qw( |
68 |
branchname branchaddress1 branchaddress2 branchaddress3 |
69 |
branchzip branchcity branchstate branchcountry |
70 |
branchphone branchfax branchemail branchreplyto |
71 |
branchreturnpath branchurl issuing branchip |
72 |
branchprinter branchnotes opac_info |
73 |
); |
74 |
plan tests => scalar(@fields)*3; |
75 |
|
76 |
foreach my $field (@fields) { |
77 |
$tx = $t->ua->build_tx( GET => |
78 |
"/api/v1/libraries?$field=$library->{$field}" ); |
79 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
80 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
81 |
my $result = |
82 |
$t->request_ok($tx) |
83 |
->status_is(200) |
84 |
->json_has( [ $library, $another_library ] ); |
85 |
} |
86 |
}; |
87 |
|
88 |
# Warn on unsupported query parameter |
89 |
$tx = $t->ua->build_tx( GET => '/api/v1/libraries?library_blah=blah' ); |
90 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
91 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
92 |
$t->request_ok($tx) |
93 |
->status_is(400) |
94 |
->json_is( [{ path => '/query/library_blah', message => 'Malformed query string'}] ); |
95 |
|
96 |
$schema->storage->txn_rollback; |
97 |
}; |
98 |
|
99 |
subtest 'get() tests' => sub { |
100 |
|
101 |
plan tests => 6; |
102 |
|
103 |
$schema->storage->txn_begin; |
104 |
|
105 |
my $library = $builder->build( { source => 'Branch' } ); |
106 |
my ( $borrowernumber, $session_id ) = |
107 |
create_user_and_session( { authorized => 0 } ); |
108 |
|
109 |
my $tx = $t->ua->build_tx( GET => "/api/v1/libraries/" . $library->{branchcode} ); |
110 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
111 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
112 |
$t->request_ok($tx) |
113 |
->status_is(200) |
114 |
->json_is($library); |
115 |
|
116 |
my $non_existent_code = 'non_existent'.int(rand(10000)); |
117 |
$tx = $t->ua->build_tx( GET => "/api/v1/libraries/" . $non_existent_code ); |
118 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
119 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
120 |
$t->request_ok($tx) |
121 |
->status_is(404) |
122 |
->json_is( '/error' => 'Library not found' ); |
123 |
|
124 |
$schema->storage->txn_rollback; |
125 |
}; |
126 |
|
127 |
subtest 'add() tests' => sub { |
128 |
plan tests => 31; |
129 |
|
130 |
$schema->storage->txn_begin; |
131 |
|
132 |
my ( $unauthorized_borrowernumber, $unauthorized_session_id ) = |
133 |
create_user_and_session( { authorized => 0 } ); |
134 |
my ( $authorized_borrowernumber, $authorized_session_id ) = |
135 |
create_user_and_session( { authorized => 1 } ); |
136 |
my $library = { |
137 |
branchcode => "LIBRARYBR1", |
138 |
branchname => "Library Name", |
139 |
branchaddress1 => "Library Address1", |
140 |
branchaddress2 => "Library Address2", |
141 |
branchaddress3 => "Library Address3", |
142 |
branchzip => "Library Zipcode", |
143 |
branchcity => "Library City", |
144 |
branchstate => "Library State", |
145 |
branchcountry => "Library Country", |
146 |
branchphone => "Library Phone", |
147 |
branchfax => "Library Fax", |
148 |
branchemail => "Library Email", |
149 |
branchreplyto => "Library Reply-To", |
150 |
branchreturnpath => "Library Return-Path", |
151 |
branchurl => "http://library.url", |
152 |
issuing => undef, # unused in Koha |
153 |
branchip => "127.0.0.1", |
154 |
branchprinter => "Library Printer", # unused in Koha |
155 |
branchnotes => "Library Notes", |
156 |
opac_info => "<p>Library OPAC info</p>", |
157 |
}; |
158 |
|
159 |
# Unauthorized attempt to write |
160 |
my $tx = $t->ua->build_tx( POST => "/api/v1/libraries" => json => $library ); |
161 |
$tx->req->cookies( |
162 |
{ name => 'CGISESSID', value => $unauthorized_session_id } ); |
163 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
164 |
$t->request_ok($tx) |
165 |
->status_is(403); |
166 |
|
167 |
# Authorized attempt to write invalid data |
168 |
my $library_with_invalid_field = { %$library }; |
169 |
$library_with_invalid_field->{'branchinvalid'} = 'Library invalid'; |
170 |
|
171 |
$tx = $t->ua->build_tx( |
172 |
POST => "/api/v1/libraries" => json => $library_with_invalid_field ); |
173 |
$tx->req->cookies( |
174 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
175 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
176 |
$t->request_ok($tx) |
177 |
->status_is(400) |
178 |
->json_is( |
179 |
"/errors" => [ |
180 |
{ |
181 |
message => "Properties not allowed: branchinvalid.", |
182 |
path => "/body" |
183 |
} |
184 |
] |
185 |
); |
186 |
|
187 |
# Authorized attempt to write |
188 |
$tx = $t->ua->build_tx( POST => "/api/v1/libraries" => json => $library ); |
189 |
$tx->req->cookies( |
190 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
191 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
192 |
my $branchcode = $t->request_ok($tx) |
193 |
->status_is(201) |
194 |
->json_is( '/branchname' => $library->{branchname} ) |
195 |
->json_is( '/branchaddress1' => $library->{branchaddress1} ) |
196 |
->json_is( '/branchaddress2' => $library->{branchaddress2} ) |
197 |
->json_is( '/branchaddress3' => $library->{branchaddress3} ) |
198 |
->json_is( '/branchzip' => $library->{branchzip} ) |
199 |
->json_is( '/branchcity' => $library->{branchcity} ) |
200 |
->json_is( '/branchstate' => $library->{branchstate} ) |
201 |
->json_is( '/branchcountry' => $library->{branchcountry} ) |
202 |
->json_is( '/branchphone' => $library->{branchphone} ) |
203 |
->json_is( '/branchfax' => $library->{branchfax} ) |
204 |
->json_is( '/branchemail' => $library->{branchemail} ) |
205 |
->json_is( '/branchreplyto' => $library->{branchreplyto} ) |
206 |
->json_is( '/branchreturnpath' => $library->{branchreturnpath} ) |
207 |
->json_is( '/branchurl' => $library->{branchurl} ) |
208 |
->json_is( '/branchip' => $library->{branchip} ) |
209 |
->json_is( '/branchnotes' => $library->{branchnotes} ) |
210 |
->json_is( '/opac_info' => $library->{opac_info} ) |
211 |
->header_is(Location => "/api/v1/libraries/$library->{branchcode}") |
212 |
->tx->res->json->{branchcode}; |
213 |
|
214 |
# Authorized attempt to create with null id |
215 |
$library->{branchcode} = undef; |
216 |
$tx = $t->ua->build_tx( |
217 |
POST => "/api/v1/libraries" => json => $library ); |
218 |
$tx->req->cookies( |
219 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
220 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
221 |
$t->request_ok($tx) |
222 |
->status_is(400) |
223 |
->json_has('/errors'); |
224 |
|
225 |
# Authorized attempt to create with existing id |
226 |
$library->{branchcode} = $branchcode; |
227 |
$tx = $t->ua->build_tx( |
228 |
POST => "/api/v1/libraries" => json => $library ); |
229 |
$tx->req->cookies( |
230 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
231 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
232 |
$t->request_ok($tx) |
233 |
->status_is(400) |
234 |
->json_is('/error' => 'Library already exists'); |
235 |
|
236 |
$schema->storage->txn_rollback; |
237 |
}; |
238 |
|
239 |
subtest 'update() tests' => sub { |
240 |
plan tests => 13; |
241 |
|
242 |
$schema->storage->txn_begin; |
243 |
|
244 |
my ( $unauthorized_borrowernumber, $unauthorized_session_id ) = |
245 |
create_user_and_session( { authorized => 0 } ); |
246 |
my ( $authorized_borrowernumber, $authorized_session_id ) = |
247 |
create_user_and_session( { authorized => 1 } ); |
248 |
|
249 |
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; |
250 |
|
251 |
# Unauthorized attempt to update |
252 |
my $tx = $t->ua->build_tx( PUT => "/api/v1/libraries/$branchcode" |
253 |
=> json => { branchname => 'New unauthorized name change' } ); |
254 |
$tx->req->cookies( |
255 |
{ name => 'CGISESSID', value => $unauthorized_session_id } ); |
256 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
257 |
$t->request_ok($tx) |
258 |
->status_is(403); |
259 |
|
260 |
# Attempt partial update on a PUT |
261 |
my $library_with_missing_field = { |
262 |
branchaddress1 => "New library address", |
263 |
}; |
264 |
|
265 |
$tx = $t->ua->build_tx( PUT => "/api/v1/libraries/$branchcode" => |
266 |
json => $library_with_missing_field ); |
267 |
$tx->req->cookies( |
268 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
269 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
270 |
$t->request_ok($tx) |
271 |
->status_is(400) |
272 |
->json_has( "/errors" => |
273 |
[ { message => "Missing property.", path => "/body/branchaddress2" } ] |
274 |
); |
275 |
|
276 |
# Full object update on PUT |
277 |
my $library_with_updated_field = { |
278 |
branchcode => "LIBRARYBR2", |
279 |
branchname => "Library Name", |
280 |
branchaddress1 => "Library Address1", |
281 |
branchaddress2 => "Library Address2", |
282 |
branchaddress3 => "Library Address3", |
283 |
branchzip => "Library Zipcode", |
284 |
branchcity => "Library City", |
285 |
branchstate => "Library State", |
286 |
branchcountry => "Library Country", |
287 |
branchphone => "Library Phone", |
288 |
branchfax => "Library Fax", |
289 |
branchemail => "Library Email", |
290 |
branchreplyto => "Library Reply-To", |
291 |
branchreturnpath => "Library Return-Path", |
292 |
branchurl => "http://library.url", |
293 |
issuing => undef, # unused in Koha |
294 |
branchip => "127.0.0.1", |
295 |
branchprinter => "Library Printer", # unused in Koha |
296 |
branchnotes => "Library Notes", |
297 |
opac_info => "<p>Library OPAC info</p>", |
298 |
}; |
299 |
|
300 |
$tx = $t->ua->build_tx( |
301 |
PUT => "/api/v1/libraries/$branchcode" => json => $library_with_updated_field ); |
302 |
$tx->req->cookies( |
303 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
304 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
305 |
$t->request_ok($tx) |
306 |
->status_is(200) |
307 |
->json_is( '/branchname' => 'Library Name' ); |
308 |
|
309 |
# Authorized attempt to write invalid data |
310 |
my $library_with_invalid_field = { %$library_with_updated_field }; |
311 |
$library_with_invalid_field->{'branchinvalid'} = 'Library invalid'; |
312 |
|
313 |
$tx = $t->ua->build_tx( |
314 |
PUT => "/api/v1/libraries/$branchcode" => json => $library_with_invalid_field ); |
315 |
$tx->req->cookies( |
316 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
317 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
318 |
$t->request_ok($tx) |
319 |
->status_is(400) |
320 |
->json_is( |
321 |
"/errors" => [ |
322 |
{ |
323 |
message => "Properties not allowed: branchinvalid.", |
324 |
path => "/body" |
325 |
} |
326 |
] |
327 |
); |
328 |
|
329 |
my $non_existent_code = 'nope'.int(rand(10000)); |
330 |
$tx = |
331 |
$t->ua->build_tx( PUT => "/api/v1/libraries/$non_existent_code" => json => |
332 |
$library_with_updated_field ); |
333 |
$tx->req->cookies( |
334 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
335 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
336 |
$t->request_ok($tx) |
337 |
->status_is(404); |
338 |
|
339 |
$schema->storage->txn_rollback; |
340 |
}; |
341 |
|
342 |
subtest 'delete() tests' => sub { |
343 |
plan tests => 7; |
344 |
|
345 |
$schema->storage->txn_begin; |
346 |
|
347 |
my ( $unauthorized_borrowernumber, $unauthorized_session_id ) = |
348 |
create_user_and_session( { authorized => 0 } ); |
349 |
my ( $authorized_borrowernumber, $authorized_session_id ) = |
350 |
create_user_and_session( { authorized => 1 } ); |
351 |
|
352 |
my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode}; |
353 |
|
354 |
# Unauthorized attempt to delete |
355 |
my $tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" ); |
356 |
$tx->req->cookies( |
357 |
{ name => 'CGISESSID', value => $unauthorized_session_id } ); |
358 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
359 |
$t->request_ok($tx) |
360 |
->status_is(403); |
361 |
|
362 |
$tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" ); |
363 |
$tx->req->cookies( |
364 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
365 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
366 |
$t->request_ok($tx) |
367 |
->status_is(204) |
368 |
->content_is(''); |
369 |
|
370 |
$tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" ); |
371 |
$tx->req->cookies( |
372 |
{ name => 'CGISESSID', value => $authorized_session_id } ); |
373 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
374 |
$t->request_ok($tx) |
375 |
->status_is(404); |
376 |
|
377 |
$schema->storage->txn_rollback; |
378 |
}; |
379 |
|
380 |
sub create_user_and_session { |
381 |
|
382 |
my $args = shift; |
383 |
my $flags = ( $args->{authorized} ) ? $args->{authorized} : 0; |
384 |
my $dbh = C4::Context->dbh; |
385 |
|
386 |
my $user = $builder->build( |
387 |
{ |
388 |
source => 'Borrower', |
389 |
value => { |
390 |
flags => $flags |
391 |
} |
392 |
} |
393 |
); |
394 |
|
395 |
# Create a session for the authorized user |
396 |
my $session = C4::Auth::get_session(''); |
397 |
$session->param( 'number', $user->{borrowernumber} ); |
398 |
$session->param( 'id', $user->{userid} ); |
399 |
$session->param( 'ip', '127.0.0.1' ); |
400 |
$session->param( 'lasttime', time() ); |
401 |
$session->flush; |
402 |
|
403 |
if ( $args->{authorized} ) { |
404 |
$dbh->do( " |
405 |
INSERT INTO user_permissions (borrowernumber,module_bit,code) |
406 |
VALUES (?,3,'parameters_remaining_permissions')", undef, |
407 |
$user->{borrowernumber} ); |
408 |
} |
409 |
|
410 |
return ( $user->{borrowernumber}, $session->id ); |
411 |
} |
412 |
|
413 |
1; |