From b0a570796cac5aadee22bcaeb1ab321c9bfc38da Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Tue, 19 Jul 2022 11:56:56 +0100 Subject: [PATCH] Bug 33146: Add public items lookup route This patch adds a /public equivilent to the item listing endpoint. This allows us to search for an item by it's external_id (barcode). Test plan 1. Apply patch 2. Perform a GET on /api/v1/public/items?external_id=some_barcode 3. Confirm that the above endpoint correctly returns items that should be visible in the OPAC Signed-off-by: Lucas Gass Signed-off-by: Tomas Cohen Arazi Signed-off-by: Nick Clemens Bug 33146: (QA follow-up) Do not delete all items in test Signed-off-by: Tomas Cohen Arazi Signed-off-by: Nick Clemens Bug 33146: Allow embedding expanded coded values Signed-off-by: Tomas Cohen Arazi Signed-off-by: Nick Clemens Bug 33146: (QA follow-up) Consistency with /biblios/:biblio_id/items Signed-off-by: Tomas Cohen Arazi Signed-off-by: Nick Clemens Bug 33146: (QA follow-up) Make sure public API enabled for tests Signed-off-by: Nick Clemens Signed-off-by: Tomas Cohen Arazi --- Koha/REST/V1/Items.pm | 26 +++++++++++++ api/v1/swagger/paths/biblios.yaml | 10 +++++ api/v1/swagger/paths/items.yaml | 61 +++++++++++++++++++++++++++++++ api/v1/swagger/swagger.yaml | 2 + t/db_dependent/api/v1/items.t | 35 +++++++++++------- 5 files changed, 121 insertions(+), 13 deletions(-) diff --git a/Koha/REST/V1/Items.pm b/Koha/REST/V1/Items.pm index 3f20e3a577..938ffcd659 100644 --- a/Koha/REST/V1/Items.pm +++ b/Koha/REST/V1/Items.pm @@ -58,6 +58,32 @@ sub list { }; } +=head3 list_public + +Controller function that handles listing Koha::Item objects available to the opac + +=cut + +sub list_public { + my $c = shift->openapi->valid_input or return; + + return try { + my $patron = $c->stash('koha.user'); + + my $items_set = + Koha::Items->filter_by_visible_in_opac( { patron => $patron } ); + my $items = $c->objects->search($items_set); + + return $c->render( + status => 200, + openapi => $items + ); + } + catch { + $c->unhandled_exception($_); + }; +} + =head3 get Controller function that handles retrieving a single Koha::Item diff --git a/api/v1/swagger/paths/biblios.yaml b/api/v1/swagger/paths/biblios.yaml index 8b7da78cb6..559e5a460b 100644 --- a/api/v1/swagger/paths/biblios.yaml +++ b/api/v1/swagger/paths/biblios.yaml @@ -525,6 +525,16 @@ - $ref: "../swagger.yaml#/parameters/q_param" - $ref: "../swagger.yaml#/parameters/q_body" - $ref: "../swagger.yaml#/parameters/q_header" + - name: x-koha-embed + in: header + required: false + description: Embed list sent as a request header + type: array + items: + type: string + enum: + - +strings + collectionFormat: csv consumes: - application/json produces: diff --git a/api/v1/swagger/paths/items.yaml b/api/v1/swagger/paths/items.yaml index a9c7ca43c5..ac8c313a14 100644 --- a/api/v1/swagger/paths/items.yaml +++ b/api/v1/swagger/paths/items.yaml @@ -396,3 +396,64 @@ x-koha-authorization: permissions: reserveforothers: place_holds +"/public/items": + get: + x-mojo-to: Items#list_public + operationId: listItemsPublic + tags: + - items + summary: List items publically visible + parameters: + - name: external_id + in: query + description: Search on the item's barcode + required: false + type: string + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/q_param" + - $ref: "../swagger.yaml#/parameters/q_body" + - $ref: "../swagger.yaml#/parameters/q_header" + - $ref: "../swagger.yaml#/parameters/request_id_header" + - name: x-koha-embed + in: header + required: false + description: Embed list sent as a request header + type: array + items: + type: string + enum: + - +strings + collectionFormat: csv + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: A list of item + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/item" + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index 6f7d6972ab..7d5e04f62d 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -291,6 +291,8 @@ paths: $ref: "./paths/patrons_password.yaml#/~1patrons~1{patron_id}~1password~1expiration_date" "/public/biblios/{biblio_id}": $ref: "./paths/biblios.yaml#/~1public~1biblios~1{biblio_id}" + "/public/items": + $ref: "./paths/items.yaml#/~1public~1items" "/public/biblios/{biblio_id}/items": $ref: "./paths/biblios.yaml#/~1public~1biblios~1{biblio_id}~1items" "/public/biblios/{biblio_id}/ratings": diff --git a/t/db_dependent/api/v1/items.t b/t/db_dependent/api/v1/items.t index 27a8566e1e..a4a6300652 100755 --- a/t/db_dependent/api/v1/items.t +++ b/t/db_dependent/api/v1/items.t @@ -27,6 +27,8 @@ use Test::Warn; use t::lib::TestBuilder; use t::lib::Mocks; +use Mojo::JSON qw(encode_json); + use C4::Auth; use Koha::Items; use Koha::Database; @@ -105,15 +107,17 @@ subtest 'list_public() tests' => sub { $schema->storage->txn_begin; - # Clean out all demo items - Koha::Items->delete(); + my $patron = $builder->build_object( { class => 'Koha::Patrons' } ); - my $patron = $builder->build_object({ class => 'Koha::Patrons' }); - my $mocked_category = Test::MockModule->new('Koha::Patron::Category'); my $exception = 1; - $mocked_category->mock( 'override_hidden_items', sub { - return $exception; - }); + + my $mocked_category = Test::MockModule->new('Koha::Patron::Category'); + $mocked_category->mock( + 'override_hidden_items', + sub { + return $exception; + } + ); my $password = 'thePassword123'; $patron->set_password( { password => $password, skip_validation => 1 } ); @@ -186,28 +190,33 @@ subtest 'list_public() tests' => sub { return $rules; }); + my $query = encode_json({ item_id => [ $item_1->id, $item_2->id, $item_3->id, $item_4->id, $item_5->id, $item_6->id ] }); + + t::lib::Mocks::mock_preference( 'RESTPublicAPI', 1 ); subtest 'anonymous access' => sub { plan tests => 21; + t::lib::Mocks::mock_preference( 'RESTPublicAnonymousRequests', 1 ); + t::lib::Mocks::mock_preference( 'hidelostitems', 0 ); - my $res = $t->get_ok( "/api/v1/public/items" )->status_is(200)->tx->res->json; + my $res = $t->get_ok( "/api/v1/public/items?q=" . $query )->status_is(200)->tx->res->json; is( scalar @{ $res }, 6, 'No rules set, hidelostitems unset, all items returned'); t::lib::Mocks::mock_preference( 'hidelostitems', 1 ); - $res = $t->get_ok( "/api/v1/public/items" )->status_is(200)->tx->res->json; + $res = $t->get_ok( "/api/v1/public/items?q=" . $query )->status_is(200)->tx->res->json; is( scalar @{ $res }, 3, 'No rules set, hidelostitems set, 3 items hidden'); t::lib::Mocks::mock_preference( 'hidelostitems', 0 ); $rules = { biblionumber => [ $biblio->biblionumber ] }; - $res = $t->get_ok( "/api/v1/public/items" )->status_is(200)->tx->res->json; + $res = $t->get_ok( "/api/v1/public/items?q=" . $query )->status_is(200)->tx->res->json; is( scalar @{ $res }, 0, 'Biblionumber rule set, hidelostitems unset, all items hidden'); $rules = { withdrawn => [ 1, 2 ] }; - $res = $t->get_ok( "/api/v1/public/items" )->status_is(200)->tx->res->json; + $res = $t->get_ok( "/api/v1/public/items?q=" . $query )->status_is(200)->tx->res->json; is( scalar @{ $res }, 4, 'Withdrawn rule set, hidelostitems unset, 2 items hidden'); $rules = { itype => [ $itype_1->itemtype ] }; - $res = $t->get_ok( "/api/v1/public/items" )->status_is(200)->tx->res->json; + $res = $t->get_ok( "/api/v1/public/items?q=" . $query )->status_is(200)->tx->res->json; is( scalar @{ $res }, 2, 'Itype rule set, hidelostitems unset, 4 items hidden'); $rules = { withdrawn => [ 1 ] }; @@ -228,7 +237,7 @@ subtest 'list_public() tests' => sub { t::lib::Mocks::mock_preference( 'hidelostitems', 1 ); $rules = { withdrawn => [ 1, 2 ] }; - my $res = $t->get_ok("//$userid:$password@/api/v1/public/items") + my $res = $t->get_ok("//$userid:$password@/api/v1/public/items?q=" . $query) ->status_is(200)->tx->res->json; is( scalar @{$res}, -- 2.39.5