3 # This file is part of Koha.
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
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.
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.
20 use Test::More tests => 5;
24 use t::lib::TestBuilder;
31 my $schema = Koha::Database->new->schema;
32 my $builder = t::lib::TestBuilder->new;
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' );
38 my $remote_address = '127.0.0.1';
39 my $t = Test::Mojo->new('Koha::REST::V1');
41 subtest 'list() tests' => sub {
44 $schema->storage->txn_begin;
47 my $library = $builder->build_object({ class => 'Koha::Libraries' });
48 my $another_library = $library->unblessed; # create a copy of $library but make
49 delete $another_library->{branchcode}; # sure branchcode will be regenerated
50 $another_library = $builder->build_object({ class => 'Koha::Libraries', value => $another_library });
51 my ( $borrowernumber, $session_id ) = create_user_and_session( { authorized => 1 } );
53 ## Authorized user tests
54 my $count_of_libraries = Koha::Libraries->search->count;
55 # Make sure we are returned with the correct amount of libraries
56 my $tx = $t->ua->build_tx( GET => '/api/v1/libraries' );
57 $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
58 $tx->req->env( { REMOTE_ADDR => $remote_address } );
60 ->status_is( 200, 'SWAGGER3.2.2' )
61 ->json_has('/'.($count_of_libraries-1).'/library_id')
62 ->json_hasnt('/'.($count_of_libraries).'/library_id');
64 subtest 'query parameters' => sub {
68 address1 => 'branchaddress1',
69 address2 => 'branchaddress2',
70 address3 => 'branchaddress3',
71 postal_code => 'branchzip',
73 state => 'branchstate',
74 country => 'branchcountry',
75 phone => 'branchphone',
77 email => 'branchemail',
78 reply_to_email => 'branchreplyto',
79 return_path_email => 'branchreturnpath',
82 notes => 'branchnotes',
83 opac_info => 'opac_info',
86 my $size = keys %{$fields};
88 plan tests => $size * 3;
90 foreach my $field ( keys %{$fields} ) {
91 my $model_field = $fields->{ $field };
92 $tx = $t->ua->build_tx( GET =>
93 "/api/v1/libraries?$field=" . $library->$model_field );
94 $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
95 $tx->req->env( { REMOTE_ADDR => $remote_address } );
99 ->json_has( [ $library, $another_library ] );
103 # Warn on unsupported query parameter
104 $tx = $t->ua->build_tx( GET => '/api/v1/libraries?library_blah=blah' );
105 $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
106 $tx->req->env( { REMOTE_ADDR => $remote_address } );
109 ->json_is( [{ path => '/query/library_blah', message => 'Malformed query string'}] );
111 $schema->storage->txn_rollback;
114 subtest 'get() tests' => sub {
118 $schema->storage->txn_begin;
120 my $library = $builder->build_object( { class => 'Koha::Libraries' } );
121 my ( $borrowernumber, $session_id ) =
122 create_user_and_session( { authorized => 1 } );
124 my $tx = $t->ua->build_tx( GET => "/api/v1/libraries/" . $library->branchcode );
125 $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
126 $tx->req->env( { REMOTE_ADDR => $remote_address } );
128 ->status_is( 200, 'SWAGGER3.2.2' )
129 ->json_is( '' => Koha::REST::V1::Library::_to_api( $library->TO_JSON ), 'SWAGGER3.3.2' );
131 my $non_existent_code = $library->branchcode;
134 $tx = $t->ua->build_tx( GET => "/api/v1/libraries/" . $non_existent_code );
135 $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
136 $tx->req->env( { REMOTE_ADDR => $remote_address } );
139 ->json_is( '/error' => 'Library not found' );
141 $schema->storage->txn_rollback;
144 subtest 'add() tests' => sub {
148 $schema->storage->txn_begin;
150 my ( $unauthorized_borrowernumber, $unauthorized_session_id ) =
151 create_user_and_session( { authorized => 0 } );
152 my ( $authorized_borrowernumber, $authorized_session_id ) =
153 create_user_and_session( { authorized => 1 } );
155 my $library_obj = $builder->build_object({ class => 'Koha::Libraries' });
156 my $library = Koha::REST::V1::Library::_to_api( $library_obj->TO_JSON );
157 $library_obj->delete;
159 # Unauthorized attempt to write
160 my $tx = $t->ua->build_tx( POST => "/api/v1/libraries" => json => $library );
162 { name => 'CGISESSID', value => $unauthorized_session_id } );
163 $tx->req->env( { REMOTE_ADDR => $remote_address } );
167 # Authorized attempt to write invalid data
168 my $library_with_invalid_field = { %$library };
169 $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
171 $tx = $t->ua->build_tx(
172 POST => "/api/v1/libraries" => json => $library_with_invalid_field );
174 { name => 'CGISESSID', value => $authorized_session_id } );
175 $tx->req->env( { REMOTE_ADDR => $remote_address } );
181 message => "Properties not allowed: branchinvalid.",
187 # Authorized attempt to write
188 $tx = $t->ua->build_tx( POST => "/api/v1/libraries" => json => $library );
190 { name => 'CGISESSID', value => $authorized_session_id } );
191 $tx->req->env( { REMOTE_ADDR => $remote_address } );
193 ->status_is( 201, 'SWAGGER3.2.1' )
194 ->json_is( '' => $library, 'SWAGGER3.3.1' )
195 ->header_is( Location => '/api/v1/libraries/' . $library->{library_id}, 'SWAGGER3.4.1' );
197 # save the library_id
198 my $library_id = $library->{library_id};
199 # Authorized attempt to create with null id
200 $library->{library_id} = undef;
201 $tx = $t->ua->build_tx(
202 POST => "/api/v1/libraries" => json => $library );
204 { name => 'CGISESSID', value => $authorized_session_id } );
205 $tx->req->env( { REMOTE_ADDR => $remote_address } );
208 ->json_has('/errors');
210 # Authorized attempt to create with existing id
211 $library->{library_id} = $library_id;
212 $tx = $t->ua->build_tx(
213 POST => "/api/v1/libraries" => json => $library );
215 { name => 'CGISESSID', value => $authorized_session_id } );
216 $tx->req->env( { REMOTE_ADDR => $remote_address } );
221 ->json_has( '/error' => "Fails when trying to add an existing library_id")
222 ->json_is( '/conflict', 'PRIMARY' ); } # WTF
223 qr/^DBD::mysql::st execute failed: Duplicate entry '(.*)' for key 'PRIMARY'/;
225 $schema->storage->txn_rollback;
228 subtest 'update() tests' => sub {
231 $schema->storage->txn_begin;
233 my ( $unauthorized_borrowernumber, $unauthorized_session_id ) =
234 create_user_and_session( { authorized => 0 } );
235 my ( $authorized_borrowernumber, $authorized_session_id ) =
236 create_user_and_session( { authorized => 1 } );
238 my $library = $builder->build_object({ class => 'Koha::Libraries' });
239 my $library_id = $library->branchcode;
241 # Unauthorized attempt to update
242 my $tx = $t->ua->build_tx( PUT => "/api/v1/libraries/$library_id"
243 => json => { branchname => 'New unauthorized name change' } );
245 { name => 'CGISESSID', value => $unauthorized_session_id } );
246 $tx->req->env( { REMOTE_ADDR => $remote_address } );
250 # Attempt partial update on a PUT
251 my $library_with_missing_field = {
252 address1 => "New library address",
255 $tx = $t->ua->build_tx( PUT => "/api/v1/libraries/$library_id" =>
256 json => $library_with_missing_field );
258 { name => 'CGISESSID', value => $authorized_session_id } );
259 $tx->req->env( { REMOTE_ADDR => $remote_address } );
262 ->json_has( "/errors" =>
263 [ { message => "Missing property.", path => "/body/address2" } ]
266 my $deleted_library = $builder->build_object( { class => 'Koha::Libraries' } );
267 my $library_with_updated_field = Koha::REST::V1::Library::_to_api( $deleted_library->TO_JSON );
268 $library_with_updated_field->{library_id} = $library_id;
269 $deleted_library->delete;
271 $tx = $t->ua->build_tx( PUT => "/api/v1/libraries/$library_id" => json => $library_with_updated_field );
272 $tx->req->cookies( { name => 'CGISESSID', value => $authorized_session_id } );
273 $tx->req->env( { REMOTE_ADDR => $remote_address } );
275 ->status_is(200, 'SWAGGER3.2.1')
276 ->json_is( '' => $library_with_updated_field, 'SWAGGER3.3.3' );
278 # Authorized attempt to write invalid data
279 my $library_with_invalid_field = { %$library_with_updated_field };
280 $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
282 $tx = $t->ua->build_tx(
283 PUT => "/api/v1/libraries/$library_id" => json => $library_with_invalid_field );
285 { name => 'CGISESSID', value => $authorized_session_id } );
286 $tx->req->env( { REMOTE_ADDR => $remote_address } );
292 message => "Properties not allowed: branchinvalid.",
298 my $non_existent_code = 'nope'.int(rand(10000));
300 $t->ua->build_tx( PUT => "/api/v1/libraries/$non_existent_code" => json =>
301 $library_with_updated_field );
303 { name => 'CGISESSID', value => $authorized_session_id } );
304 $tx->req->env( { REMOTE_ADDR => $remote_address } );
308 $schema->storage->txn_rollback;
311 subtest 'delete() tests' => sub {
314 $schema->storage->txn_begin;
316 my ( $unauthorized_borrowernumber, $unauthorized_session_id ) =
317 create_user_and_session( { authorized => 0 } );
318 my ( $authorized_borrowernumber, $authorized_session_id ) =
319 create_user_and_session( { authorized => 1 } );
321 my $branchcode = $builder->build( { source => 'Branch' } )->{branchcode};
323 # Unauthorized attempt to delete
324 my $tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" );
326 { name => 'CGISESSID', value => $unauthorized_session_id } );
327 $tx->req->env( { REMOTE_ADDR => $remote_address } );
331 $tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" );
333 { name => 'CGISESSID', value => $authorized_session_id } );
334 $tx->req->env( { REMOTE_ADDR => $remote_address } );
336 ->status_is(204, 'SWAGGER3.2.4')
337 ->content_is('', 'SWAGGER3.3.4');
339 $tx = $t->ua->build_tx( DELETE => "/api/v1/libraries/$branchcode" );
341 { name => 'CGISESSID', value => $authorized_session_id } );
342 $tx->req->env( { REMOTE_ADDR => $remote_address } );
346 $schema->storage->txn_rollback;
349 sub create_user_and_session {
352 my $flags = ( $args->{authorized} ) ? $args->{authorized} : 0;
353 my $dbh = C4::Context->dbh;
355 my $user = $builder->build(
357 source => 'Borrower',
364 # Create a session for the authorized user
365 my $session = C4::Auth::get_session('');
366 $session->param( 'number', $user->{borrowernumber} );
367 $session->param( 'id', $user->{userid} );
368 $session->param( 'ip', '127.0.0.1' );
369 $session->param( 'lasttime', time() );
372 if ( $args->{authorized} ) {
374 INSERT INTO user_permissions (borrowernumber,module_bit,code)
375 VALUES (?,3,'parameters_remaining_permissions')", undef,
376 $user->{borrowernumber} );
379 return ( $user->{borrowernumber}, $session->id );