@@ -, +, @@ them cookie) with a Patron that has no permissions. This Patron will be referred as "your patron" or "your borrowernumber" below. XXX with your borrowernumber) and check you receive correct data XXX with someone else's borrowernumber) and check you get a permission error. existing checkout id of your Patron) and check you receive correct data existing checkout id of some other Patron) and check you get a permission error. with existing checkout id of some other Patron. You should get a permission error. checkout id of checkout for your patron. You should get a permission error. the maximum number of renewals is reached (you should have a 403 error). YYY should be checkout id of checkout for your patron. --- Koha/REST/V1/Checkout.pm | 27 ++++++++++++---- t/db_dependent/api/v1/checkouts.t | 67 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 9 deletions(-) --- a/Koha/REST/V1/Checkout.pm +++ a/Koha/REST/V1/Checkout.pm @@ -20,6 +20,7 @@ use Modern::Perl; use Mojo::Base 'Mojolicious::Controller'; use C4::Auth qw( haspermission ); +use C4::Context; use C4::Circulation; use Koha::Issues; @@ -27,7 +28,8 @@ sub list { my ($c, $args, $cb) = @_; my $user = $c->stash('koha.user'); - unless ($user && haspermission($user->userid, { circulate => "circulate_remaining_permissions" })) { + unless ($user && ($user->borrowernumber == $c->param('borrowernumber') + || haspermission($user->userid, { circulate => "circulate_remaining_permissions" }))) { return $c->$cb({error => "You don't have the required permission"}, 403); } @@ -43,9 +45,6 @@ sub get { my ($c, $args, $cb) = @_; my $user = $c->stash('koha.user'); - unless ($user && haspermission($user->userid, { circulate => "circulate_remaining_permissions" })) { - return $c->$cb({error => "You don't have the required permission"}, 403); - } my $checkout_id = $args->{checkout_id}; my $checkout = Koha::Issues->find($checkout_id); @@ -56,6 +55,13 @@ sub get { }, 404); } + my $borrowernumber = $checkout->borrowernumber; + + unless ($user && ( $user->borrowernumber == $borrowernumber + || haspermission($user->userid, { circulate => "circulate_remaining_permissions" }))) { + return $c->$cb({error => "You don't have the required permission"}, 403); + } + return $c->$cb($checkout->unblessed, 200); } @@ -63,9 +69,6 @@ sub renew { my ($c, $args, $cb) = @_; my $user = $c->stash('koha.user'); - unless ($user && haspermission($user->userid, { circulate => "circulate_remaining_permissions" })) { - return $c->$cb({error => "You don't have the required permission"}, 403); - } my $checkout_id = $args->{checkout_id}; my $checkout = Koha::Issues->find($checkout_id); @@ -79,6 +82,16 @@ sub renew { my $borrowernumber = $checkout->borrowernumber; my $itemnumber = $checkout->itemnumber; + my $OpacRenewalAllowed; + if ($user->borrowernumber == $borrowernumber) { + $OpacRenewalAllowed = C4::Context->preference('OpacRenewalAllowed'); + } + + unless ($user && ($OpacRenewalAllowed + || haspermission($user->userid, { circulate => "circulate_remaining_permissions" }))) { + return $c->$cb({error => "You don't have the required permission"}, 403); + } + my ($can_renew, $error) = C4::Circulation::CanBookBeRenewed( $borrowernumber, $itemnumber); --- a/t/db_dependent/api/v1/checkouts.t +++ a/t/db_dependent/api/v1/checkouts.t @@ -17,9 +17,10 @@ use Modern::Perl; -use Test::More tests => 27; +use Test::More tests => 57; use Test::MockModule; use Test::Mojo; +use t::lib::Mocks; use t::lib::TestBuilder; use DateTime; @@ -59,8 +60,14 @@ $session->param('ip', '127.0.0.1'); $session->param('lasttime', time()); $session->flush; -my $borrower = $builder->build({ source => 'Borrower' }); +my $borrower = $builder->build({ source => 'Borrower', value => { flags => 0 } }); my $borrowernumber = $borrower->{borrowernumber}; +my $borrower_session = C4::Auth::get_session(''); +$borrower_session->param('number', $borrowernumber); +$borrower_session->param('id', $borrower->{ userid }); +$borrower_session->param('ip', '127.0.0.1'); +$borrower_session->param('lasttime', time()); +$borrower_session->flush; my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode }; my $module = new Test::MockModule('C4::Context'); @@ -82,12 +89,15 @@ $t->request_ok($tx) my $biblionumber = create_biblio('RESTful Web APIs'); my $itemnumber1 = create_item($biblionumber, 'TEST000001'); my $itemnumber2 = create_item($biblionumber, 'TEST000002'); +my $itemnumber3 = create_item($biblionumber, 'TEST000003'); my $date_due = DateTime->now->add(weeks => 2); my $issue1 = C4::Circulation::AddIssue($borrower, 'TEST000001', $date_due); my $date_due1 = Koha::DateUtils::dt_from_string( $issue1->date_due ); my $issue2 = C4::Circulation::AddIssue($borrower, 'TEST000002', $date_due); my $date_due2 = Koha::DateUtils::dt_from_string( $issue2->date_due ); +my $issue3 = C4::Circulation::AddIssue($loggedinuser, 'TEST000003', $date_due); +my $date_due3 = Koha::DateUtils::dt_from_string( $issue3->date_due ); $tx = $t->ua->build_tx(GET => "/api/v1/checkouts?borrowernumber=$borrowernumber"); $tx->req->cookies({name => 'CGISESSID', value => $session->id}); @@ -101,6 +111,39 @@ $t->request_ok($tx) ->json_is('/1/date_due' => $date_due2->ymd . ' ' . $date_due2->hms) ->json_hasnt('/2'); +$tx = $t->ua->build_tx(GET => "/api/v1/checkouts/".$issue3->issue_id); +$tx->req->cookies({name => 'CGISESSID', value => $borrower_session->id}); +$t->request_ok($tx) + ->status_is(403) + ->json_is({ error => "You don't have the required permission" }); + +$tx = $t->ua->build_tx(GET => "/api/v1/checkouts?borrowernumber=".$loggedinuser->{borrowernumber}); +$tx->req->cookies({name => 'CGISESSID', value => $borrower_session->id}); +$t->request_ok($tx) + ->status_is(403) + ->json_is({ error => "You don't have the required permission" }); + +$tx = $t->ua->build_tx(GET => "/api/v1/checkouts?borrowernumber=$borrowernumber"); +$tx->req->cookies({name => 'CGISESSID', value => $borrower_session->id}); +$t->request_ok($tx) + ->status_is(200) + ->json_is('/0/borrowernumber' => $borrowernumber) + ->json_is('/0/itemnumber' => $itemnumber1) + ->json_is('/0/date_due' => $date_due1->ymd . ' ' . $date_due1->hms) + ->json_is('/1/borrowernumber' => $borrowernumber) + ->json_is('/1/itemnumber' => $itemnumber2) + ->json_is('/1/date_due' => $date_due2->ymd . ' ' . $date_due2->hms) + ->json_hasnt('/2'); + +$tx = $t->ua->build_tx(GET => "/api/v1/checkouts/" . $issue1->issue_id); +$tx->req->cookies({name => 'CGISESSID', value => $borrower_session->id}); +$t->request_ok($tx) + ->status_is(200) + ->json_is('/borrowernumber' => $borrowernumber) + ->json_is('/itemnumber' => $itemnumber1) + ->json_is('/date_due' => $date_due1->ymd . ' ' . $date_due1->hms) + ->json_hasnt('/1'); + $tx = $t->ua->build_tx(GET => "/api/v1/checkouts/" . $issue1->issue_id); $tx->req->cookies({name => 'CGISESSID', value => $session->id}); $t->request_ok($tx) @@ -127,6 +170,26 @@ $t->request_ok($tx) ->status_is(200) ->json_is('/date_due' => $expected_datedue->ymd . ' ' . $expected_datedue->hms); +$tx = $t->ua->build_tx(PUT => "/api/v1/checkouts/" . $issue3->issue_id); +$tx->req->cookies({name => 'CGISESSID', value => $borrower_session->id}); +$t->request_ok($tx) + ->status_is(403) + ->json_is({ error => "You don't have the required permission" }); + +t::lib::Mocks::mock_preference( "OpacRenewalAllowed", 0 ); +$tx = $t->ua->build_tx(PUT => "/api/v1/checkouts/" . $issue2->issue_id); +$tx->req->cookies({name => 'CGISESSID', value => $borrower_session->id}); +$t->request_ok($tx) + ->status_is(403) + ->json_is({ error => "You don't have the required permission" }); + +t::lib::Mocks::mock_preference( "OpacRenewalAllowed", 1 ); +$tx = $t->ua->build_tx(PUT => "/api/v1/checkouts/" . $issue2->issue_id); +$tx->req->cookies({name => 'CGISESSID', value => $borrower_session->id}); +$t->request_ok($tx) + ->status_is(200) + ->json_is('/date_due' => $expected_datedue->ymd . ' ' . $expected_datedue->hms); + $tx = $t->ua->build_tx(PUT => "/api/v1/checkouts/" . $issue1->issue_id); $tx->req->cookies({name => 'CGISESSID', value => $session->id}); $t->request_ok($tx) --